아두이노 기초 강좌는 아두이노를 처음 접하시는 전자분야 비 전공자를 위한 강좌입니다. 이해를 위해서는 간단한 프로그래밍 지식이 필요할 수 있습니다. 프로그래밍이 처음이라면 [아두이노 프로그래밍 기초] 강좌를 먼저 읽으시길 권해 드립니다.
=============================================================
.
아래에서는 아두이노에서 시리얼 통신을 다루는 기본 방법을 설명합니다. Serial 통신 표준의 상세 내용, 기타 I2C, SPI 통신에 대한 상세 내용이 필요하시면 아래 링크를 참고하세요.
아두이노에서 가장 자주 사용되는 기능 중 하나가 Serial 입출력입니다. 아두이노에 작성한 프로그램을 업로드 할 때, 아두이노 IDE에서 Serial Monitor로 메시지를 확인할 때 사용되는 것이 바로 Serial 통신입니다. 아두이노에서는 별다른 디버깅 도구가 없기 때문에 내가 만든 프로그램이 문제가 있을 경우 어디가 문제인지 찾기 위해 코드 곳곳에 Serial 통신 함수들을 넣어둡니다. 그러면 PC에서 Serial Monitor를 통해 지금 어떻게 동작하고 있는지 체크할 수 있겠죠.
1. Hardware serial
아두이노는 Serial 통신 기능과 이를 사용하기 위한 함수를 내장하고 있습니다. 이것을 Hardware Serial 이라고 합니다. Hardware serial 용으로 디지털 0, 1번 핀이 예약되어 있는데(UNO 보드 기준) 아래 아두이노 UNO 보드를 보시면 0번, 1번 핀이 RX, TX 라고 표시되어 있는 것을 알 수 있습니다. Serial 통신에서 사용되는 데이터 RX(수신), TX(송신) 용 핀입니다.
PC에서 프로그램을 업로드 할 때 사용되기 때문에 업로드 할 때 이 핀이 다른 용도로 사용중이라면 업로드가 되지 않고 아래와 같은 에러 메시지를 출력합니다.
avrdude: stk500_getsync(): not in sync: resp=0×00
물론 0, 1번 핀을 PC가 아닌 다른 모듈과의 Serial 통신에도 사용할 수 있습니다. 하지만 일단은 PC와 USB로 연결해서 사용될 때를 기준으로 설명하고 마지막에 다른 모듈에 사용하는 방법을 정리하겠습니다.
2. Serial – 데이터 송신
Serial 통신을 통해 PC로 데이터를 전송하는 가장 기본적인 방법은 아래와 같습니다.
void setup(){ Serial.begin(9600); } void loop(){ Serial.print(78); // "78" Serial.print("Hello world."); // "Hello world." Serial.print("\n"); Serial.println(78); // "78" Serial.println("Hello world."); // "Hello world." Serial.println(""); Serial.write(78); // send a byte with the value 78 Serial.write(“hello”); //send the string “hello” and return the length of the string. Serial.println(""); }
먼저 Serial 통신을 사용하겠다고 선언을 해야합니다. setup() 함수 안에서 아래처럼 선언하면 Serial 통신을 사용할 수 있습니다.
Serial.begin(9600);
9600 이 의미하는 것은 통신 속도입니다. Baud rate (보레이트, bit per second 단위) 라고 합니다. 주의할 점은 여기서 지정한 통신 속도와 Serial 통신으로 연결되는 상대방이 지정하는 통신 속도가 일치해야 한다는 점입니다. 여기서는 USB 를 통해 PC와 연결되므로 아두이노 IDE – Serial Monitor 에 설정된 통신 속도가 일치해야 합니다. Serial Monitor 를 실행해보면 하단부에 통신 속도를 선택할 수 있는 옵션이 있습니다.
Serial.begin() 으로 통신이 준비되면 아래 함수들을 이용해서 데이터를 전송할 수 있습니다.
Serial.print(), Serial.println(), Serial.write()
먼저 print() 와 println()은 동일한 역할을 합니다. 배열을 제외한 어떤 변수든 넣으면 그 값을 출력해줍니다. 다만 println() 함수는 값을 출력한 뒤에 줄넘김 문자를 붙여주는 차이입니다.
write() 함수는 1 byte, 1개의 문자, 문자열, 배열을 출력할 때 사용합니다. 보통 문자열 외에 저장해 둔 데이터 값을 순차적으로 보낼 때 사용합니다.
이제 위 예제코드가 어떻게 Serial 통신으로 데이터를 전송하는지 확인해 보겠습니다. 프로그램을 업로드하고 아두이노 IDE – Serial Monitor를 실행하면 아래와 같은 내용이 반복해서 찍힐겁니다.
———————————————
78Hello world.
78
Hello world.
Nhello
———————————————
줄넘김이 어떻게 처리되었는지 유심히 보세요. 그리고 write(78) 이 N으로 바뀐 점도 중요합니다. write(78) 은 78 (16진수로 4E)에 해당하는 아스키(ASCII) 문자를 출력했습니다. print() 에서는 숫자를 입력하면 문자열로 바꿔서 전송하지만 write() 에서는 숫자를 그대로 전송하기 때문에 수신측에서 문자로 인식해서 78에 해당하는 아스키 문자 – N 을 출력합니다.
3. Serial – 데이터 수신
Serial을 디버깅 용도로 사용할 때는 위 예제에서 사용하는 정도로도 충분하지만 PC에서 아두이노로 데이터를 보내주고 이걸 받아서 처리하고 싶을 때는? 혹은 아두이노와 다른 Serial 통신 모듈이 연결되었을 때 다른 모듈에서 보내주는 데이터를 받을 때는 어떻게 해야 할까요?
아래 예제는 Serial 을 통해 수신한 데이터를 그대로 다시 Serial 을 통해 송신하는 Serial echo 예제입니다. 즉 PC에서 뭔가를 보내주면 그걸 수신해서 그대로 PC로 다시 보내버리는 예제입니다.
void setup() { Serial.begin(9600); } void loop() { if (Serial.available()) { Serial.write(Serial.read()); } }
예제는 엄청 간단합니다.
setup() 함수에서 Serial.begin() 을 통해 Serial 통신을 준비합니다. 그리고 Serial.available() 함수를 실행합니다. available() 함수는 Serial 을 통해 수신한 데이터가 있을 때 true를 리턴해 줍니다. 따라서 수신한 데이터가 없으면 loop() 구문을 계속 돌면서 available() 함수를 실행해서 들어온게 없나 체크하고 들어온 데이터가 있으면 아래 라인을 실행합니다.
Serial.write(Serial.read());
Serial.read() 함수가 바로 수신한 데이터를 1byte 씩 읽어오는 함수입니다. read() 를 실행하면 1byte char 를 리턴해주는데 이걸 그대로 Serial.write() 함수에 사용했습니다. 따라서 수신한 데이터를 그대로 송신해 버리겠죠.
아두이노 IDE 실행해서 Serial Monitor 를 엽니다. 그리고 Serial Monitor 창 상단, 문자열 입력하는 부분에 영문으로 아무거나 입력해보세요. 그럼 입력한대로 다시 수신해서 보여줄겁니다.
Serial 통신을 이용한 데이터 수신은 위 예제코드를 입맛에 맛게 변형해서 사용하면 됩니다.
4. Software Serial
(이번 절의 내용은 보다 심화된 학습 내용입니다. 이해가 어려우면 그냥 넘어가셔도 됩니다. 추후에 다시 다룰 내용입니다.)
위에서 0번과 1번 핀은 Hardware serial 로 예약된 핀이고 Serial.xxx() 함수로 사용한다고 했습니다. 그럼 PC와의 연결에 Serial 통신을 사용해 버렸는데 다른 Serial 통신 모듈과는 어떻게 통신해야 할까요?
크게 두 가지 방법이 있습니다.
(1) SoftwareSerial 을 사용하는 방법
SoftwareSerial 이란 디지털 핀 2개를(0, 1번을 제외한) 이용해서 Serial 통신을 하는 방법을 말합니다. 그리고 Serial.xxx() 함수들을 대신할 수 있도록 전용의 SoftwareSerial 라이브러리가 제공되고 있습니다. 블루투스 모듈을 보통 이런 방법으로 사용합니다. 아래 예제처럼 사용이 가능합니다.
/* Software serial multple serial test Receives from the hardware serial, sends to software serial. Receives from software serial, sends to hardware serial. The circuit: * RX is digital pin 10 (connect to TX of other device) * TX is digital pin 11 (connect to RX of other device) Note: Not all pins on the Mega and Mega 2560 support change interrupts, so only the following can be used for RX: 10, 11, 12, 13, 50, 51, 52, 53, 62, 63, 64, 65, 66, 67, 68, 69 Not all pins on the Leonardo support change interrupts, so only the following can be used for RX: 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI). created back in the mists of time modified 25 May 2012 by Tom Igoe based on Mikal Hart's example This example code is in the public domain. */ #include <SoftwareSerial.h> SoftwareSerial mySerial(10, 11); // RX, TX void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); Serial.println("Goodnight moon!"); // set the data rate for the SoftwareSerial port mySerial.begin(9600); } void loop() // run over and over { // Receive from bluetooth and send it to PC if (mySerial.available()) Serial.write(mySerial.read()); // Receive from PC and send it to bluetooth if (Serial.available()) mySerial.write(Serial.read()); }
앞서 다루었던 echo 예제와 비슷한데, 여기서는 PC에서 받은 데이터는 블루투스로 보내주고 블루투스에서 받은 데이터는 PC로 보내주도록 작성된 겁니다.
일단 아래 두 라인을 파일 제일 위에 선언해서 SoftwareSerial 을 파일에서 사용가능하도록 설정해줍니다.
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11);
여기서 mySerial(10, 11) 부분이 중요합니다. 이렇게 선언하면 이후 코드에서는 mySerial.xxx() 형태로 Serial 함수들을 사용할 수 있습니다. 10-11은 Serial 모듈의 RX, TX 핀을 연결한 아두이노 디지털 핀 번호입니다. 소스코드에서 mySerial.xxx() 로 사용한 코드들이 10, 11번 핀으로 Serial 통신을 하기위한 함수들입니다.
(2) 0, 1 번 Hardware Serial 을 사용
PC와의 연결없이 독립적으로 동작한다면 굳이 SoftwareSerial 을 사용하지 않아도 됩니다. 그냥 0, 1번 핀에 모듈을 물려서 Serial.xxx() 함수들을 사용하면 됩니다. 단, 아래 주의사항만 지키면 됩니다.
– 소스코드를 업로드 할 때 0, 1번 핀이 다른 모듈에 의해 사용중이면 안됩니다. 따라서 0, 1번 핀에 연결된 모듈을 제거하고 소스코드를 업로드 한 다음 다시 연결하고 리셋해야 합니다. (일부 보드에서는 굳이 모듈을 제거하지 않고도 업로드가 가능하도록 지원하기도 합니다.)
– 통신에 문제가 있을 경우 문제가 되는 곳을 추적할 방법이 없으므로 SoftwareSerial 을 사용해서 소스코드를 안정화 시킨 다음 Hardware serial로 바꿔주는 것이 좋습니다.
초급이라 하기에는 조금 어려운 감이 있습니다만.. 일단 Serial을 통해 문자열을 출력하는 방법을 익히고, 나머지는 이런 내용이 있다는 정도를 알아두시고 넘어가시면 되겠습니다. 추후 관련된 문제가 나오거나 상세 정보가 필요할 경우 복습하시고 상세한 내용은 아래 링크를 참고하세요.
Serial 통신과 아두이노에서 지원하는 함수들 : http://arduino.cc/en/Reference/Serial
SoftwareSerial 상세 : http://arduino.cc/en/Tutorial/SoftwareSerialExample
===============================================================
이 문서는 작성자의 동의없이 개인적인 목적 외의 상업적인 목적으로 활용되어서는 안됩니다.
이 문서의 일부 혹은 전체를 수정, 삭제, 재배포 하여서는 안됩니다.
작성자 : GodsTale (godstale@hotmail.com)
작성하신 글 잘읽었습니다. 한가지 궁금한점이 있어서 질문드립니다. 현재 하나의 프로젝트를 진행중인데 하나의 아두이노에는 블루투스로 안드로이드와 통신을 하고 안드로이드에서 데이터를 받은 후, 다른 아두이노에 그 데이터를 전송하려고 합니다.
두 아두이노간의 통신을 xbee를 통해 무선으로 데이터를 송수신하려고 하는데 안드로이드에서 데이터는 softwareSerial로 받고, 다른 아두이노에 전송할 데이터는 hardwareSerial로 데이터를 받을 수 있는지. 하나의 아두이노가 두개의 serial 통신이 모두 가능한지 궁금해서 댓글남깁니다.
네 가능합니다. 소스코드 업로드 때는 하드웨어 시리얼 포트를 잠시 분리해두고 업로드 끝나면 다시 연결해서 재부팅하고 사용하면 됩니다.
ㅇㅅㅇ!
안녕하세요. 좋은글 잘읽었습니다. 한가지 궁금한점이 있어서 문의 드립니다. 간단하게 USB시리얼로 아두이노에서 데이터를 받아온뒤 바로 다시 USB로 되어 잇는 zigbee로 시리얼통신으로 데이터를 전송할수 있는지 궁금합니다.
네 프로그램만 적절히 짜면 가능합니다.
안녕하세요 좋은 정보 감사합니다. 제가 xbee 양방향 통신을 구현하고있는데요
1번 xbee에서 열번 숫자를 보내면 2번 xbee가 열개의 숫자데이터를 평균을 내서 다시 1번 xbee로 보내는 코드를 짜고있습니다 그런데 잘 안되네요 ㅠㅠ 문자열로 데이터를 받아오는데 숫자로 읽어올순없을까요… 제가하려는게 가능한건지도 잘 모르겠어요 ㅠㅠ
새로 개편한 홈페이지 QnA 게시판에서 드린 답변인것 같네요.
http://www.hardcopyworld.com/gnuboard5/bbs/board.php?bo_table=qna
정말 감사합니다. 덕분에 잘 배워갑니다!
안녕하세요 글 잘읽었습니다. 제가 프로젝트를 진행중인데 시리얼 통신을 할때 수신값을 변수로 다른 동작을 제어할 수 있는 가능성이 아두이노에 있을까요?
네 가능합니다.
아래의 글을 보면 소프트웨어 시리얼 라이브러리는 인터럽트를 사용하기에 아두이노 우노에서 PCINT 적용 가능한 2,3번 핀에 연결하라고 되어있는데 위 예제에서는 10,11번핀을 사용중이네요. 저 같은 경우에는 아두이노 프로미니를 자주사용하는데 핀번호 8,9나 10,11 사용시에도 통신이 잘되구요. 혹시 우노나 메가 같은 보드에서만 PCINT 적용가능한 포트에 연결해야 하는건가요? 이와 관련해서 정보좀 주셨으면 감사하겠습니다.
아래글 : http://www.hardcopyworld.com/ngine/aduino/index.php/archives/360
저는 아두이노는 전혀모르는 초보인데요 아두이노에 센서를 달아 헬륨풍선을 달아 띄워올린뒤 다시받아 갑등의 정보를 얻고 싶습니다. 어떻게 해야할까요?
좋은 글 감사합니다. 이해가 잘 되네요
올려주신글 아주 잘 읽었습니다. 감사합니다.
현재 고등학교 친구들과 프로젝트를 하나하고 있습니다. 궁금한것이 있어 글남김니다.
제가 온도센서로 모터동작을 구현하고 싶은대 이건 그럼 소프트웨어 시리얼을 사용해야하나요?
좋은 글 너무 감사드립니다! 덕분에 공부하고 가요 ^^
자세히 설명해주셔서 정말 감사합니다. 초보에게 딱 유용한 정보입니다.
고맙습니다
도움을 주셔서 고맙습니다
안녕하세요
고맙습니다