오늘은 간단히 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. 내용
상보 필터는 각도를 계산할 때, 단순히, 자이로값(각속도값)만 적분(합산)하지 않는다. 가속도 센서값을 함께 고려해, 에러값을 보정한다. 이 내용을 수식으로 표현하면 다음과 같다.