?>

Hard Copy World

HCW

Arduino beginner

Home > Learning >

Arduino beginner

아두이노 기초 강좌 7 – Serial 입출력

페이지 정보

작성자 최고관리자 쪽지보내기 메일보내기 홈페이지 자기소개 아이디로 검색 전체게시물 작성일14-10-02 16:24 조회8,216회 댓글2건

본문

아두이노 기초 강좌는 아두이노를 처음 접하시는 전자분야 비 전공자를 위한 강좌입니다. 이해를 위해서는 간단한 프로그래밍 지식이 필요할 수 있습니다. 프로그래밍이 처음이라면 [아두이노 프로그래밍 기초] 강좌를 먼저 읽으시길 권해 드립니다.

===============================================================

 

아두이노에서 가장 자주 사용되는 기능 중 하나가 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(송신) 용 핀입니다.

 

ArduinoUno_r2_front450px

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)  

추천 0
  • 페이스북으로 보내기
  • 트위터로 보내기
  • 구글플러스로 보내기

댓글목록

SY월드님의 댓글

SY월드 쪽지보내기 메일보내기 자기소개 아이디로 검색 전체게시물 작성일

좋은 강좌를 잘 보고 있습니다. 덕분에 많이 배우고 있습니다. 아두이노 홈페이지에서 Serial.available() 함수를 찾아보니, 입력된 문자열의 바이트를 얻는다고 되있네요. 그런데 강의에는 true를 반환한다고 되 있어서요. 1바이트를 얻기 때문에 true라고 보시는건가요??ㅎㅎ;;;제가 C도 초급이고 해서 질문 드립니다.

최고관리자님의 댓글

최고관리자 쪽지보내기 메일보내기 홈페이지 자기소개 아이디로 검색 전체게시물 댓글의 댓글 작성일

아두이노가 시리얼 통신 포트를 통해 데이터를 받으면 일단 시리얼 버퍼라는 곳에 저장해 둡니다. available() 함수는 버퍼에 저장된 (읽지 않은) 데이터가 몇 바이트 인지 알려주는 함수입니다. 따라서 0을 리턴하면 수신한 데이터가 없다는 뜻이고, 1 이상이면 수신한 데이터가 있다는 뜻입니다.
available() 함수는 단지 버퍼에 데이터가 몇 바이트 쌓여있는지 체크만 합니다. 실제 데이터를 읽어오는 함수는 read() 함수이고 read() 가 실행되면 버퍼에서 데이터를 읽어서 리턴해줍니다. 그리고 버퍼에서 읽은 데이터는 삭제됩니다.