목차. 1. 아두이노의특징및종류설명 2. 아두이노소프트웨어설치및브레드보드이용하기 3. 라이브러리추가하기 4. 센서류 A. 근접물체감지하기 (QRD1114) B. 온도센서로온도감지하기 (TMP36) C. MPU-6050 이용각속도 / 가속도 / 온도측정하기 D. ADXL335를이용하여기울기측정하기 (ADXL335) E. Flex 센서를이용한구부림측정하기 (Flex 구부림센서 ) F. FSR 압력센서를이용한압력측정하기 (FSR 센서 ) G. 온도습도센서테스트 (DHT11) H. 인체감지센서모듈테스트하기 I. 초음파거리센서사용하기 (HC-SR04) J. 자기장센서를이용하여절대방향측정 (HMC5883L) K. 적외선거리센서 (Sharp GP2Y0A21YK) L. 초음파거리센서 (Maxbotix Sonar LV EZ1) M. RGB 컬러센서 (Parallax ColorPAL) 5. 디스플레이류 A. LED 깜빡이기 1
B. PWM을이용한 LED 밝기조절 C. 여러개 LED 동시에제어하기 D. 쉬프트레지스터 (74HC595) E. 16x2 LCD 제어하기 6. 액츄에이터류 A. 서보모터구동하기 B. H-Bridge를이용한 DC 모터방향제어하기 C. 스테핑모터제어하기 (EasyDriver) 7. 무선네트워크사용하기 A. Bluetooth B. Zigbee (XBee) AT 모드 C. Zigbee (XBee) API 모드로거리센싱 8. 입출력인터페이스 A. 시리얼모니터에텍스트출력하기 B. 키보드로문자입력받아아두이노에전송하기 C. 스위치사용하여 LED 컨트롤 D. 4x4 키패드이용하기 9. 응용편 A. 밝기에따른 DC 모터속도제어 B. 장애물감지후모터의방향제어 C. 손가락으로모터제어하기 D. 압력에따른 LED의밝기제어 2
E. 키보드로모터방향제어하기 F. Visual Studio Express C# 와아두이노인터페이스 G. 매틀랩을이용한센서값디스플레이 10. 관련테크닉강좌 A. 칼만필터의실제적사용 3
1. 아두이노의특징및종류설명특별히프로그래밍을많이해보지않은초보자분들도쉽게사용할수있는아두이노는하드웨어를설계한후, 프로그램을통해독립적으로작동할수있도록만들어주는통합개발환경이라고도불릴수있는데, 오픈소스를기반으로하여많은하드웨어가개발되었고, 많은예제가커뮤니티를통해공유된다는점이그장점중장점입니다. 하지만, 처음접하시는분들에게는이다양한종류의아두이노중어떤것을선택해서시작할지가고민이실수있습니다. 다음은현재 (2013년 3월 ) 를기준으로마켓에서구입할수있는아두이노제품을도표화한것이니참고해주세요. 보드프로세서동작 전압 클럭디지털 / 아날로그 / PWM/UART 포트수 플래시 메모리 Arduino ATmega328 5V 16MHz 14/6/6/1 32Kb Uno Arduino ATmega32U4 5V 16MHz 20/12/7/1 32Kb Leonardo Arduino Due AT91SAM3X8E (32bit ARM core) 3.3V 84MHz 54/12/12/4 512Kb Arduino ATmega2560 5V 16MHz 54/16/14/4 256Kb Mega 2560 Arduino ATmega2560 5V 16MHz 54/16/14/4 256Kb Mega ADK Arduino ATmega328 5V 16MHz 14/6/4/1 32Kb Ethernet 4
Arduino ATmega328 5V 16MHz 14/8/6/1 32Kb Mini LilyPad ATmega168V/ATm 2.7 8MHz 14//6/6/1 16Kb Arduino ega328v 5.5V LilyPad ATmega32u4 3.3V 8MHz 9/4/4/1 32Kb Arduino USB Arduino ATmega32u4 5V 16MHz 20/12/7/1 32Kb Micro Arduino ATmega328 5V 16MHz 14/8/6/1 32Kb Nano Arduino ATmega168 3.3V 8MHz 14/6/6/1 16Kb Pro Mini or 5V or 16MHz Arduino ATmega328 3.3V 8MHz 14/6/6/1 16Kb Pro or 5V or 16MHz Arduino ATmega328P 3.3V 8MHz 14/8/6/1 32Kb Fio 일반적으로사용하는목적이라면아두이노우노를추천할수있습니다. 그 이유는대부분의튜토리얼및예제소스가우노를기반으로되었고, 사용하는 사람들도가장많기때문에도움을쉽게얻을수있기때문입니다. 5
하지만, 다른보드또한목적에맞게유용하게사용될수있습니다. Arduino Leonardo는조이스틱혹은마우스처럼컴퓨터와의인터페이스혹은주변장치처럼사용하고자할때는유용하게사용할수있습니다. 이 Arduino Leonardo는가상시리얼포트로 PC와통신하므로 USB와시리얼통신이분리되어키보드와마우스의에뮬레이터로사용할수있습니다. Arduino Due 는 32bit ARM 프로세서를사용하여다른아두이노제품과 성능면에서월등한차이가납니다. 클럭수도 84MHz 이기에고성능을요하는비전 시스템등에유용하게사용될수있습니다. Arduino Mega2560은우노다음으로많이사용되는보드로서많은포트들이장점중의하나입니다. 우노를사용하시다가센서와액츄에이터를추가하다보면포트수가부족할수있는데, 이 Arduino Mega2560은많은포트를제공함으로써부족한포트수로인한불편함을줄일수있습니다. Arduino Mega ADK 는 USB 호스트컨트롤러와 Arduino Mega2560 을하나의 보드안에넣어서 Google ADK 와호환되도록만들었습니다. 이보드는 USB 호스트인터페이스를통해서안드로이드폰과연동할수있습니다. 6
2. [ 시작하기 ] 아두이노소프트웨어설치및브레드보드이용하기 아두이노소프트웨어다운로드아두이노소프트웨어는일반적으로스케치라고부르며이스케치는 arduino.cc/en/main/software 에서다운로드받으실수있습니다. 주소창에위의주소를입력하면다음과같이다운로드페이지가열린다. Windows, Mac OS X, Linux 등의플랫폼에맞는스케치를다운로드받으실수있으며, 이번매뉴얼은많은분들이사용하시는윈도우를기반으로작성되었기에윈도우용스케치를다운받도록하겠습니다. 아두이노스케치다운로드페이지 사용하는 OS 가윈도우가아니면, 위에서사용할플랫폼에맞게다운로드받으실수있습니다. 그리고다운로드받은플랫폼은저장하고싶은위치에저장하면됩니다. 아두이노스케치는별도의설치가필요없으며, 다음의아두이노아이콘을이용하여소프트웨어를실행할수있습니다. Mac 을사용한다면, 아두이노다운로드는디스크이미지 (.dmg) 로제공되며, 다운로드가완료된후 7
파일을두번클릭하면이미지가마운트되며설치할수있습니다. 리눅스는리눅스버전에따라달라지기때문에자세한정보는아두이노위키 (http://www.arduino.cc/playground/learning/linux) 를참조하거나메카솔루션의기술상담게시판을이용할수있습니다. 다운로드및설치가끝나고폴더를열어서아두이노아이콘을더블클릭하면다음과같이스케치가열리며처음에는시간이약간걸릴수있기때문에기다리도록합니다. 아두이노실행폴더 : 위의아이콘을더블클릭하면아두이노스케치가열립니다 8
아두이노스케치초기화면 아두이노소프트웨어를오픈하였을때보이는창입니다. 현재, 아두이노는 Arduino Pro Mini 로설정되어있고, 시리얼포트는 COM5 설정되어있음이 오른쪽하단에표기되어있습니다. 우리가사용할아두이노우노와적합한시리얼포트를설정하기위해아두이노우노드라이버가잘설치되었는지확인합니다. USB 로아두이노와컴퓨터연결만약, USB 를이용하여아두이노에연결하기전과연결한후의시리얼포트인식변화가없다면, 아두이노의드라이버가설치되어있지않은것입니다. 아두이노소프트웨어에서도구 > 시리얼포트를클릭하고, 만약, 회색톤으로시리얼포트가활성화되어있지않다면, 아두이노드라이버가연결되어있지않은것입니다. 또한, USB 를꼽았다가빼었다를하면서시리얼포트에변화가없다면이또한, 9
아두이노드라이버를인식하지못한것이기때문에, 아두이노드라이버를 매뉴얼로설정해줍니다. 시리얼포트가설정되지않은상황 : 드라이버를설치해야한다. 드라이버설치장치관리자에들어가기위해왼쪽아래에있는실행버튼을누르고프로그램및파일검색이라는조그만검색창에 devmgmt.msc 를입력하고검색합니다. 그럼, 다음과같은장치관리자가나타나게됩니다. 혹은시작버튼 제어판 시스템및보안 시스템 장치관리자를이용해서장치관리자에접근할수있고, 장치관리자가열리면다음과같이느낌표로드라이버설치를요구하는아두이노를발견할수있으며, 오른쪽마우스버튼을클릭하여드라이버소프트웨어업데이트를클릭합니다. 10
장치관리자화면과아두이노소프트웨어업데이트 드라이버소프트웨어업데이트 : 수동으로업데이트하기그후, 컴퓨터에서드라이버소프트웨어찾아보기를클릭하여수동으로검색을합니다. 찾아보기를클릭하여압축을푼아두이노폴더에들어가서 drivers 라는폴더를지정하고. 다음버튼을누르면드라이버가설치됩니다. 가령 C:\Arduino 에 다운받은아두이노를압축풀었다면 C:\Arduino\arduino-1.0.3\drivers 까지 설정하고설치를하면된다. 설치가되지않으면메카솔루션의기술상담으로 문의해주세요. 아두이노보드와시리얼포트설정 11
설치된아두이노에몇번의시리얼 (COM 포트 ) 이입력되어있는지확인하기 위해서 USB 를끼웠다빼었다하면도구 시리얼포트에변화가생기는것을볼수있습니다. 변화가있는시리얼포트가현재연결되어있는아두이노의시리얼포트입니다. 시리얼포트를클릭하여설정합니다. 브레드보드와익숙해지기. 일명빵판이라불리우는브레드보드는납땜없이테스팅을하기위해만들어져있습니다. 일반적인브레드보드는다음과같이연결되어있습니다. 브레드보드정면과내부케리커처 ( 출처 : SIK GUIDE, Sparkfun) 양쪽끝에있는파란색, 그리고빨간색의세로열은하나로연결되어있어서, VCC 및 GND 로사용되고, 가로열은일반적으로 5-6 개의핀을하나로연결시킴으로서 5-6 개의핀에연결된케이블및핀들이동일한신호를공유할수있도록해줍니다. 프로그램을아두이노에업로드 12
앞으로설명될예제및여러분들이작성한프로그램들은다음과같은절차를거쳐아두이노보드에업로드됩니다. 먼저, 1) 프로그램을작성혹은다운받고, 2) 프로그램을확인 (Verify) 를한후, 3) 프로그램을업로드 (Upload) 한다. 이세단계가아두이노에서가장중요한스텝입니다. 3. 라이브러리추가하기 13
아두이노의가장큰장점중하나는여러개발자가만들어놓은라이브러리가오픈되어있다는점입니다. 이라이브러리는각각의목적에맞는함수와명령어로구성되어있으며아두이노개발자들끼리공유를함으로써개발시간을단축시켜줍니다. 예컨대, 서보모터를구동하기위해서 servo 라이브러리를사용할수있고, 라이브러리가제공하는 servo.attach(), servo.write() 라는함수를이용하여쉽게서보모터를구동할수있습니다. 이번장에서는아두이노스케치에내장되어있지않은라이브러리를추가하는방법과사용하는방법에대하여알아보겠습니다. 즉, 다른사람이개발하여공유한라이브러리를다운로드받고, 다운로드받은라이브러리를적절한위치에저장하고불어옴으로써라이브러리를사용할준비를하도록합니다. 따라하기 : 문서혹은내문서폴더에들어가면 Arduino 폴더가있습니다. 실행파일이 있는곳이아닌문서로가도록합니다. Arduino 폴더안에있는 libraries 폴더안에다운받은 zip 파일을풀면 라이브러리설치가완료됩니다. 예를들어, 4x4 Keypad를사용하기위해서 Keypad.h 라는라이브러리를다운로드받기위해다음의링크로가셔서 Keypad.zip을다운받은후, 내문서의 Arduino-libararies에압축풀기를합니다. (http://playground.arduino.cc/code/keypad) 14
링크를따라가면다음의압축파일을다운로드받을수있습니다. 아두이노 IDE 를새로열게되면파일 - 예제에 Keypad 관련예제가포함되어있는 것을알수있고, 별도의프로그램을사용하여 Keypad.h 를사용하여도에러가발 생하지않음을확인할수있습니다. 15
4. A. 근접물체감지하기 (QRD1114) 근접물체를감지하기위해서는여러가지센서가사용될수있지만, 저렴하면서작은 QRD1114를이용하여근접센싱을할수있습니다. 이 QRD1114는적외선 LED와포토트렌지스터가작은모듈에구현이되어있는것으로적외선 LED로부터발광된빛이사물에반사되어돌아오는빛의세기를포토트렌지스터로측정함으로센싱을할수있도록설계되어있습니다. 준비물 : 아두이노우노, USB 케이블, QRD1114, 10k 옴저항, 220 옴저항, 브레드보드, 점퍼케이블 배경지식 : 1번과 2번으로구성되어있는것은포토트렌지스터이고, 3번과 4번으로구성되어있는것은적외선 LED입니다. 3번에서입력받은전원으로적외선 LED는발광하게되고, 사물에반사된적외선의세기를포토트렌지스터로센싱하게됩니다. 이때, 아두이노의디지털인풋은풀업저항에연결되어있기때문에사물이없을경우는센싱값이 HIGH(1) 을갖게되고, 물체가감지되었을경우에는값이 LOW(0) 을갖게된다. 시리얼모니터를이용하여확인할수있습니다. 따라하기 : 16
QRD1114 의 4 개의다리를브레드보드에꼽고저항을연결하여다음과 같이회로를구성합니다. 다음의프로그램을업로드합니다. int signal = 4; // 디지털핀 4 번으로센서값 (0 혹은 1) 을읽을변수. int onoff; // 4 번핀에서읽은값이 High(1) 인지 Low(0) 인지저장할변수 void setup() 17
Serial.begin(9600); // 시리얼통신을사용하여모니터링할수있다. void loop() onoff = digitalread(signal); // 불리언신호 (0 혹은 1) 을읽어서 onoff에저장 Serial.println(onoff); // onoff변수값을 Serial.println을통해출력. 업로드후에시리얼모니터를이용하여센싱되는값을시리얼모니터를통해확인해볼수있습니다. 시리얼모니터는스케치의오른쪽상단에있는아이콘을클릭하여볼수있습니다. 시리얼모니터링창이열리면센서를손으로막았다떼었다하면서값이 변하는것을체크해볼수있습니다. 18
4. B. 온도센서로온도감지하기 (TMP36) TMP36온도센서는 -40도에서 125도까지온도를측정할수있는센서로약 ±2도정도의정확도를가지고있습니다. 세개의다리가있는데평평한곳을정면으로가정할때, 왼쪽다리는입력전원, 오른쪽은 GND, 그리고가운데다리를이용하여온도를측정할수있습니다. 비교적간단한회로이지만, 핀방향을잘숙지하고회로를구성하도록하세요. 준비물 : 아두이노우노, USB 케이블, TMP36 온도센서, 브레드보드, 점퍼케이블 배경지식 : 일반적으로센서를사용하여실제적인물리량 (ex. 온도 ) 을측정하기위해서는변환공식이필요합니다. TMP36에인가해주는전원은 5V입니다. 그리고아두이노가센서로부터읽는방법은 analogread() 라는함수를이용합니다. 이 anlogread() 함수는센서로부터나오는아날로그전압값 (0~5V) 를디지털값으로변환하여읽게되는데그범위는 10bit, 즉 0에서 1023 사이의값입니다. 따라서 5V는 1023에매칭이되고, 5V/1024*analogRead를이용하여전원값을읽을수 19
있습니다. 그리고, 데이터시트에서기재된센서의특징에서전압과온도의관계를 생각할수있습니다. 위의표에서사용된 TMP36 을보면 Offset Voltage(V) 는 0.5 이고, Output Voltage Scaling 은 0.01V/C 입니다. 즉, 1 도에 0.01V 씩증가한다는의미죠. V( 전압 ) 과 C( 온도 ) 와의관계를생각해보면, V = 0.01*C + 0.5 가되고, 이를온도에 대하여다시풀면, C = 100*(V 0.5) 가됩니다. 따라하기 : TMP36 의가운데신호다리를아날로그 0 번에연결하고전원과 GND 를 아두이노에다음과같이연결합니다. 20
다음의프로그램을업로드하고시리얼모니터를통해온도의변화를 측정해봅니다. int temperaturepin = 0; float V; float C; void setup() Serial.begin(9600); void loop() int reading = analogread(temperaturepin); V = reading * 5; 21
V = V/1024; C = 100*(V - 0.5); Serial.print("voltage: "); Serial.print(V); Serial.print(" deg: "); Serial.print(C); delay(1000); 22
4. C. MPU-6050 을이용하여각속도 / 가속도 / 온도측정하기 MPU-6050은 9축모션퓨전알고리즘을지원하는가속도, 자이로센서보드로서디지털로출력되는온도센서기능도가지고있습니다. I2C라는통신프로토콜을이용하여다수의센서데이터들을소수의핀을이용하여수집할수있도록합니다. MPU-6050 지금까지다루었던센서들은아날로그핀을이용하여값을읽었습니다. 이번에 다룰 MPU-6050 은아날로그핀이아닌두개의디지털핀을이용하여 3 축각속도, 3 축가속도, 그리고온도를측정할수있습니다. 준비물 : 아두이노우노, USB 케이블, MPU-6050, 브레드보드, 점퍼케이블 배경지식 : I2C(Inter-Integrated Circuit) 는저속의주변기기간 SCL(serial clock) 과 SDA(serial data) 2개의커넥션을가지고있습니다. 표준아두이노보드는클럭시그널을제공하는 SCL을위해아날로그핀 5을사용하고데이터전송을위한 SDA을위해서는아날로그핀 4을사용합니다. (Mega는 SDA는디지털핀 20 그리고 23
SCL 은핀 21 을사용한다.) 따라서, MPU-6050 의 SCL 은아두이노의 A5, SDA 는 아두이노의 A4 를사용합니다. 따라하기 : 아두이노의 3.3V, GND, A4, A5 를 MPU-6050 의 VCC, GND, SDA, SCL 에각각 연결합니다. 다음의프로그램을업로드하고시리얼모니터링을통해값을확인합니다. #include <Wire.h> #define MPU6050_ACCEL_XOUT_H 0x3B // R #define MPU6050_PWR_MGMT_1 0x6B // R/W #define MPU6050_PWR_MGMT_2 0x6C // R/W #define MPU6050_WHO_AM_I 0x75 // R #define MPU6050_I2C_ADDRESS 0x68 typedef union accel_t_gyro_union 24
; struct uint8_t x_accel_h; uint8_t x_accel_l; uint8_t y_accel_h; uint8_t y_accel_l; uint8_t z_accel_h; uint8_t z_accel_l; uint8_t t_h; uint8_t t_l; uint8_t x_gyro_h; uint8_t x_gyro_l; uint8_t y_gyro_h; uint8_t y_gyro_l; uint8_t z_gyro_h; uint8_t z_gyro_l; reg; struct int x_accel; int y_accel; int z_accel; int temperature; int x_gyro; int y_gyro; int z_gyro; value; void setup() 25
int error; uint8_t c; Serial.begin(9600); Wire.begin(); // default at power-up: // Gyro at 250 degrees second // Acceleration at 2g // Clock source at internal 8MHz // The device is in sleep mode. // error = MPU6050_read (MPU6050_WHO_AM_I, &c, 1); Serial.print(F("WHO_AM_I : ")); Serial.print(c,HEX); Serial.print(F(", error = ")); Serial.println(error,DEC); // According to the datasheet, the 'sleep' bit // should read a '1'. But I read a '0'. // That bit has to be cleared, since the sensor // is in sleep mode at power-up. Even if the // bit reads '0'. error = MPU6050_read (MPU6050_PWR_MGMT_2, &c, 1); Serial.print(F("PWR_MGMT_2 : ")); Serial.print(c,HEX); Serial.print(F(", error = ")); Serial.println(error,DEC); 26
// Clear the 'sleep' bit to start the sensor. MPU6050_write_reg (MPU6050_PWR_MGMT_1, 0); void loop() int error; double dt; accel_t_gyro_union accel_t_gyro; Serial.println(F("")); Serial.println(F("MPU-6050")); // Read the raw values. // Read 14 bytes at once, // containing acceleration, temperature and gyro. // With the default settings of the MPU-6050, // there is no filter enabled, and the values // are not very stable. error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *) &accel_t_gyro, sizeof(accel_t_gyro)); Serial.print(F("Read accel, temp and gyro, error = ")); Serial.println(error,DEC); // Swap all high and low bytes. // After this, the registers values are swapped, // so the structure name like x_accel_l does no // longer contain the lower byte. uint8_t swap; 27
#define SWAP(x,y) swap = x; x = y; y = swap SWAP (accel_t_gyro.reg.x_accel_h, accel_t_gyro.reg.x_accel_l); SWAP (accel_t_gyro.reg.y_accel_h, accel_t_gyro.reg.y_accel_l); SWAP (accel_t_gyro.reg.z_accel_h, accel_t_gyro.reg.z_accel_l); SWAP (accel_t_gyro.reg.t_h, accel_t_gyro.reg.t_l); SWAP (accel_t_gyro.reg.x_gyro_h, accel_t_gyro.reg.x_gyro_l); SWAP (accel_t_gyro.reg.y_gyro_h, accel_t_gyro.reg.y_gyro_l); SWAP (accel_t_gyro.reg.z_gyro_h, accel_t_gyro.reg.z_gyro_l); // Print the raw acceleration values Serial.print(F("accel x,y,z: ")); Serial.print(accel_t_gyro.value.x_accel, DEC); Serial.print(F(", ")); Serial.print(accel_t_gyro.value.y_accel, DEC); Serial.print(F(", ")); Serial.print(accel_t_gyro.value.z_accel, DEC); Serial.println(F("")); // The temperature sensor is -40 to +85 degrees Celsius. // It is a signed integer. // According to the datasheet: // 340 per degrees Celsius, -512 at 35 degrees. // At 0 degrees: -512 - (340 * 35) = -12412 Serial.print(F("temperature: ")); dt = ( (double) accel_t_gyro.value.temperature + 12412.0) / 340.0; Serial.print(dT, 3); Serial.print(F(" degrees Celsius")); Serial.println(F("")); 28
// Print the raw gyro values. Serial.print(F("gyro x,y,z : ")); Serial.print(accel_t_gyro.value.x_gyro, DEC); Serial.print(F(", ")); Serial.print(accel_t_gyro.value.y_gyro, DEC); Serial.print(F(", ")); Serial.print(accel_t_gyro.value.z_gyro, DEC); Serial.print(F(", ")); Serial.println(F("")); delay(500); int MPU6050_read(int start, uint8_t *buffer, int size) int i, n, error; Wire.beginTransmission(MPU6050_I2C_ADDRESS); n = Wire.write(start); if (n!= 1) return (-10); n = Wire.endTransmission(false); if (n!= 0) return (n); // hold the I2C-bus // Third parameter is true: relase I2C-bus after data is read. Wire.requestFrom(MPU6050_I2C_ADDRESS, size, true); i = 0; 29
while(wire.available() && i<size) buffer[i++]=wire.read(); if ( i!= size) return (-11); return (0); // return : no error int MPU6050_write(int start, const uint8_t *pdata, int size) int n, error; Wire.beginTransmission(MPU6050_I2C_ADDRESS); n = Wire.write(start); // write the start address if (n!= 1) return (-20); n = Wire.write(pData, size); // write data bytes if (n!= size) return (-21); error = Wire.endTransmission(true); // release the I2C-bus if (error!= 0) return (error); return (0); // return : no error int MPU6050_write_reg(int reg, uint8_t data) 30
int error; error = MPU6050_write(reg, &data, 1); return (error); 아래보이는시리얼모니터링의창처럼, error = 0 이고, 3 축의가속도, 온도, 그리고 3 축의자이로값이출력되는것을확인할수있습니다. 31
4. D. ADXL335 를이용하여기울기측정하기 가속도센서를이용하여각도를측정할수있습니다. ADXL335의 X, Y, Z핀을아두이노의 A1, A2, A3에각각연결하고 GND는 GND, ADXL335의 VCC는아두이노의 3V3과 AREF에연결합니다. 아날로그신호를읽게되는데 AREF에 3.3V를공급함으로써보다정확한레퍼런스전압을이용하여신호값을읽을수있습니다. // these constants describe the pins. They won't change: const int xpin = A1; // x-axis of the accelerometer const int ypin = A2; // y-axis 32
const int zpin = A3; // z-axis (only on 3-axis models) int sampledelay = 500; //number of milliseconds between readings void setup() // initialize the serial communications: Serial.begin(9600); //Make sure the analog-to-digital converter takes its reference voltage from // the AREF pin analogreference(external); pinmode(xpin, INPUT); pinmode(ypin, INPUT); pinmode(zpin, INPUT); void loop() int x = analogread(xpin); //add a small delay between pin readings. I read that you should //do this but haven't tested the importance delay(1); int y = analogread(ypin); //add a small delay between pin readings. I read that you should //do this but haven't tested the importance delay(1); 33
int z = analogread(zpin); //zero_g is the reading we expect from the sensor when it detects //no acceleration. Subtract this value from the sensor reading to //get a shifted sensor reading. float zero_g = 512.0; //scale is the number of units we expect the sensor reading to //change when the acceleration along an axis changes by 1G. //Divide the shifted sensor reading by scale to get acceleration in Gs. float scale = 102.3; Serial.print(((float)x - zero_g)/scale); Serial.print("\t"); Serial.print(((float)y - zero_g)/scale); Serial.print("\t"); Serial.print(((float)z - zero_g)/scale); Serial.print("\n"); // delay before next reading: delay(sampledelay); 34
4. E. Flex 센서를이용한구부림측정하기 웨어러블수트가등장하면서각광받은 Flex 휨센서는구부러진정도를측정할수 있는센서입니다. FSR 압력센서와마찬가지로저항의일종인 Flex 휨센서는 구부러진정도에따라저항값이바뀌는특징을이용합니다. 준비물 : 아두이노우노, USB 케이블, 10k 옴저항, Flex 센서, 브레드보드, 점퍼 케이블 배경지식 : Flex 센서는다음과같이구부러진정도가커지면저항값이커집니다. 따라하기 : Flex 센서와저항을이용하여다음과같은회로를구성합니다. 35
다음의프로그램을업로드한후시리얼모니터링을통하여값의변화를 체크해봅시다. int flexpin = 0; // 센서값을읽기위해아날로그핀 0 번을 flexpin 에지정한다. void setup() Serial.begin(9600); // 센서값을읽기위해시리얼모니터를사용할것을설정. void loop() int flexval; // 센서값을저장할변수 flexval = analogread(flexpin); // 아날로그를입력받음 (0~1023) 36
Serial.print("sensor: "); // sensor: 라는텍스트를프린트한다. Serial.println(flexVal); // println 은줄바꿈명령이다. flexval 의값을출력한다. 시리얼모니터링에서데이터가빠르게진행되서값을체크하기어렵다면 delay() 함수를사용해볼수있습니다. Serial.println(flexVal); 다음줄에 delay() 를사용해봅시다. (ex. delay(200);) 37
4. F. FSR 압력센서를이용한압력측정하기 FSR(Force Sensing Resistor) 는얇은필름방식으로제작된압력센서로서간단한접촉의압력측정이가능합니다. 굽힘센서와마찬가지로저항의일종이며 10k옴저항을사용하여값을측정할수있습니다. 정밀한압력및힘의측정에는로드셀을사용할수있으나, 비교적저렴하면서쉽게구현이가능하기때문에널리사용되고있습니다. 준비물 : 아두이노우노, USB 케이블, 10k 옴저항, FSR, 브레드보드, 점퍼케이블 배경지식 : 데이터시트에서제공된실험결과를보면저항값과힘의관계가그래프에 표현되어있습니다. V O V I = R FSR R 1 + R FSR 여기서 V I =5V, 즉 1023 이고, R 1 =10000 옴이라고하면, V O 와 R FSR 의관계식은 다음과같이됩니다. R FSR = 9.78 V O 1 ( V O 1023 ) V O 는아두이노의 analogread() 함수를이용하여센서값을얻고, 위공식을 바탕으로 FSR 의저항값을측정할수있습니다. 그리고, 측정된저항값 ( R FSR ) 을 아래저항과힘의관계그래프를통하여가해진힘을확인할수있습니다. 38
따라하기 : FSR 과저항을이용하여다음과같은회로를구성합니다. 다음의프로그램을업로드한후시리얼모니터링을통하여값의변화를 체크해봅시다. 39
int FSRpin = 0; // FSRpin을아날로그0(A0) 에연결 int Vo; // 센서값을저장할변수 float Rfsr; void setup() Serial.begin(9600); // 센서값을읽기위해시리얼모니터를사용할것을설정. void loop() Vo = analogread(fsrpin); // 아날로그를입력받음 (0~1023) Rfsr = ((9.78 * Vo)/(1-(Vo/1023.0))); Serial.print("Rfsr: "); // sensor: 라는텍스트를프린트한다. Serial.println(Rfsr); // println은줄바꿈명령이다. Rfsr의값을출력한다. 시리얼모니터링에서데이터가빠르게진행되서값을체크하기어렵다면 delay() 함수를사용해볼수있습니다. Serial.println(Rfsr); 다음줄에 delay() 를사용해보세요. (ex. delay(200);) 40
4. G. 온도습도센서테스트 (DHT11) 온도습도센서 DHT11 을아두이노에다음과같이연결합니다. DHT11 Pin 1 (Vss) --> Arduino +5V DHT11 Pin 2 (Signal) --> Arduino Pin 2 DHT11 Pin 2 (Signal) --> Arduino +5V via Resistor 4.7K DHT11 Pin 3 --> N/C DHT11 Pin 4 (GND) --> Arduino Ground 이때, 센서의핀정보는다음과같습니다. 41
메카솔루션혹은아두이노플레이그라운드에서 DHT11 라이브러리를 다운로드받으신후에다음의소스코드를이용하여센서값을얻으실수 있습니다. #include <dht11.h> dht11 DHT11; #define DHT11PIN 2 void setup() Serial.begin(9600); Serial.println("DHT11 TEST PROGRAM "); Serial.print("LIBRARY VERSION: "); Serial.println(DHT11LIB_VERSION); Serial.println(); double Fahrenheit(double celsius) return 1.8 * celsius + 32; 42
void loop() Serial.println("\n"); int chk = DHT11.read(DHT11PIN); Serial.print("Read sensor: "); switch (chk) case 0: Serial.println("OK"); break; case -1: Serial.println("Checksum error"); break; case -2: Serial.println("Time out error"); break; default: Serial.println("Unknown error"); break; Serial.print("Humidity (%): "); Serial.println((float)DHT11.humidity, 2); Serial.print("Temperature (oc): "); Serial.println((float)DHT11.temperature, 2); Serial.print("Temperature (of): "); Serial.println(Fahrenheit(DHT11.temperature), 2); delay(2000); 43
4. H. 인체감지센서모듈테스트하기 44
/* * PIR sensor tester */ int ledpin = 13; int inputpin = 2; int pirstate = LOW; int val = 0; // choose the pin for the LED // choose the input pin (for PIR sensor) // we start, assuming no motion detected // variable for reading the pin status void setup() pinmode(ledpin, OUTPUT); pinmode(inputpin, INPUT); // declare LED as output // declare sensor as input Serial.begin(9600); void loop() 45
val = digitalread(inputpin); // read input value if (val == HIGH) // check if the input is HIGH digitalwrite(ledpin, HIGH); // turn LED ON if (pirstate == LOW) // we have just turned on Serial.println("Motion detected!"); // We only want to print on the output change, not state pirstate = HIGH; else digitalwrite(ledpin, LOW); // turn LED OFF if (pirstate == HIGH) // we have just turned of Serial.println("Motion ended!"); // We only want to print on the output change, not state pirstate = LOW; /* * PIR sensor tester */ int ledpin = 13; int inputpin = 2; int pirstate = LOW; int val = 0; // choose the pin for the LED // choose the input pin (for PIR sensor) // we start, assuming no motion detected // variable for reading the pin status void setup() pinmode(ledpin, OUTPUT); pinmode(inputpin, INPUT); // declare LED as output // declare sensor as input 46
Serial.begin(9600); void loop() val = digitalread(inputpin); // read input value if (val == HIGH) // check if the input is HIGH digitalwrite(ledpin, HIGH); // turn LED ON if (pirstate == LOW) // we have just turned on Serial.println("Motion detected!"); // We only want to print on the output change, not state pirstate = HIGH; else digitalwrite(ledpin, LOW); // turn LED OFF if (pirstate == HIGH) // we have just turned of Serial.println("Motion ended!"); // We only want to print on the output change, not state pirstate = LOW; 47
4. I. 초음파거리센서사용하기 (HC-SR04) 초음파거리센서를이용하여 2cm~400cm 까지거리를측정할수있습니다. 센서 의 Trig, Echo 를어느디지털핀에연결하여도무방하나, 12 번, 11 번에각각연결하 였고, VCC 와 GND 를 5V 와 GND 에연결하였습니다. 다음의코드를업로드하여센서동작을구현할수있습니다. int trigpin = 12; int echopin = 11; void setup() Serial.begin (9600); pinmode(trigpin, OUTPUT); pinmode(echopin, INPUT); void loop() long duration, distance; digitalwrite(trigpin, LOW); // Added this line 48
delaymicroseconds(2); // Added this line digitalwrite(trigpin, HIGH); delaymicroseconds(10); // Added this line digitalwrite(trigpin, LOW); duration = pulsein(echopin, HIGH); distance = (duration/2) / 29.1; if (distance >= 200 distance <= 0) Serial.println("Out of range"); else Serial.print(distance); Serial.println(" cm"); delay(500); 49
4. J. 자기장센서를이용하여절대방향측정 (HMC5883L) HMC5883L 을이용하여절대방향을측정할수있습니다. 이자기장센서는자석에의해값이왜곡될수있으니, 자석이들어가있는모터등과가까이사용하지않는것이좋습니다. I2C 통신을하며다음과같이연결하실수있습니다. MPU6050 VCC GND SCL SDA Arduino <-> 3V3 <-> GND <-> ANALOG IN A5 <-> ANALOG IN A4 참고로, SCL 과 SDA 는보드마다차이가있습니다. 다음을참고해주세요.^^ Board Uno, Ethernet Mega2560 Leonardo Due I2C / TWI pins A4 (SDA), A5 (SCL) 20 (SDA), 21 (SCL) 2 (SDA), 3 (SCL) 20 (SDA), 21 (SCL), SDA1, SCL1 #include <Wire.h> //I2C Arduino Library #define address 0x1E //0011110b, I2C 7bit address of HMC5883 void setup() 50
//Initialize Serial and I2C communications Serial.begin(9600); Wire.begin(); //Put the HMC5883 IC into the correct operating mode Wire.beginTransmission(address); //open communication with HMC5883 Wire.send(0x02); //select mode register Wire.send(0x00); //continuous measurement mode Wire.endTransmission(); void loop() int x,y,z; //triple axis data //Tell the HMC5883 where to begin reading data Wire.beginTransmission(address); Wire.send(0x03); //select register 3, X MSB register Wire.endTransmission(); //Read data from each axis, 2 registers per axis Wire.requestFrom(address, 6); if(6<=wire.available()) x = Wire.receive()<<8; //X msb x = Wire.receive(); //X lsb z = Wire.receive()<<8; //Z msb z = Wire.receive(); //Z lsb y = Wire.receive()<<8; //Y msb y = Wire.receive(); //Y lsb 51
//Print out values of each axis Serial.print("x: "); Serial.print(x); Serial.print(" y: "); Serial.print(y); Serial.print(" z: "); Serial.println(z); delay(250); 52
4. K. 적외선거리센서사용하기 (Sharp GP2Y0A21YK) int sensorpin = 0; //pin Analog 0 int ledpin = 13; int valsensor = 0; void setup() Serial.begin(9600); pinmode(ledpin,output); void loop() valsensor = analogread(sensorpin); Serial.print("Sensor value: "); Serial.print(valSensor); 53
4. L. 초음파거리센서 (Maxbotix Sonar LV EZ1) int configpin = 13; //Set the sonar Calibration Pin void setup() //begin of program Serial.begin(9600); //serial baud rate 9600 pinmode(configpin,output); //make Calibration pin output void loop() //looping of program digitalwrite(configpin,high); //raise the reset pin high delay(120); //start of calibration ring float sensorvalue = analogread(0); //get analog sensor value from pin 0 float inchvalue = (254.0/1024.0) *2.0* sensorvalue; //convert to inches Serial.print("Sensed a-d value:"); //print a-d text Serial.println(sensorvalue); //print a-d value Serial.print("Inch value="); //print inch text Serial.println(inchvalue); //print inch value delay(1000); //optional delay 1 second digitalwrite(configpin,low); //turn off Calibration ring and sensor delay(1000); //delay 1 second 54
4. M. RGB 컬러센서 (Parallax ColorPAL) #include <SoftwareSerial.h> const int sio = 2; // ColorPAL connected to pin 2 const int unused = 255; // Non-existant pin # for SoftwareSerial const int siobaud = 4800; const int waitdelay = 200; // Received RGB values from ColorPAL int red; int grn; int blu; // Set up two software serials on the same pin. SoftwareSerial serin(sio, unused); SoftwareSerial serout(unused, sio); void setup() Serial.begin(9600); reset(); // Send reset to ColorPal serout.begin(siobaud); pinmode(sio, OUTPUT); 55
serout.print("= (00 $ m)!"); // Loop print values, see ColorPAL documentation serout.end(); // Discontinue serial port for transmitting serin.begin(siobaud); pinmode(sio, INPUT); // Set up serial port for receiving void loop() readdata(); // Reset ColorPAL; see ColorPAL documentation for sequence void reset() delay(200); pinmode(sio, OUTPUT); digitalwrite(sio, LOW); pinmode(sio, INPUT); while (digitalread(sio)!= HIGH); pinmode(sio, OUTPUT); digitalwrite(sio, LOW); delay(80); pinmode(sio, INPUT); delay(waitdelay); void readdata() char buffer[32]; if (serin.available() > 0) // Wait for a $ character, then read three 3 digit hex numbers 56
buffer[0] = serin.read(); if (buffer[0] == '$') for(int i = 0; i < 9; i++) while (serin.available() == 0); buffer[i] = serin.read(); if (buffer[i] == '$') return; parseandprint(buffer); delay(10); // Wait for next input character // Return early if $ character encountered // Parse the hex data into integers void parseandprint(char * data) sscanf (data, "%3x%3x%3x", &red, &grn, &blu); char buffer[32]; sprintf(buffer, "R%4.4d G%4.4d B%4.4d", red, grn, blu); Serial.println(buffer); 57
5. A. LED 깜빡이기 가장기본적인출력이면서동시에아두이노가제대로동작하는지를확인할수있습니다. 아두이노우노는 13번핀이 LED에연결되어있는채출고되기때문에별다른연결없이 USB 케이블과아두이노만으로 LED 깜빡이기예제를수행할수있습니다. 준비물 : 아두이노우노, USB 케이블 따라하기 : USB 를이용하여아두이노와컴퓨터의 USB 포트를연결하기. 아두이노소프트웨어의파일 예제 Basics Blink 를클릭. LED 깜빡이는예제가다음과같이열립니다. 58
첫번째부분은변수선언파트로 13번핀을 led로사용하겠다는의미이며, 두번째 void setup() 는아두이노에전원이공급되면한번실행되는메소드이며핀에대한입출력설정및시리얼함수초기화등을합니다. pinmode(led, OUTPUT) 이라는커맨드는 led를출력으로사용하겠다는의미입니다. 여기서 led는핀번호를의미하기때문에 13번핀을출력으로설정이라고생각하면됩니다. 그리고세번째 void loop() 는아두이노에전원이들어온후꺼질때까지계속반복해서실행되는메소드이며위의소스를보면 digitalwrite(led, HIGH) 라는커맨드에서 led(13번핀 ) 에출력을 HIGH(5V) 로출력하여 LED를켜고 delay(1000) 이라는함수로 1000ms(1초 ) 동안켠상태를유지합니다. 그리고다시 digitalwrite(led, LOW) 라는커맨드로 led에출력을 LOW(0V) 로하여 LED를끄고 delay(1000) 이라는함수로 1000ms(1초 ) 동안끈상태를유지합니다. 결과적으로 void loop() 는 LED가 1초에한번씩꺼졌다켜졌다를반복하는깜빡이는동작을하게됩니다. 왼쪽상단의확인 (Verify) 버튼을누른후, 완료가되면업로드버튼을 눌러서 LED 깜빡이기프로그램을아두이노에올려보세요. 확인이되었으면, delay(1000) 을 delay(100) 으로바꿔서 LED 가더빨리 깜빡이는지도확인해보세요. 59
5. B. PWM 을이용한 LED 밝기조절 LED 의밝기를조절하려면어떻게해야할까. PWM(Pulse Width Modulation) 이라는것을이용하여 LED 의밝기를조절할수있습니다. 위의그림에서와 PWM은신호의 On/Off의비율을변경시키는방법을통해높고낮은레벨의출력을할수있도록합니다. 즉, Off의비율이많으면점점흐릿해지는 LED를출력하게되고, On의비율이많으면점점밝아지는 LED 출력을하게됩니다. 이 PWM은아날로그출력이라는함수를사용하게되는데이출력에사용할수있는핀의개수가제한되어있습니다. 아두이노우노에서는 3,5,6,9,10,11번의 6개핀을사용할수있고, 디지털핀쪽의물결표시 (~) 로확인할수있습니다. 준비물 : 아두이노우노, USB 케이블, 브레드보드, LED, 330 옴저항, 점퍼케이블 따라하기 : 60
LED는애노드와캐소드라는두개의리드가있는반도체장치입니다. 다리가긴쪽이애노드 (+) 이고, 다리가짧은쪽이캐소드 (-) 입니다. 통상적으로 LED에필요한전압은 1.8~2.3V이므로 5V에서 3V가량을전압강하해야합니다. 그리고 LED가끌어쓰는전류를감안해서약 330옴의저항을연결합니다. 다음의소스를스케치에복사혹은타이핑을한후확인 - 업로드를해 보자. int led = 3; int brightness = 0; int increment = 1; void setup() // analogwrite을통해구동되는핀은출력으로선언하지않아도된다. void loop() if(brightness > 255) increment = -1; // 255에도달하면값은낮춘다. 61
else if(brightness < 1) increment = 1; // 0으로떨어지면값을높인다. brightness = brightness + increment; // 밝기 (brightness) 를증가혹은감소한다. analogwrite(led, brightness); // 밝기를출력한다 delay(10); 매번 LED의밝기가밝아졌다가어두워졌다가하는것을확인할수있습니다. 아날로그신호를디지털신호로읽기위해서는 analogread() 를사용하며 0~1023(10bit) 까지의값으로변환해서읽을수있고, 이번예제에서사용한 analogwrite() 는 0~255(8bit) 까지변환하여출력할수있습니다. 62
5. C. 여러개 LED 동시에제어하기 LED 를깜빡이고, PWM 을이용한밝기조절을하였다면여러개의 LED 를 제어하는것은어려운일이아닙니다. 이번예제를통해 8 개의 LED 를순차적으로 깜빡이는것을 for 루프와배열에대하여공부도해보도록합시다. for 루프 간략하게설명을하자면여러분이어떤코드를여러번 실행해야할때, 사용하는매우유용한반복문의일종입니다. 배열 배열 (array) 는여러개의변수를지정할때사용하며배열의 인덱스를이용하여그값을지정할수있고배열에들어있는값을 요소 (element) 라합니다. 다음의예를통하여 for 루프와배열에대하여알아봅시다. 먼저, LED 8개를 Digital핀 2번에서 9번까지 8개를연결할것을설정하였습니다. 각각의 LED에대하여 ledpin1에서 ledpin8이라고설정을했습니다. 그리고 setup() 메소드에서이 LED들을입력이아닌출력으로사용할것을 pinmode함수를통해지정하였습니다. 왼쪽의코드가잘못된것은전혀아니지만, for 루프와배열을이용하여좀더컴팩트한프로그램을구현해보도록하죠. 오른쪽의코드는 intledpins[] 라는배열을선언했습니다. 8개의숫자가 ledpins라는배열에할당이됩니다. 아두이노에서배열은 0번이첫번째요소를지칭합니다. 따라서, int ledpins[0] = 2; int ledpins[1] = 3, 그리고, int ledpins[7] 은 9가됩니다. 이 8개의 LED들을 OUTPUT으로설정하기위하여 for(int i=0; i<=7; i++) 라는 for 루프문을사용합니다. 이는 i라는인덱스를이용하여 0에서 7까지 i를 1씩증가시키겠다는의미입니다. 따라서 for 루프가시작되는처음에는 i=0, pinmode(ledpins[0], OUPUT); i를 1씩증가시켜다음에는 i=1이되고 pinmode(ledpins[1], OUTPUT); 그리고마지막으로 i=7; pinmode(ledpins[7], OUTPUT) 이되고 for 루프문은종료됩니다. int ledpin1 = 2; int ledpins[] = 2,3,4,5,6,7,8,9; 63
int ledpin2 = 3; int ledpin3 = 4; void setup() int ledpin4 = 5; int ledpin5 = 6; for(int i = 0; i <= 7; i++) int ledpin6 = 7; int ledpin7 = 8; pinmode(ledpins[i],output); int ledpin8 = 9; void setup() pinmode(ledpin1, OUTPUT); pinmode(ledpin2, OUTPUT); pinmode(ledpin3, OUTPUT); pinmode(ledpin4, OUTPUT); pinmode(ledpin5, OUTPUT); pinmode(ledpin6, OUTPUT); pinmode(ledpin7, OUTPUT); pinmode(ledpin8, OUTPUT); 기본적으로왼쪽의코드와오른쪽의코드는같습니다. 하지만, 왼쪽의코드는오른쪽의코드보다 50바이트정도사이즈가더큽니다. 한정된메모리를사용하는아두이노인만큼최적화된프로그램을위해배열과 for 루프를적절히사용하도록하는것이좋습니다. 본격적으로 8 개의 LED 를제어해봅시다. 준비물 : 아두이노우노, USB 케이블, 브레드보드, LED 8 개, 330 옴저항 8 개, 점퍼 케이블 따라하기 : 64
LED는애노드와캐소드라는두개의리드가있는반도체장치이다. 다리가긴쪽이애노드 (+) 이고, 다리가짧은쪽이캐소드 (-) 이다. 통상적으로 LED에필요한전압은 1.8~2.3V이므로 5V에서 3V가량을전압강하해야한다. 그리고 LED가끌어쓰는전류를감안해서약 330옴의저항을연결한다. 330옴을 LED의짧은다리와 GND에연결한다. 그리고, LED의다리가긴쪽을아두이노의디지털핀2번에서 9번까지연결한다. ( 다음그림에서사용된저항이미지는임의로사용되었기때문에 330옴 ( 주황-주황-갈색 ) 을사용한다. 주황은 3을갈색은 0을의미함 ) 65
다음의소스를스케치에복사혹은타이핑을한후확인 - 업로드를해 보자. int ledpins[] = 2,3,4,5,6,7,8,9; // 8 개의 LED 를 Digital2 번부터 Digital9 번까지 사용함. void setup() for(int i = 0; i <= 7; i++) pinmode(ledpins[i],output); // 8개의 LED를출력으로설정. void loop() for(int i = 0; i <= 7; i++) digitalwrite(ledpins[i], HIGH); // D2부터 D9에연결된 LED를순차적으로켬 delay(100); // 100ms(0.1초 ) 동안기다림. for(int i = 7; i >= 0; i--) digitalwrite(ledpins[i], LOW); // D9부터 D2에연결된 LED를순차적으로끔 delay(100); // 100ms(0.1초 ) 동안기다림. 66
5. D. 쉬프트레지스터 (74HC595) 만약, 여러개의 LED를제어해야하지만그만큼의사용가능한핀들이없다면 ( 많은핀들을모터및센서에할당한경우 ), 쉬프트레지스터를이용하여다수의 LED를제어할수있습니다. 쉬프트레지스터는 IC(integrated circuit) 의일종으로 3개의핀을이용하여 8개의각기다른출력을할수있습니다. 쉬프트레지스터는많은종류가있지만, 74HC595라는칩을사용하도록하겠습니다. 다음은 74HC595칩의핀배열및논리값입니다. SER, SRCLK, RCLK는 74HC595의제어인풋이며아두이노에서값을받습니다. 그리고 QA~QH까지는 74HC595의출력이며최대 8개의 LED에연결이가능합니다. SER은 data핀, SRCLK는 Clock, RCLK는 latch 핀으로각각아두이노의디지털핀 2,3,4번에연결할수있습니다. 우리가사용할아두이노의핀은 D2, D3, D4이며이들은각각 data, clock, latch 핀이됩니다. 이번에는 bitwrite() 와 shiftout() 이라는함수를이용하여시리얼시프트함수를작성하겠습니다. bitwrite(): bitwrite는숫자를 bit로바꾸서기록하는함수이며 bitwrite(x,n,b) 와같이사용됩니다. 여기서 x는 bit로바꿀숫자이며 n은기록될디지털핀, 그리고 b는 bit에쓸불리언수 (0 혹은 1) 을나타냅니다. ( 참고 : http://arduino.cc/en/reference/bitwrite) shiftout(): shiftout 은 1byte 를한번에 1bit 씩밀어내는시프트출력 명령입니다. shiftout(datapin, clockpin, bitorder, value) 와같이사용되며 67
datapin은 74HC595의 SER과연결된핀, clockpin은 SRCLK에연결된핀을지정하면됩니다. bitorder는 MSBFIRST (Most Significant Bit First) 혹은 LSBFIRST (Least Significant Bit First) 중선택이가능한데이는쉬프트하는방향을의미합니다. 그리고 value는쉬프트출력을하려는 data입니다. 준비물 : 아두이노우노, USB 케이블, 74HC595, 브레드보드, LED 8 개, 330 옴저항 8 개, 점퍼케이블 따라하기 : 먼저 74HC595 와아두이노, 그리고 8 개의 LED 와저항들을다음에보이는 회로와같이연결합니다. 68
다음의소스를스케치에복사혹은타이핑을한후확인 - 업로드를 하겠습니다.. int datapin = 2; int clockpin = 3; int latchpin = 4; byte data = 0; void setup() pinmode(datapin, OUTPUT); pinmode(clockpin, OUTPUT); pinmode(latchpin, OUTPUT); void loop() for(int i = 0; i <= 7; i++) shiftwrite(i, HIGH); delay(100); for(int i = 7; i >= 0; i--) shiftwrite(i, LOW); delay(100); void shiftwrite(int desiredpin, boolean desiredstate) 69
bitwrite(data,desiredpin,desiredstate); shiftout(datapin, clockpin, MSBFIRST, data); digitalwrite(latchpin, HIGH); digitalwrite(latchpin, LOW); 70
5. E. 16x2 LCD 제어하기 일반 16x2 LCD 는 16 개의핀이있습니다. 이핀들은다음과같이구성되어있고, 아두이노에연결할수있습니다. 여기서, 실제 LCD 와아두이노는다음의그림처럼연결하고, 포텐쇼미터를 이용하여 LCD 의밝기를조절할수있는옵션을만들어주는것이좋습니다. 71
프로그램은 LiquidCrystal.h 라는라이브러리를추가하여쉽게테스트를할수 있고, 기본소스는다음과같습니다. // include the library code: #include <LiquidCrystal.h> // initialize the library with the numbers of the interface pins LiquidCrystal lcd(12, 11, 5, 4, 3, 2); void setup() // set up the LCD's number of columns and rows: lcd.begin(16, 2); // Print a message to the LCD. lcd.print("hello, world!"); 72
void loop() // set the cursor to column 0, line 1 // (note: line 1 is the second row, since counting begins with 0): lcd.setcursor(0, 1); // print the number of seconds since reset: lcd.print(millis()/1000); 73
6. A. 서보모터구동하기 우리가사용할서보모터는내부에포텐쇼미터혹은볼륨이있어서모터가어느정도회전했는지센싱하고, 모터내부에있는컨트롤러를이용하여입력받은값만큼돌려주는기능을가지고있습니다. 대부분의서보모터는무한회전을하지않고 180도정도회전하는데, 아두이노의 PWM을이용하여각도를컨트롤할수있습니다. 또한, 아두이노의 delay함수를이용하여모터의회전속도도조절할수있습니다. 앞에서보았던 PWM을이용하여모터를회전할수있지만, 아두이노의강점인오픈라이브러리를이용하여서보모터를쉽게컨트롤하겠습니다. 아두이노소프트웨어를다운받으면 Servo.h라는라이브러리가함께설치됩니다. 따라서별도의라이브러리추가를할필요없이그대로사용하면됩니다. Servo.h 라이브러리는다음의함수를포함합니다. servo.attach(pin): 서보모터가연결될핀을지정합니다. 서보모터는 PWM 으로제어되기때문에디지털핀중물결표시가있는핀에연결하면 된다. 우노의경우 3, 5, 6, 9, 10, 11 번을사용할수있습니다. servo.write(angle): 회전시킬각도를입력합니다. 이함수가실행되면 모터는 angle 만큼회전합니다. 준비물 : 아두이노우노, USB 케이블, 서보모터, 브레드보드, 점퍼케이블 따라하기 : 서보모터는일반적으로 3 개의선을가지고있습니다. VCC( 빨강 ), GND( 검정 혹은갈색 ), 그리고신호선 ( 노랑혹은주황 ). VCC 와 GND 를아두이노에 연결하고, 신호선을디지털 9 번핀에연결합니다. 74
다음의소스를스케치에복사혹은타이핑을한후확인 - 업로드를해 보세요. #include <Servo.h> // 서보라이브러리 Servo motor1; // 서보모터오브젝트 void setup() motor1.attach(9); // 서보모터를 9번에연결 75
void loop() for(int position = 0; position < 180; position += 2) // 0도에서 180까지 2도씩증가 motor1.write(position); // 모터를 position만큼회전 delay(20); // 모터가돌때까지기다림. for(int position = 180; position >= 0; position -= 2)//180도에서 0도까지 2도씩감소 motor1.write(position); // 모터를 position만큼회전 delay(20); // 모터가돌때까지기다림. 주의!: 서보모터를사용하실때, 소비하는전류로인해아두이노에연결한다른센서들이오작동할수있으니, 여러서보모터혹은다른센서들과함께사용할때는독립전원을사용하여서모터에전원을공급하고, 모터의 GND와아두이노의 GND는커먼그라운드를해주시길바랍니다. 76
6. B. H-Bridge 를이용한 DC 모터방향제어하기 SN754410은쉽고편리한 IC로 DC 모터의속도와방향을컨트롤할수있게합니다. 이번예제를통해쉽고간단하게 DC모터의방향을제어해보겠습니다. 또한, 본예제와가속도센서를이용해세그웨이와같은밸런스로봇도제작할수있고, 모터를이용한여러가지애플리케이션을제작할수있습니다. 준비물 : 아두이노우노, USB 케이블, 브레드보드, SN754410, DC 모터, 점퍼 케이블 배경지식 : SN754410을이용하여한개의 DC모터를컨트롤하기위해서는 1개의 PWM, 2개의디지털아웃풋이요구됩니다. 1개의 PWM은스피드를컨트롤하기위함이며, 2개의디지털아웃풋은모터의방향을결정하기위함입니다. 다음의 SN754410 칩의함수테이블을보면 A가 H(high) 일때, 아웃풋 Y는 HIGH이고, A가 L(low) 일때, 아웃풋은 L이다. 모터컨트롤러를왜사용하는가생각할수있습니다. 아두이노에서나오는아날로그아웃풋을이용하여컨트롤할수도있고, 혹은트랜지스터와다이오드를이용하여컨트롤할수도있습니다. 하지만, 모터에서사용하는전류가보통 100mA이상이므로 40mA를출력하는아두이노에직접적으로연결하는것은옳지않으며간단히모터컨트롤러칩을사용함으로써두개의모터를제어하는편리함때문에이번예제에서는트랜지스터와다이오드를이용한모터컨트롤대신 SN754410을이용한모터컨트롤을하기로했습니다. SN754410의핀정보를보면총 4개의인풋이있습니다 1A, 2A, 3A, 4A. 이 4개의인풋을이용하여두개의모터방향을결정할수있습니다. 즉, 1A와 2A를이용하여 1Y, 2Y의값을컨트롤하고, 3A와 4A를이용하여 3Y, 4Y를컨트롤합니다. 1Y, 2Y는첫번째모터에, 그리고 3Y, 4Y는두번째모터에각각연결됩니다. 그리고, 1,2EN핀과 3,4EN핀에 PWM 값을입력해주면서전압에따른모터의속도컨트롤이가능합니다. 77
SN754410 의핀정보및함수테이블 : 모터의출력 Y, 회로다이어그램 따라하기 : 1개의 DC모터를컨트롤하기위해서다음의회로를구성해봅시다. SN754410을브레드보드에꼽습니다. 아래회로에서왼쪽에있는작은홈이있는방향이 1번핀이시작되는방향입니다. 78
모터에서나오는두개의신호선은 + 혹은 에대한정의가없으니, 임의로결정을한후에브레드보드에끼워도무방하며방향은컨트롤러에서결정할수있습니다. 혹은회전하는방향에따라모터에서나오는갈색과보라색의선을바꾸어끼워도됩니다. 회로를구성하였으면다음의프로그램을컴파일후업로드해보세요. int speedpin = 3; // SN754410의 1,2EN 핀과 PWM핀에연결하였다. 속도제어용핀 int motor1apin = 6; // 1A int motor2apin = 7; // 2A int speed_value_motor1; // 모터스피드를위한변수 void setup() 79
pinmode(speedpin, OUTPUT); pinmode(motor1apin, OUTPUT); pinmode(motor2apin, OUTPUT); void loop() digitalwrite(motor1apin, LOW); // 1A에 LOW digitalwrite(motor2apin, HIGH); // 2A에 HIGH speed_value_motor1 = 127; // 0~255의수중선택가능함. 0: 속도제로, 255: 최고속도. analogwrite(speedpin, speed_value_motor1); // PWM 출력을하여정한속도만큼모터회전 위의코드에서 loop() 내에있는명령문중, digitalwrite(motor1apin, LOW) 와 digitalwrite(motor2apin, HIGH) 를다음과바꾸어보세요. ditialwrite(motor1apin, HIGH), digitalwrite(motor2apin, LOW). 모터가반대방향으로도는것을확인할수있습니다. 또한, speed_value_motor1 = 127 의값을 255 로도바꾸어보세요. 모터가더 빨리회전하는것을확인할수있을것입니다. 80
6. C. 스테핑모터제어하기 (EasyDriver) 준비물 : 아두이노우노, USB 케이블, 브레드보드, EasyDriver, 스테핑모터, 점퍼 케이블, 12V 전원 따라하기 : 모터의네개의선을 EasyDriver 에연결하고, 12V 의전원도 Easy Driver 에 연결합니다. EasyDriver 의그라운드를아두이노의그라운드와연결하여커먼그라운드해 줍니다. 아두이노의 8 번과 9 번을 EasyDriver 에연결하여모터를제어해보겠습니 다. 81
void setup() pinmode(8, OUTPUT); // 8 번핀은방향전환핀으로사용합니다. pinmode(9, OUTPUT); // 9 번핀은스텝핀으로사용합니다. digitalwrite(8, LOW); digitalwrite(9, LOW); void loop() digitalwrite(9, HIGH); delay(1); digitalwrite(9, LOW); delay(1); 위의코드는한스텝씩스테핑모터를돌리는예제입니다. 간단한예제에요. delay 값을변화해서모터의회전속도를조절할수있습니다. 다음은방향전환 예제소스입니다. int Distance = 0; // 모터가돌아간절도를기록할변수입니다. void setup() pinmode(8, OUTPUT); pinmode(9, OUTPUT); digitalwrite(8, LOW); digitalwrite(9, LOW); void loop() 82
digitalwrite(9, HIGH); delaymicroseconds(100); digitalwrite(9, LOW); delaymicroseconds(100); Distance = Distance + 1; if (Distance == 3600) if (digitalread(8) == LOW) digitalwrite(8, HIGH); else digitalwrite(8, LOW); Distance = 0; delay(500); 83
7. A. Bluetooth 블루투스모듈중에저렴하고사용하기편리한 JY-MCU 블루투스모듈을 이용하여데이터를전송받을수있습니다. 하드웨어 TX 와 RX 를사용할것이기에 블루투스를연결하기전에다음의프로그램을업로드합니다. char val; // variable to receive data from the serial port int ledpin = 8; // LED connected to pin 48 (on-board LED) void setup() pinmode(ledpin, OUTPUT); // pin 48 (on-board LED) as OUTPUT Serial.begin(9600); // start serial communication at 9600bps void loop() if( Serial.available() ) // if data is available to read val = Serial.read(); // read it and store it in 'val' if( val == 'H' ) // if 'H' was received digitalwrite(ledpin, HIGH); // turn ON the LED else digitalwrite(ledpin, LOW); // otherwise turn it OFF delay(100); // wait 100ms for next reading 84
업로드가완료된후, 다음처럼아두이노와연결합니다. 통신을하기위해서컴퓨터에블루투스동글을사용하거나혹은안드로이드 폰의블루투스와연결을합니다. 장치를추가하고 linvor 라는것을찾고 비밀번호로 1234 를입력합니다. 85
7. B. Zigbee(XBee) AT 모드 XBee를이용한커뮤니케이션을하기위해서는크게두가지방법이있는데그하나는 AT모드이고다른하나는 API모드입니다. AT모드는 XBee를구입하고별도의 XBee프로그래밍없이바로사용할수있는장점이있고, XBee가유선을대신한다라고생각하면됩니다. 반면에 API모드는구성하기까다로운면이없지않지만, RSSI (Received Signal Strength Indication) 과에러체크등다양한기능을가능하게하는장점이있습니다. XBee를이용하여커뮤니케이션을하는하드웨어구성도역시크게두가지를생각할수있는데, 하나는아두이노 컴퓨터간의커뮤니케이션이고다른하나는아두이노-아두이노간의커뮤니케이션입니다. 먼저, 아두이노- 컴퓨터간의커뮤니케이션을용이하게하기위해서는 USB XBee 레귤레이터보드를사용합니다. XBee를 USB XBee 레귤레이터보드에끼우고, 컴퓨터의 USB포트에연결하면컴퓨터와 XBee가연결이되고데이터를받거나보낼준비를하게됩니다. 그리고아두이노쪽에서는 TX와 RX를 XBee의 RX와 TX에연결하면되는데, XBee의핀이 1mm 간격으로되어있기때문에일반빵판이나 PCB에는연결하기어렵기때문에레귤레이터보드를사용하면편리합니다. USB 레귤레이터보드 ( 좌컴퓨터에연결 ) 와레귤레이터보드 ( 우, 아두이노에연결 ) 86
7. C. Zigbee(XBee) API 모드를이용해서거리센싱하기 라디오시그널을사용하는 XBee는받은신호의세기를이용하여거리를측정하는데사용할수있습니다. 물론, 그거리가정확한것은아니지만, 다음과같이거리에따라신호의세기가감소하는특성을이용하여신호의세기측정이가능합니다. 거리에따른 RSS 의세기변화 이를구현하기위해서는먼저 XBee 를 API 모드로변환시켜줘야합니다. 이 변환시켜주는소프트웨어는 X-CTU 로서 XBee 를디자인한 Digi International 에서 다운로드받으실수있는데, 다음의링크에서받으실수있습니다. http://www.digi.com/support/productdetail?pid=3352&osvid=57&type=utilities X-CTU 를실행하면다음과같이윈도우가열리고, 각각의 XBee 를다음과같이셋팅할수 있습니다. 87
X-CTU 소프트웨어 먼저, API를이용하여 RSSI를받기위해서는수신부와발신부를각각다르게설정해야하는데, 수신부는 End-Device라하며발신부는 Coordinator라부르겠습니다. 그럼, 수신부쪽에서는위의화면에서 Function Set과파라미터들을다음과바꿔줍니다. 수신부쪽파라미터셋업 XB24 XBEE 802.15.4 MY 0 BD 57600 AP 1 88
발신부쪽파라미터셋업 XB24 XBEE 802.15.4 DL 0 MY 1 BD 57600 AP 0 XBee 셋업이완료되면각각의아두이노에다음의코드를업로드하여신호의 세기 (RSS) 를측정할수있습니다. < 스케치코드 - Sender> void setup() Serial.begin(57600); void loop() Serial.print("ID:001"); delay(300); < 스케치코드 - Receiver> void setup() Serial.begin(57600); pinmode(8,output); pinmode(9,output); pinmode(10,output); pinmode(11,output); pinmode(12,output); byte rssi=0x00; 89
void loop() if(serial.available()) byte in = Serial.read(); if(in == (byte) 0x7E) int i=0; while(true) if(serial.available()) in= Serial.read(); if(i==5)rssi=in; Serial.print(in,HEX); Serial.print(" "); i++; if(i>13)break; Serial.print("/ "); Serial.print("RSSI:"); Serial.print(rssi,HEX); Serial.println(" "); if(rssi>0x30) digitalwrite(8,high); digitalwrite(9,high); digitalwrite(10,high); digitalwrite(11,high); digitalwrite(12,high); else if(rssi>0x2b) digitalwrite(8,high); digitalwrite(9,high); digitalwrite(10,high); digitalwrite(11,high); 90
digitalwrite(12,low); else if(rssi>0x27) digitalwrite(8,high); digitalwrite(9,high); digitalwrite(10,high); digitalwrite(11,low); digitalwrite(12,low); else if(rssi>0x22) digitalwrite(8,high); digitalwrite(9,high); digitalwrite(10,low); digitalwrite(11,low); digitalwrite(12,low); else if(rssi>0x1c) digitalwrite(8,high); digitalwrite(9,low); digitalwrite(10,low); digitalwrite(11,low); digitalwrite(12,low); else digitalwrite(8,low); digitalwrite(9,low); digitalwrite(10,low); digitalwrite(11,low); digitalwrite(12,low); 91
8. A. 시리얼모니터에텍스트출력하기 아두이노에는 USB 케이블을이용하여간단히컴퓨터와데이터를주고받을수 있습니다. 특히, 시리얼모니터라는기능을유용하게이용할수있는데, 간단한 예제를통해서시리얼데이터를아두이노에서컴퓨터로보내봅시다. 준비물 : 아두이노우노, USB 케이블 따라하기 : 앞서 LED 깜빡이기예제를수행하였다면별다른하드웨어변경은 필요없습니다. USB 케이블을이용하여아두이노와컴퓨터를연결합니다. 다음의간단한프로그램을아두이노의스케치에복사한후, 확인 ( 컴파일 ) 그리고업로드를합니다. void setup() Serial.begin(9600); // 시리얼포트를사용하겠다는선언 void loop() Serial.println("Mechasolution"); // Mechasolution이라는텍스트를줄바꾸면서출력한다. 업로드후, 스케치의오른쪽상단에있는시리얼모니터아이콘을클릭하거나, 도구-시리얼모니터, 혹은 Ctrl+Shift+M을눌러서시리얼모니터창을띄워봅니다. 92
93
8. B. 키보드로문자입력받아아두이노에전송하기 키보드를이용하여로봇을제어하거나, MIDI와같은장비와의인터페이스를구현하기위해, 아두이노의 Serial.read() 함수를이용하여컴퓨터와아두이노의통신을구현할수있습니다. 키보드로부터키를입력받아, 아두이노의시리얼모니터링창에입력하면, 그값을아두이노에전송되고, 아두이노는다시그값을컴퓨터에보냄으로확인이가능합니다. 준비물 : 아두이노우노, USB 케이블 따라하기 : USB 케이블을이용하여아두이노와컴퓨터를연결합니다. 보드와시리얼 포트설정을한후다음의프로그램을업로드해봅니다. byte KeyInput; void setup() Serial.begin(9600); void loop() if(serial.available() > 0) KeyInput = Serial.read(); Serial.write(KeyInput); 업로드후, 시리얼모니터를열고, 키를입력한후 엔터를쳐서 아두이노에전송해봅시다. 94
엔터를치면, 아두이노로부터값을출력받는것을확인할수있습니다. 95
8. C. 스위치사용하여 LED 컨트롤 알고리즘으로 LED 를컨트롤할수도있지만, 다양한스위치를이용하여 LED 를 컨트롤할수도있습니다. 스위치는버튼스위치, 토글스위치등여러가지가 있지만, 기본원리는회로를연결혹은끊는것입니다. 준비물 : 아두이노우노, USB 케이블, 마이크로스위치, 10k 저항, 브레드보드, 점퍼케이블 배경지식 : 위의회로를보면, 스위치가열려있을때, 아두이노의인풋 (PINx) 는 HIGH 인풋을 받게됩니다. 하지만, 스위치가닫히게되면 PINx 는 GND 에연결이되어 LOW 인풋을받게됩니다. 따라하기 : 스위치를브레드보드에연결혹은필요에따라납땜을합니다. 그리고 스위치의한쪽에풀업저항을이용하여 5V 에연결합니다. 반대쪽의 96
스위치핀은 GND 에연결합니다. 아두이노의디지털핀을스위치와저항이 만나는점 ( 노드 ) 에연결합니다. 이디지털핀은 digitalread() 라는함수를 이용하여값을읽을것입다. 아두이노디지털핀 13 번에연결되어있는내장형 LED 를사용할것이나 필요에따라서앞서설명된 LED 예제들을참고할수있습니다. int button1pin = 2; // 버튼스위치의 2 번핀 int ledpin = 13; // 아두이노에내장된 LED void setup() pinmode(button1pin, INPUT); // 버튼을인풋으로사용할것을설정 pinmode(ledpin, OUTPUT); // LED는아웃풋으로사용. 97
void loop() int button1state; // 버튼의입력값을저장할변수 button1state = digitalread(button1pin); // 버튼으로부터받은 0 혹은 1의값을저장 if (button1state == LOW) // 버튼이 LOW(0) 이면 digitalwrite(ledpin, HIGH); // LED를켜고 Else // 그렇지않으면 digitalwrite(ledpin, LOW); // LED를끈다. 98
8. D. 4x4 키패드이용하기 위의키패드는 8개의핀으로구성되어있으며아두이노의 Keypad 라이브러리를이용하여간단히테스트할수있습니다. 왼쪽에서오른쪽으로아두이노의디지털핀 2번에서 9번까지연결합니다. 그리고아두이노홈페이지에가셔서 Keypad 라이브러리를다운로드받고다음의소스코드를작성하여간단히테스트를할수있습니다. #include <Keypad.h> const byte ROWS = 4; const byte COLS = 4; char keys[rows][cols] = '1','2','3','A', '4','5','6','B', '7','8','9','C', '*','0','#','D' ; byte rowpins[rows] = 2,3,4,5; //connect to row pinouts 99
byte colpins[cols] = 6,7,8,9; //connect to column pinouts Keypad keypad = Keypad( makekeymap(keys), rowpins, colpins, ROWS, COLS ); void setup() Serial.begin(9600); void loop() char key = keypad.getkey(); if (key!= NO_KEY) Serial.println(key); 100
9. A 밝기에따른 DC 모터속도제어 조도센서는 CdS라는광전도셀을이용하여가시광선이없는곳에서는절연체와같이전류가흐르지않다가가시광선이닿으면도체와같이전류가잘흐르는성질을가지고있습니다. 빛을감지하여회로를 ON/OFF하거나센서및방범용모듈등에많이사용됩니다. 이번예제에서는조도센서를이용하여빛의세기를측정하고, 그세기에따라 DC모터의속도를제어하는프로그램을실행해봅시다. 준비물 : 아두이노우노, USB 케이블, 10k 옴저항, 조도센서, SN754410, DC 모터, 브레드보드, 점퍼케이블 따라하기 : Flex 센서, FSR 과같이조도센서도두개의다리를가지고있는일종의 저항입니다. 여기에앞서다루었던 DC 모터방향제어하기예제를 응용하여다음의회로를구성합니다. 101
다음의프로그램을업로드합니다. int sensorpin = 0; // 조도센서가연결될 A0핀 int speedpin = 3; // SN754410의 1,2EN 핀과 PWM핀에연결하였다. 속도제어용핀 int motor1apin = 6; // 1A int motor2apin = 7; // 2A int speed_value_motor1; // 모터스피드를위한변수 int lightlevel; // 조도센서로부터읽은값을저장할변수 void setup() pinmode(speedpin, OUTPUT); pinmode(motor1apin, OUTPUT); 102
pinmode(motor2apin, OUTPUT); void loop() lightlevel = analogread(sensorpin); // 센서로부터읽은값을저장 (0~1023) digitalwrite(motor1apin, LOW); // 1A에 LOW digitalwrite(motor2apin, HIGH); // 2A에 HIGH lightlevel = map(lightlevel, 0, 1023, 0, 255); // PWM 출력레벨 (8bit) 로센서값을맵핑 analogwrite(speedpin, lightlevel); // 밝기에따라모터회전속도출력 103
9. B. 장애물감지후모터의방향제어 앞에서소개된 QRD1114는 1cm 내에있는사물을감지하는데유용하게쓰이는센서입니다. 이센서를이용하여소형로봇의장애물감지를할수있으며모터의방향도제어할수있습니다. 보다먼거리의사물을감지하기위해서는적외선센서혹은초음파센서를이용할수있습니다. 준비물 : 아두이노우노, USB 케이블, QRD1114, 10k 옴저항, 220 옴저항, SN754410, DC 모터, 브레드보드, 점퍼케이블 따라하기 : 앞서다루었던 QRD1114 예제와 DC 모터제어예제를이용하여다음의 회로를구성합니다. 104
QRD1114가사물을감지했을때, 모터의방향을바꾸는예제를 if 명령어를이용하여다음과같이프로그램을작성할수있습니다. 프로그램을업로드한후, QRD1114센서를손가락으로막았다떼었다하면서모터의회전방향을체크할수있습니다. int speedpin = 3; // SN754410의 1,2EN 핀과 PWM핀에연결하였다. 속도제어용핀 int signal = 4; // 디지털핀4번으로센서값 (0 혹은 1) 을읽을변수. int onoff; // 4번핀에서읽은값이 High(1) 인지 Low(0) 인지저장할변수 int motor1apin = 6; // 1A int motor2apin = 7; // 2A int speed_value_motor1; // 모터스피드를위한변수 105
void setup() pinmode(speedpin, OUTPUT); pinmode(motor1apin, OUTPUT); pinmode(motor2apin, OUTPUT); void loop() onoff = digitalread(signal); // 불리언신호 (0 혹은 1) 을읽어서 onoff에저장 if(onoff == 1) digitalwrite(motor1apin, LOW); // 1A에 LOW digitalwrite(motor2apin, HIGH); // 2A에 HIGH else digitalwrite(motor1apin, HIGH); // 1A에 LOW digitalwrite(motor2apin, LOW); // 2A에 HIGH speed_value_motor1 = 127; // 0~255의수중선택가능함. 0: 속도제로, 255: 최고속도. analogwrite(speedpin, speed_value_motor1); // PWM 출력을하여정한속도만큼모터회전 106
9. C. 손가락으로서보모터제어하기 손가락에 Flex 센서를연결하여굽힌정도에따라서보모터를제어할수 있습니다. 앞에서다룬 Flex 센서예제와서보모터예제를통하여 손가락으로서보모터제어를구현해봅시다. 준비물 : 아두이노우노, USB 케이블, Flex 센서, 10k 옴저항, 서보모터, 브레드보드, 점퍼케이블 따라하기 : 앞서다루었던 QRD1114 예제와서보모터구동예제를이용하여다음의 회로를구성합니다. 107
다음의프로그램을업로드하여손가락의굽힌정도에따라서보모터가회전하는지체크해봅시다. 매 0.2초마다값을읽기때문에모터의속도가느리다면모터가회전하는중간에센서값을읽을수도있습니다. 테스트를하면서 delay() 함수를변경하여부드러운컨트롤을할수있습니다. #include <Servo.h> // 서보라이브러리 Servo motor1; // 서보모터오브젝트 108
int flexpin = 0; // 센서값을읽기위해아날로그핀 0 번을 flexpin 에지정한다. int motorangle; void setup() motor1.attach(9); // 서보모터를 9번에연결 void loop() int flexval; // 센서값을저장할변수 flexval = analogread(flexpin); // 아날로그를입력받음 (0~1023) motorangle = map(flexval, 0, 1023, 0, 180); motor1.write(motorangle); // 모터를 position만큼회전 delay(200); // 모터가돌때까지기다림. 109
9. D. 압력에따른 LED 의밝기제어 FSR( 압력센서 : Force Sensing Resistor) 을이용하여쉽게 LED 의밝기를조절할수 있습니다. 앞서 PWM 을이용한 LED 밝기조절예제와 FSR 을이용한압력측정 예제를통하여이를구현할수있습니다. 준비물 : 아두이노우노, USB 케이블, FSR 센서, 10k 옴저항, LED, 브레드보드, 점퍼케이블 따라하기 : FSR 과저항 (10k 옴 ) 을이용하여압력을측정하는예제를구현하고, LED 를 PWM 핀에연결한다. 다음의회로를참고합니다. 110
압력에따른 LED 밝기제어프로그램을업로드합니다. int led = 3; int brightness = 0; int increment = 1; int FSRpin = 0; // FSRpin을아날로그0(A0) 에연결 int Vo; // 센서값을저장할변수 float Rfsr; void setup() // analogwrite을통해구동되는핀은출력으로선언하지않아도된다. 111
void loop() Vo = analogread(fsrpin); // 아날로그를입력받음 (0~1023) brightness = map(vo, 0, 1023, 0, 255); analogwrite(led, brightness); // 밝기를출력한다 delay(10); 112
9. E. 키보드로모터방향제어하기 키보드로부터입력받은값을이용하여 DC 모터의회전방향을제어할수 있습니다. 이번예제에서는 A 를입력받으면정방향회전, B 를입력받으면역방향 회전, 그리고, C 를입력받으면정지하는시스템을구현하였습니다. 준비물 : 아두이노우노, USB 케이블, SN754410, DC 모터, 브레드보드, 점퍼 케이블 따라하기 : 다음과같이회로를구성하고, 아래의프로그램을업로드합니다. int speedpin = 3; int motor1apin = 6; // H-bridge leg 1 // H-bridge enable pin for speed control 113
int motor2apin = 7; // H-bridge leg 2 int ledpin = 13; // status LED int speed_value_motor1; // value for motor speed byte KeyInput; void setup() // set digital i/o pins as outputs: pinmode(speedpin, OUTPUT); pinmode(motor1apin, OUTPUT); pinmode(motor2apin, OUTPUT); pinmode(ledpin, OUTPUT); Serial.begin(9600); void loop() digitalwrite(ledpin, HIGH); // status LED is always on KeyInput = Serial.read(); if(keyinput == 'A') // put motor in forward motion digitalwrite(motor1apin, HIGH); // set leg 1 of the H-bridge low digitalwrite(motor2apin, LOW); // set leg 2 of the H-bridge high else if(keyinput == 'B') digitalwrite(motor1apin, LOW); // set leg 1 of the H-bridge low digitalwrite(motor2apin, HIGH); // set leg 2 of the H-bridge high else if(keyinput == 'C') digitalwrite(motor1apin, LOW); // set leg 1 of the H-bridge low digitalwrite(motor2apin, LOW); // set leg 2 of the H-bridge high 114
speed_value_motor1 = 127; // half speed analogwrite(speedpin, speed_value_motor1); // output speed as 시리얼모니터창을열어서 A, B, 혹은 C 를타이핑한후엔터입력을하여 모터의회전방향을체크할수있습니다.. 115
9. F. Visual Studio Express C# 와아두이노인터페이스 Microsoft의 Visual Studio Express C# 은무료개발툴로서 Microsoft홈페이지에서다운로드가가능합니다. C# 이란, C++ 의연산력 (computing power) 과 Visual Basic의편의성 (convenience) 을결합하기위한목적으로마이크로소프트사에서개발한객체지향프로그래밍언어입니다. C++ 가기반이며, 자바랑비슷한특징을지니고있습니다. 준비물 : 아두이노우노, USB 케이블, 10k 옴저항, FSR 센서 따라하기 : 다음의링크에서 Visual C# 2010 Express 를다운로드받습니다. http://www.microsoft.com/visualstudio/kor/downloads#d-express-windowsdesktop 지금설치버튼을누르면, vcs_web.exe 파일이다운로드되고, 이를더블 클릭하여실행합니다. 116
다음을클릭 다음을클릭 117
다음을클릭 저장할폴더를설정한후설치클릭 118
설치완료 119
설치된 Microsoft Visual C# Express 2010 을실행하면위의창이열립니다. 120
새프로젝트를클릭하여 Window Forms 응용프로그램을클릭후이름을 ArduinoInterface 라하고확인을클릭합니다. 위와같은창이열리며왼쪽에숨겨있는도구상자를클릭한후, 자동숨기기버튼 ( 압정모양의버튼 ) 을클릭하여도구상자를아래그림과 같이펼칩니다. 121
왼쪽의도구상자에서 SerialPort 를드래그하여오른쪽의 Form1 에 놓습니다. 도구상자에서버튼을클릭하여 Form1 에두개의버튼을넣어줍니다. 그리고마우스오른쪽버튼을클릭한후속성에들어가서 button1 과 button2 의이름 (Text) 를 LED ON, LED OFF 로바꾸어줍니다. 122
123
라벨을이용하여 Sensor Value 라는텍스트를넣어주고, RichTextBox 를 이용하여센서값이출력될빈텍스트상자를넣어줍니다. 이때, Form1을더블클릭하면다음과같이소스코드창으로넘어가게됩니다. Form1을더블클릭하였기때문에 Form1_load라는함수가생겼습니다. 마찬가지로두개의 LED ON, LED OFF 버튼을더블클릭하여소스코드에버튼클릭함수를넣어줍니다. 이번예제에서구현할 1) C# 에서버튼으로 LED 컨트롤하기, 2) FSR 센서값 C# 에디스플레이를하기위해, 다음의회로를구성합니다. 124
아두이노에다음의프로그램을업로드합니다. int FSRpin = 0; // FSRpin을아날로그0(A0) 에연결 int Vo; // 센서값을저장할변수 float Rfsr; void setup() pinmode(13, OUTPUT); Serial.begin(9600); // 센서값을읽기위해시리얼모니터를사용할것을설정. void loop() 125
if(serial.available()) int c = Serial.read(); if (c == '1') digitalwrite(13,high); else if (c == '0') digitalwrite(13,low); Vo = analogread(fsrpin); // 아날로그를입력받음 (0~1023) Rfsr = ((9.78 * Vo)/(1-(Vo/1023.0))); Serial.println(Rfsr); // println은줄바꿈명령이다. Rfsr의값을출력한다. C# 과아두이노인터페이스를구성하기위해시리얼포트를설정해야합니다. 시리얼포트를설정하기위해서는 Baudrate과포트번호를아두이노와동일하게설정하여야합니다. Serial.begin(9600) 에서 9600bps를사용하였기때문에 9600으로입력하고, COM10을사용하였기때문에, 다음과같이입력합니다. 여러분이사용하고있는포트번호를입력합니다. 다음의 C# 코드를앞서 Visual Studio C# 에치환합니다. C# 코드 using System; 126
using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO.Ports; namespace ArduinoInterface public partial class Form1 : Form string sensorval; public Form1() InitializeComponent(); serialport1.portname = "COM10"; serialport1.baudrate = 9600; serialport1.open(); private void Form1_Load(object sender, EventArgs e) private void button1_click(object sender, EventArgs e) 127
serialport1.write("1"); button1.enabled = false; button2.enabled = true; private void button2_click(object sender, EventArgs e) serialport1.write("0"); button1.enabled = true; button2.enabled = false; private void serialport1_datareceived(object sender, SerialDataReceivedEventArgs e) sensorval = serialport1.readline(); this.invoke(new EventHandler(DisplayText)); private void DisplayText(object sender, EventArgs e) richtextbox1.appendtext(sensorval); richtextbox1.scrolltocaret(); 128
상단의디버깅시작버튼혹은 F5 를누르면프로그램이실행되고다음의 창이열립니다. LED ON 버튼을누르면아두이노의 LED 가켜지고, LED OFF 버튼을누르면 LED 가꺼지는것을확인할수있습니다. 센서값도실시간으로 업데이트가되는것을확인할수있습니다. 129
9. F. 매틀랩을이용한센서값디스플레이 매틀랩 (MATLAB) 은 Mathworks사에서개발된수치해석및프로그래밍환경을제공하는공학용프로그램입니다. 많은공학도들이매틀랩을이용한과제및연구를하고있기에이번예제에서는실시간으로변하는센서값을매틀랩에서보여주는기본적인프로그램을작성하겠습니다. 앞서소개된 FSR을이용한회로도를다시구성해보도록하겠습니다. 준비물 : 아두이노우노, USB 케이블, 10k 옴저항, FSR 센서 따라하기 : FSR 과 10k 옴저항을이용하여다음의회로를구성합니다. 아두이노에다음의프로그램을업로드합니다. 130
int FSRpin = 0; // FSRpin을아날로그0(A0) 에연결 int Vo; // 센서값을저장할변수 float Rfsr; void setup() Serial.begin(9600); // 센서값을읽기위해시리얼모니터를사용할것을설정. void loop() Vo = analogread(fsrpin); // 아날로그를입력받음 (0~1023) Rfsr = ((9.78 * Vo)/(1-(Vo/1023.0))); Serial.println(Rfsr); // println은줄바꿈명령이다. Rfsr의값을출력한다. 매틀랩을실행합니다. 매틀랩초기시작화면 131
매틀랩스크립트를열어서다음의코드를작성합니다. instrreset serialobj = serial('com10','baudrate',9600); fopen(serialobj); i=1; while(1) a = str2num(fscanf(serialobj)); plot(i,a,'*'); hold on drawnow i=i+1; end 그리고, 실행을하면, 다음과같이센서값이실시간으로출력되는것을 확인할수있습니다. 132
이때, while(1) 이라는무한루프에서빠져나오기위해서 Ctrl + C 이용할수 있습니다. 133