1. 우분투 15.04 설치
2016.3 현재 우분투 15.04 버전 이미지가 릴리즈되었다. 이 버전에는 Ubuntu 15.04 with MATE Desktop, OpenCV 2.4.12.1, ROS Jade(Bare Bones), OpenNI 2.2, Libfreenect, Libfreenect2, Point Cloud Library 1.7.2, Arduino IDE 가 포함되어 있다.
이미지를 다운로드 받은 후, xz압축을 푼다. 그리고, Win32 Disk Imager를 이용해, img파일을 micro SD카드에 굽는다. 그리고, SD카드를 오드로이드에 넣고, 전원을 넣는다.
그럼, 다음과 같은 화면을 볼 수 있다(모니터가 딴곳에 가 있어, 프로젝터를 사용했다). 만약, 완전히 부팅되지 않고 중간에 계속 재부팅하는 문제가 있으면 전원이 아래 스펙인지 체크해 본다.
오늘은 간단히 FS-TH9X RF송수신기를 이용한, 서보모터 제어 방법을 간단히 알아보도록 하겠다.
1. 조립
조립은 매우 쉽다. 송신기는 다음 왼쪽 그림과 같이 생겼다. 수신기는 다음 오른쪽과 같이 작은 박스처럼 생겼다(적색 표시된 안테나가 달려 있다).
이 수신기는 아래와 같이 각 핀이 배터리 연결부를 제외하고는 8개 채널이 있다. 즉, 모터를 8개 별개로 제어할 수 있다.
전원을 수신기에 연결하기 위해 수신기의 BIND라고 표시된 채널의 3개의 핀에서, 신호핀을 제외한 양극+, 음극- 핀에 배터리를 다음과 같이 연결한다. 그리고, 서보 모터를, 채널 1과, 채널 3에 다음 그림과 같이 연결한다
2. 테스트
송신기 전원을 키고, 조정기를 좌우상하로 움직여 본다. 그럼, 이 동작에 따라, 서보모터가 원격으로 움직일 것이다.
동작 영상은 다음과 같다.
3. 결과
서보 모터와 같이, 모터를 제어할 수 있는 신호선이 있다면, 수신기에 직접 연결해서, 모터를 바로 제어할 수 있다. 만약, 신호선이 없는 DC 모터인 경우에는, 수신기에 입력되는 신호에 따라, DC모터에 PWD로 전압을 조정해 제어할 수 있는 회로를 덧붙여 연결해야 한다. 만약, 아두이노를 이용한다면, 이 회로는 간단히 프로그램으로 코딩하면 된다.
참고로, 수신기에서 특정 채널에 신호를 주면, 송신기의 신호선에 전압의 변화가 일어나게 된다. 이 전압의 변화는 송신기의 조작에 따라 전압이 올라가기도하고, 내려가기도 하는 데, 이를 이용해, 아두이노에서 전압의 변화에 따라, DC모터에 PWD제어를 하면 DC모터를 쉽게 제어할 수 있다.
참고 내용은 다음과 같다.
1. FS-TH9X 설정 방법
2. FS-TH9X
Turnigy 9X Configuration for Aux Channel Gimbal and Servo Control
3. 테스트
실제로 잘 동작되는 지 테스트해보자. 테스트에 사용한 태양전지는 한장에 2.7V를 출력하며, 많은 전류를 얻기 위해, 병렬로 결선하였다. 사용된 충전지는 니켈 카드뮴 배터리(N-270AA)로, 1.2V 두개를 직렬연결해, 2.4V로 만들었으며, 용량은 270mAh를 갖는다. 야외에서 태양전지를 소형 모터에 연결해 본다. 큰 문제 없으면, 다음과 같이 잘 동작한다.
충전지에 충전을 해 본다. 다음은 충전하기 전의 충전지 전압이다.
야외에서 충전을 해 본다. 회로 결선은 앞의 설명대로 연결한다.
야외에서 약 30분 정도 충전을 시킨다. 그리고, 다시 전압을 측정해 본다.
충전지와 소형모터를 연결해 본다. 다음과 같이 소형모터를 회전할 만한 전압과 전류가 있다는 것을 확인할 수 있다.
약 1분 정도 소형모터를 동작시킨 후, 전압을 다시 측정해 본다. 다음과 같이, 전압 소모가 일어났음을 알 수 있다.
LED를 연결해 본다. 다음과 같이 잘 동작한다.
4. 응용 사례
다음은 태양전지 기반 아두이노이다. 아두이노에 필요한 전류를 태양전지에서 충전된 충전지로 부터 얻는다.
실제로 에너지 절약 캠페인을 위해, 스마트 홈이란 주제로 전시한 메이커 페어 참가 프로젝트의 상세 내용은 다음 링크를 참고하길 바란다. 메이커 페어 때 작업한 스마트 홈 관련 디자인, 소스코드 및 관련 참고 자료가 포함되어 있다 (전체 구현 내용은 매우 많으므로, 이 글에서 제공하지 않는다).
1. 프로세싱 개요
프로세싱은 미디어아트에 많이 활용되는 저작 도구이다. Java기반으로 스크립트를 개발하여, 데이터를 가시화한다. 매우 많은 수의 라이브러리와 예제를 프로세싱 홈페이지 및 관련 사이트에서 제공한다. processing.js를 사용하면, 웹기반으로 동작한다.
2. 프로세싱 사용 사례
프로세싱으로 개발한 작품을 확인해 보자.
이와 같이 전문가적인 컴퓨터 그래픽스를 만들 수 있다.
3. 프로세싱 코딩
프로세싱을 이용해, 센서 데이터를 취득하고, 이를 가시화하는 다음 그림과 같은 데쉬보드를 개발해 본다.
센서 데이터는 serial 통신으로 부터 획득한다. 조도, 온도, 습도, 전류 센서를 아두이노에 연결하여, 초당 2회씩 데이터를 프로세싱으로 보낸다. 이를 가시화한다.
데이터베이스에 센서 데이터를 저장하는 원리를 간단히 보여주기 위해, sensor.txt, energy.txt 파일 두개를 사용하였다(물론, MySQL과 같은 DB를 사용할 수 있으나, 교육적 원리를 전달해 주면 충분하므로 작업이 쉬운 방법으로 처리한다). 아울러, 센서 저장 및 그래픽 출력 간격을 교육적 효과를 얻을 수 있도록 매우 짧게 설정하였다.
다음은 관련 주요 코드이다(bar chart, pie chart 및 building 그래픽은 소스에 포함하지 않았음. 앞의 링크 참고.).
/** * Smart home */ import java.util.Iterator; PFont font = createFont("Arial", 30, true); Chart[] charts = new Chart[2]; Bar[] bars = new Bar[2]; building[] buildingz; PApplet pg; void setup() { size(1024, 768, P3D); smooth(); noStroke(); colorMode(RGB); // colorMode(HSB, TWO_PI, 1, 1, 1); setup_arduino(); for(int i = 0; i < charts.length; i++) charts[i] = new Chart(); charts[0].initChart("Year", width * 0.8, height * 0.2, 180.0); charts[1].initChart("Month", width * 0.8, height * 0.5, 180.0); for(int i = 0; i < bars.length; i++) bars[i] = new Bar(); bars[0].initBar("Sensor", "sensor.txt", "sensor_data.txt", width * 0.05, height * 0.62, 400, 300); bars[1].initBar("Energy", "energy.txt", "energy_data.txt", width * 0.55, height * 0.62, 400, 300); initBuilding(); } void draw() { update_arduino(); background(230, 150, 30); textFont(font); String str = "Smart Home Dashboard"; fill(0); text(str, width / 2, 50); for(int i = 0; i < charts.length; i++) charts[i].drawChart(); for(int i = 0; i < bars.length; i++) bars[i].drawBar(); fill(32, 128, 32, 128); house(20, 300, 250, 150); fill(32, 128, 32, 196); house(220, 200, 320, 250); translate(90, -20); for(int a=0;a<buildingz.length;a++){ buildingz[a].dessine( ); } translate(0, 0); } void initBuilding() { buildingz = new building[0]; float decx = 270; float decy = 270; float bx = 270; for (int b = 0; b < 4; b++){ float mindy = 0; for (int a = 0; a < 4;a++){ float x = decx; float y = decy + mindy; new building(x, y); decx = decx - 76; mindy += 25; } decy = decy + 30; decx = bx + 30; bx = decx; } } void house(float x, float y, float W, float H) { noStroke(); rect(x, y, W, H); triangle(x, y, x + W / 2, y - H / 2, x + W, y); }
웹서버에 개발된 코드를 동작시키려면, 다음과 같이 시도해 본다.
1. 웹서버를 설치한다 (python 서버, locally).
2. processing.js 등을 다운로드 받는다.
3. index.html 파일을 다음과 같이 만든다. <html> <head> <title>Hello Web</title> <script src="processing.js"></script> </head> <body> <h1>Processing.js</h1> <p>web-based sketch:</p> <canvas data-processing-sources="your_processing-1.pde your_processing-2.pde ..."></canvas> </body> </html>
4. 웹서버를 실행한다.
5. chrome에서 localhost:8080을 입력한다.
만약, 프로세싱 스케치가 로딩되지 않아, 그래픽이 표시되지 않으면, 프로세싱 파일을 하나로 합쳐본다. 이렇게 해도 로딩이 잘 안되면, 다른 종류의 웹서버를 설치해 시도해 본다.
4. 아두이노 연결
아두이노에서는 센서 데이터를 취득하거나, 릴레이와 같은 액추에이터를 제어한다.
릴레이에는 5V LED가 연결되어 있어, 간단한 스마트 전등을 구현하고 있다.
에너지 소모 데이터는 전류센서로 부터 얻도록 되어 있다. 기타, 스마트 홈에서 가전기기 조절에 필요한 온도, 습도, 조도 센서도 아두이노와 연결한다.
이렇게 연결된 센서 데이터는 energy.txt, sensor.txt로 구분해 파일로 저장하고, 이 데이터를 정해진 시간 단위로 읽어, 앞의 프로세싱으로 코딩한 스마트 홈 데쉬보드에 컴퓨터 그래픽으로 출력한다. 이런 방식으로 스마트 홈의 기본적인 기능들을 만들고, 보기 쉬운 그래픽으로 표현하여, 에너지의 중요성에 대한 교육적인 효과를 전달한다.
아래 코드의 적색 부분에서 센서값을 프로세싱과 시리얼포트로 주고 받는다.
참고로, 아두이노에서 사용한 코드들은 앞의 압축파일 링크에서 '1.공부'폴더에 저장된 참고자료들을 사용해, 적절히 조합한 것이다.
상세 코드는 다음과 같다.
// include the library code: #include <LiquidCrystal.h> #include <DHT.h> // Relay pin const int relay_pin = 7; boolean relay_state = false; // Define measurement variables float amplitude_current; float effective_value; float effective_voltage = 230; // Set voltage to 230V (Europe) or 110V (US) float zero_sensor; // DHT instance #define DHTPIN 6 #define DHTTYPE DHT11 DHT dht(DHTPIN, DHTTYPE); // initialize the library with the numbers of the interface pins LiquidCrystal lcd(10, 11, 2, 8, 4, 9); // Variables to be exposed to the API int temperature; int humidity; int light; int effective_power; void setup() { // Start Serial Serial.begin(9600); // 115200); // set up the LCD's number of columns and rows: lcd.begin(16, 2); pinMode(relay_pin, OUTPUT); zero_sensor = getSensorValue(A1); } void loop() { // Measure from DHT temperature = dht.readTemperature(); // / 30.0; // 4.7k Ohm. Calibration factor. humidity = dht.readHumidity(); // / 20.0; // Measure light level float sensor_reading = analogRead(A0); light = sensor_reading / 1024*100; // Perform power measurement float sensor_value = getSensorValue(A1) - zero_sensor; // Convert to current. (ACS712T). http://arduinosensors.com/index.php/tag/allegro-acs712/ float sensor_voltage = sensor_value * 10.0 / 1023.0; amplitude_current = (sensor_voltage - 2.5) / 0.186; effective_value = amplitude_current / 1.414; effective_power = abs(effective_value * effective_voltage / 1000); String data; data = data + temperature + ", " + humidity + ", " + light + ", " + effective_power; Serial.println(data);
// If the light level is less than 50 %, switch the lights off if (light < 50) { digitalWrite(relay_pin, HIGH); relay_state = true; lcd.begin(16, 2); } else { digitalWrite(relay_pin, LOW); relay_state = false; lcd.begin(16, 2); } // Display temperature lcd.setCursor(0,0); lcd.print("T:"); lcd.print((int)temperature); lcd.print((char)223);
// Display humidity lcd.setCursor(0,1); lcd.print("H:"); lcd.print(humidity); lcd.print("%"); // Display light level lcd.setCursor(6,1); lcd.print("L:"); lcd.print(light); lcd.print("%"); delay(200); } // Get the reading from the current sensor float getSensorValue(int pin) { int sensorValue; float avgSensor = 0; int nb_measurements = 100; for (int i = 0; i < nb_measurements; i++) { sensorValue = analogRead(pin); avgSensor = avgSensor + float(sensorValue); } avgSensor = avgSensor / float(nb_measurements); return avgSensor; }
5. 마무리
프로세싱은 시리얼 장치, 센서, 카메라, 키텍트 등과 같은 다양한 입출력 장치 및 관련 라이브러리를 지원할 뿐만 아니라, javascript기반 node.js를 이용해, 웹 상에서 스마트폰 같은 다양한 장치를 통해, 작품을 렌더링할 수 있는 강력한 도구이다. 이를 잘 활용하면, 매력적인 그래픽스 영상을 개발할 수 있다.
MPU-6050 가속도와 자이로(각속도) 센서는 이론적으로는 각 값을 누적한다면, 거리와 각도를 알 수 있어야 한다. 하지만, 센서에 노이즈가 포함되어 있어, 누적하면 할 수록 참값과는 멀어져 버려, 발산해 버리고 만다. 그러므로, 노이즈를 필터링해, 에러를 제거해 주어야 한다. 이런 기법 중 유명한 것이, 상보 필터(Complementary Filter)와 칼만 필터(Kalman Filter)이다. 이 글에서는 상보 필터를 다룬다.
2. 내용
상보 필터는 각도를 계산할 때, 단순히, 자이로값(각속도값)만 적분(합산)하지 않는다. 가속도 센서값을 함께 고려해, 에러값을 보정한다. 이 내용을 수식으로 표현하면 다음과 같다.
이 글에서는 PID 제어에 대해서 정리한다. PID는 액추에이터, 자율주행 차량, 로봇, 센서값 보정 등에 필수적인 함수로 사용된다.
1. 개요
PID제어는 목표로한 물리량을 자연스럽게 수렴시키는 제어 방법이다. 우리는 PID제어를 본능적으로 사용하고 있다. 예를 들어, 차를 운전할 때, 차의 방향을 목표지점을 가늠하여, 좌우 회전을 적절히 하여, 원하는 목표까지 운전한다. 만약, 좌우회전을 너무 크게 한다면, 목표값보다 발산할 것이고, 너무 적게하면, 변화폭이 적어, 너무 늦게 목표값에 도달할 것이다. 다음 그림은 자율제어와 관련된 PID와 MPC (model-based predictive control) 방법을 보여준다.
PID제어는 자연스럽게 목표 물리량(속도, 방향, 온도 센서값 등)으로 수렴시킨다. 다음 영상은 이 내용을 보여준다.
PID는 목표값과 현재값의 차이인 에러값을 줄여주는 방향으로, 현재값을 보정한다. 에러값은 PID값으로 변환된 후, 현재값을 보정하는 데 사용한다. PID각 항목은 다음과 같은 의미를 가진다.
P: Proportinal(비례)
I: Integral(적분)
D: Differential(미분)
이 값들이 합해져서, 현재값을 보정하는 과정을 계속 반복해, 현재값이 목표로한 물리량으로 수렴하게 한다.
PID의 상세한 의미는 다음 영상을 참고한다.
PID각 항목에 대한 계수값(Gain값)은 물리량을 만들어 내는 액추에이터 종류에 따라 적절히 설정해야 한다. 이 값을 적절히 설정해야, 자연스럽게, 빠르게 목표치까지 수렴하도록 할 수 있다. PID를 계산하는 소스코드는 다음과 같다. 보면, 알겠지만, 매우 간단한다.
double calculate_PID(double reference_input, double feedback_input) { error = reference_input - feedback_input;// Compute the error error_sum = error_sum + error; // Compute the error sum proportional_output = proportional_gain * error;// Compute the proportional output integral_output = integral_gain*error_sum;// Compute the integral output derivative_output = derivative_gain * (error - errorPrev);// Compute the derivative output // Compute the pre-saturated output presaturated_output = proportional_output + integral_output + derivative_output; return presaturated_output; }
PID의 gain값을 설정하는 것에 따라서, 목표치까지 수렴하는 곡선 특성이 달라진다. 급하게 수렴할 수도 있고, 천천히 수렴할 수도 있다. 적절한 gain값을 계산하기 위해, 다음 수렴 곡선과 표 내용을 참고한다.
제어 동작
Kp 값
Ki 값
Kd 값
비례 제어
0.3~0.7 T/KL
0
0
PI 제어
0.35~0.6 T/KL
0.3~0.6 / KL
0
PID 제어
0.6~0.95 T/KL
0.6~0.7 / KL
0.3~0.45 T/K
gain값이 클때와 작을 때 수렴하는 곡선의 특성은 다음과 같다.
2. 개발
여기서는 아두이노로 액추에이터를 제어하는 방법을 정리한다. 우선, 아두이노로 모터를 PID 제어하는 방법을 아래 영상에서 확인해 보자.
아두이노 기반 PID제어 관련 소스는 다음 링크에서 확인할 수 있다. 라이브러리도 만들어져 있어, 간단히 함수만 사용하면 된다.
1. 개요
최근에는 많은 디자인을 GrabCAD같은 곳에서 다운로드 받아, 레이저커팅으로 재미있는 소품을 만들어 볼 수 있게 되었다. 본 글은 이와 같은 곳에서 모델을 다운로드하고, 레이저 커닝을 하는 것에 대한 내용을 간단히 다룬다.
2. 준비물
디자인을 위한 준비물은 다음과 같다.
오토캐드
라이노
스케치업
슬라이서 애드인
오토캐드는 2차원 모델링도구이며, 라이노나 스케치업은 3차원 모델링 도구이다. 보통, 오토캐드는 레이저 커닝 절단선을 다듬거나, 수정할 때 사용한다.
3. 레이저 커팅 순서
레이저 커팅 순서는 다음과 같다.
1. 3차원 모델링: 필수적인 단계는 아니다. 3차원 모델링을 하지 않고, 바로 2차원 절단면을 디자인해도 무방하다. 다만, 3차원적으로 형상이 복잡하다면, 3차원 모델링부터 해야 한다.
2. 3차원 모델링 단면 디자인: 3차원 모델링이 되어 있다면, 라이노나 애드인 도구를 이용해, 단면을 자동으로 추출할 수 있다.
3. 단면 디자인을 DXF파일로 변환: 레이저 커팅 기계는 커팅 데이터를 전송하는 소프트웨어가 있다. 그 레이저 커팅 구동 소프트웨어가 입력받는 대표적인 파일 포맷이 DXF파일 포맷이다. 오토데스크사가 개발한 산업계 표준 포맷이 DXF파일이므로, 오토캐드에서 손쉽게 편집할 수 있다.
4. DXF파일을 레이저 커팅 구동 소프트웨어에 Import
5. 레이저 커팅 레이어 편집: 입력된 DXF 도면 파일에는 절단해야할 선들, 레이저로 표시만 해야할 선들로 구분해야 한다. 또한, 절단선들도, 외곽 절단선과 내부 절단선을 구분해야 한다. 만약, 외부 절단선을 먼저 레이저 커팅하고, 내부 절단선을 그 이후에 레이저 커팅하면, 전체 절단면이 기계 바닥이 떨어질 수 있기 때문에, 내부 절단선을 레이저 커팅 못할 경우가 생긴다. 그러므로, 아래와 같은 순서로 절단선을 선택해, 레이어로 구분한다.
1) 내부 표시선 레이어
2) 내부 절단선 레이어
3) 외부 절단선 레이어
각 레이어의 레이저 출력을 조절해, 절단, 표시 수준으로 레이저 출력 및 속도를 설정한다.
6. 도면을 레이저 커팅 기계에 다운로드
7. 레이저 커팅 기계에 재료(MDF/아크릴 등) 적재
8. 레이저 커팅 기계 원점 설정
9. 레이저 커팅 기계가 커팅할 최대 프레임 영역 확인
10. 별 이상이 없다면, 레이저 커팅을 시작한다.
대부분의 레이저 커팅 기계는 이런 순서로 진행된다. 레이저 커팅시 불꽃은 매우 강하므로 장시간 바라보고 있지 말자. 당연하겠지만, 기계가 잘 동작되지 않는다고, 정지하지 않은 상태에서 손을 기계에 넣어서는 절대로 안된다.
4. 다운로드를 통한 레이저 커팅
여기서는, 간단한 집을 다운로드해서, 레이저 커팅을 해 본다. 다음 링크에서 작은 MDF 집을 다운로드 받는다.
http://cartonus.com/small-wooden-houses/
다운로드된 파일 압축을 풀어보면, *.ai 이 생성된다. Adobe 일러스터 프로그램에서 이 파일을 열고, dxf로 export한다. 그리고, 앞의 순서대로, dxf파일을 레이저 커팅 기계 구동용 소프트웨어를 이용해, 레이저 커팅을 한다.
만약, 집의 크기를 수정하려면, 오토캐드에서 scale이나 offset명령 등을 이용해, dxf 도면을 수정해야 한다. 이 경우, MDF 두께를 고려해 디자인한, MDF면끼리 접한 모서리 부분의 두께 부위가 달라질 수 있으므로, 주의해야 한다.
5. 3차원 모델 기반 레이저 커팅
육면체와 같은 단순한 3차원 모형은 라이노 등에서 단면 추출 등의 명령으로 손쉽게 2차원 DXF파일을 생성할 수 있다. 하지만, 복잡한 곡면 3차원 모형은 모델링 된 것을 얇게 절단해, 절단면 별로 DXF파일을 생성한 후, 이 DXF 도면을 각각 레이저 커팅해야 한다. 이 경우, 별도의 애드인 툴이 필요하다. 이와 관련해, 다음 영상을 참고한다.
6. 마무리
레이저 커팅을 이용하면, 매우 재미있는 공작품을 만들 수 있다. 그리 어렵지 않으니, 시도해 보길 바란다.