[아두이노] [강좌] 17. Serial 통신(3) - 유용한 기능들
지난 강좌에서 시리얼 통신을 사용하기 위한 기본 함수 begin(), print()/println(), available(), read() 함수에 대해 설명했었다. 사실 이 함수들만 알고 있어도 시리얼 통신을 이용하는 데에는 전혀 지장이 없지만, 시리얼 통신을 더 편하게 사용할 수 있도록 아두이노가 제공하는 함수들이 있다. 아두이노는 친절하니까요.
이번 강좌는 함수 설명으로만 이뤄져서 좀 심심할지도. 그럼 시~작!
Serial.write(value)
Serial.write(buffer, length)
Serial.print() 함수와 마찬가지로 시리얼 데이터를 송신하는 기능을 하지만, 다른 점은 value 값에 byte 형과 문자열밖에 올 수 없다는 점이다. 즉, 숫자를 넣어도 그 숫자가 문자로 변환되지 않는다는 것. 매개 변수로 byte 형 배열과 배열의 길이를 줘서 배열에 저장된 값을 순차적으로 전송할 수도 있다.
매개 변수 value : byte 형 데이터 또는 문자열. buffer : byte 형 배열의 이름 length : 전송할 배열의 길이 또는 전송할 데이터의 개수 |
Serial.write() 함수는 시리얼 통신으로 문자가 아닌 데이터를 전송할 때 주로 이용된다. 예제에서 해 본 PC의 시리얼 모니터 프로그램과 통신할 때에는 시리얼 모니터 프로그램이 무조건 문자로만 읽기 때문에 Serial.print() 함수를 주로 이용하지만, 블루투스나 지그비 등 다른 모듈과 통신할 때에는 문자 외에 직접 데이터 값을 지정하여 보내야 하는 경우도 많다. 그럴 때 write() 함수를 사용한다.
long Serial.parseInt()
시리얼 통신으로 수신되는 데이터가 숫자를 나타내는 문자열일 경우, 그 값을 숫자로 변환하여 long 타입으로 반환한다. 예를 들어 시리얼 통신으로 ‘1’,’0’,’0’ 이라는 문자가 차례로 들어올 경우 이 값을 읽어 100이라는 숫자로 변환하여 반환하는 것.
반환 값
long 형 숫자 : 변환 된 숫자 값. 숫자가 아닌 문자가 들어올 경우 0을 반환.
|
print() 함수 설명 때 아스키 코드에 대해서 설명했었고, 시리얼 모니터 프로그램은 받은 데이터를 무조건 ‘문자’로만 인식한다고 설명했었다. 이 점은 데이터를 보낼 때도 똑같이 적용되어, 입력된 데이터를 모두 ‘문자’로 인식하고 그 문자에 해당하는 아스키 코드 값을 보내게 된다.
그래서 시리얼 모니터 프로그램의 입력 창에 “100”이라고 입력하면 100이라는 값이 전송되는 것이 아니라 ‘1’, ‘0’, ‘0’이라는 3개의 문자가 전송되는 것. 이 문자를 가지고 숫자인지 아닌지, 숫자라면 얼마를 나타내는 숫자인지 판독해서 그 값을 반환하는 함수가 바로Serial.parseInt() 함수.
역시 아두이노는 친절하다.
예를 보자.
void loop() { if(Serial.available() > 0) { long readValue1 = Serial.parseInt(); long readValue2 = Serial.parseInt();
Serial.print(readValue1); Serial.print(" "); Serial.println(readValue2); } } |
setup() 함수에 Serial.begin() 함수로 초기화 해주는 건 이제 말 안 해도 알고 있을거라 따로 써주지 않았다. 위 코드를 업로드한 후 시리얼 모니터 프로그램을 열자. 그리고 입력 창에 “100,200”이라고 입력한 뒤 “Send” 버튼 또는 Enter.
위 그림처럼 100과 200이 나란히 출력된 것을 확인할 수 있다. 물론 Serial.parseInt() 함수를 한 번만 사용해서 하나의 수만 입력 받을 수도 있다.
유의해야 할 점은 데이터를 전송할 때 숫자 데이터의 맨 마지막에 숫자가 아닌 다른 문자가 붙는다면 Serial.parseInt() 함수가 한번 더 실행되어 0을 반환한다는 점. 오른 쪽 아래의 “No line ending” 설정을 바꿔 줄바꿈 문자 등을 자동으로 붙일 경우에도 0이 한번 더 반환되므로 꼭 유의할 것!
float Serial.parseFloat()
int 형으로 바꿔주는 함수만 있다면 섭하지. 숫자 문자를 입력 받아 float 형의 데이터로 변환해 반환한다.
반환 값
float 형 데이터 : 변환된 float 형 데이터. 숫자가 아닌 문자가 들어올 경우 0을 반환. |
byte Serial.readBytes(buffer, length)
지정한 개수만큼 읽어와 버퍼에 저장한다. 길이가 정해진 데이터를 수신할 때 유용하다. 지정한 개수만큼 데이터가 수신되지 않을 경우 수신된 개수만큼만 저장하고 그 개수를 반환한다.
매개 변수
buffer : 데이터를 저장할 char형 배열 이름
length : 읽어 올 데이터의 길이 |
반환 값 byte 형 데이터 : 읽어온 데이터의 길이. |
byte Serial.readBytesUntil(character, buffer, length)
지정한 문자가 수신될 때까지 데이터를 읽어온다. 단, length 값으로 지정한 개수를 넘지 않는다. 읽어 온 데이터의 개수를 반환한다.
매개 변수
character : 수신 종료를 의미할 문자
buffer : 데이터를 저장할 char형 배열 이름
length : 읽어 올 데이터의 최대 길이 |
반환 값
byte 형 데이터 : 읽어온 데이터의 길이 |
단, 유의해야 할 점은 character 값으로 지정한 문자는 버퍼에 저장되지 않는다는 점.
Serial.setTimeout(timeout)
Serial.readBytes() 함수나 Serial.readBytesUntil() 함수에 사용되는 타임아웃 시간을 설정한다. 즉, 지정한 길이만큼 데이터가 수신되지 않았을 때 수신을 기다리는 최대 시간을 의미. 타임 아웃 시간은 Serial.parseInt() 함수나 Serial.parseFloat() 함수에도 이용된다. 기본으로 1초가 설정되어 있다.
매개 변수
timeout : 설정할 타임 아웃 시간. 밀리초 단위로 설정한다. (unsigned long 타입) |
Serial.end()
시리얼 통신 연결을 끊고, 사용되던 핀(Serial. 일 경우 0번, 1번 핀)을 일반 디지털 IO 핀으로 사용하게 한다. 다시 시리얼 통신을 사용하기 위해서는 Serial.begin() 함수를 사용하면 된다.
serialEvent()
이 함수는 호출하기 위한 함수가 아니라 기능을 정의하기 위한 함수이다. 아두이노는 시리얼 통신을 통해 데이터가 수신되면 자동으로serialEvent() 함수를 호출하도록 되어 있다. 물론 정의하지 않아도 상관없다. 다음 예제 소스는 지난 강좌의 SerialReadTest.ino 예제 소스와 동일한 동작을 하도록 수정한 소스 코드이다.
SerialReadTest2.ino |
void setup() { Serial.begin(9600); }
void loop() { }
void serialEvent() { char c = Serial.read(); Serial.print("rx : "); Serial.println(c); }
|
업로드 한 후 실행해보자. loop() 함수에 아무 내용이 없고, serialEvent() 함수를 호출하는 소스 코드가 없는데도 불구하고 SerialReadTest.ino 예제의 결과와 동일하게 출력된다.
자동으로 호출된다규. 함수명 틀리지 않도록 주의!
시리얼 통신은 PC와 아두이노 보드간의 통신 외에도 블루투스 모듈, 지그비 모듈, JPEG 카메라 등 많은 모듈간의 통신에 이용된다. 그러니 모든 함수에 대해서는 아니더라도 기본 함수에 대한 내용은 꼭 인지하고 있도록 하자.
음? 데자뷰인가, 지난 강좌에서 했던 얘기 같은데.
그럼 이만, 뿅!