이전 시간에는 아두이노 공식 포럼에서 제공한 시리얼 클래스 라이브러리를 사용하여 아두이노와 시리얼 통신을 해보았다.
이번에는 단순 시리얼 통신이 아니라 프로토콜을 직접 만들어서 통신을 해보겠다.
프로토콜 통신은 전자장비 간에 통신하는 규칙을 말하며 직접 만들어서 통신이 가능하게끔 만들어 볼 것이다.
규칙은 간단하게 가장 앞 기호가 "#"이 들어가면 다음 명령어와 값에 따라 아두이노를 제어할 수 있도록 만들어보자
이전 프로젝트 파일을 열어서 수정을 해보자
cpp 코드는 입력된 내용을 아두이노로 전달하고, 아두이노는 입력된 값을 검산하여 규칙에 맞다면 내장 LED를 제어한다
여기서의 프로토콜 규칙은 다음과 같다.
'#'으로 시작하며 '+'로 구분을 하고, 앞 뒤로 커맨드와 데이터 값으로 분류하는 것이다.
cpp 파일을 구동하여 "#LED+ON"을 입력하면 LED가 500ms 간격으로 점멸할 것이다.
"#DELAY+숫자"를 입력하면 입력된 숫자만큼의 간격으로 점멸한다.
위 방식은 String 문자열을 활용한 프로토콜 통신 방법이다.
간단한 프로젝트나 사용자에게 쉬운 이용방식을 제공하기에는 매우 좋다.
추가로 공부하고싶다면 아두이노 공식 포럼의 String 페이지를 참고하자
https://www.arduino.cc/reference/en/language/variables/data-types/stringobject/
String() - Arduino Reference
Description Constructs an instance of the String class. There are multiple versions that construct Strings from different data types (i.e. format them as sequences of characters), including: a constant string of characters, in double quotes (i.e. a char ar
www.arduino.cc
하지만 실시간으로 데이터를 주고 받아 String 문자열을 계속 검산하기에는 아두이노에게 있어 효율적이지 않다.
따라서 String이 아닌 새로운 프로토콜 방식을 공부해보자, cpp 코드와 아두이노 코드는 다음과 같다
아마 코드를 보면 이게 뭐지.. 싶을 것이다
원리는 간단하다 아두이노에서 전송한 4개의 바이트 데이터를 검산하여 데이터를 추출하는 것이다.
cpp 파일의 루프 속도가 너무 빨라서 아두이노에서 전송한 속도를 연속적으로 한번에 다 잡아내지 못한다.
따라서 순차적으로 데이터를 쌓아 처리하는 방식이다.
{ 0xFF, 0xFF, Data High, Data Low } 의 프로토콜 형식을 만든 것이다.
cpp 코드는 0xFF의 값을 순서대로 입력받은 경우 다음 데이터를 data 값으로 계산하고, 0xFF를 검산하는 과정에서 다른 값이 들어온다면 index 변수를 초기화하여 다시 검산하는 것이다.
SP->ReadData(incomingData, 1) 함수에서 dataLength 자리에 1을 사용하였다. 1개의 데이터를 받는 경우 데이터가 존재하는지를 판단하도록 한 것이다.
여기서 의문점이 들 것이다. 4개의 바이트 데이터를 받게 조건을 걸어주면 4개의 데이터를 바로 처리할 수 있지 않을까?
답변은 컴퓨터의 처리속도와 아두이노의 데이터 전송속도가 다르기 때문에 4개의 데이터를 받을 때도 있지만 2개, 2개 또는 3개, 1개 등의 경우로 데이터가 나눠지기 때문에 손실이 일어난다. 따라서 위와 같이 스택과 비슷한 구조를 활용하여 데이터를 수신하면 빠르고 정확한 데이터를 수신받을 수 있다. String 문자열을 사용한 것과 비교하면 매우 빠르게 데이터를 통신할 수 있는 것이다.
컴퓨터에서 아두이노로 데이터를 전송할 때 마찬가지로 저 방식을 그대로 사용해도 좋다.
해당 라이브러리에서 사용하는 방식은 데이터를 읽으면서 데이터 존재 유무 및 개수를 파악하기 때문에 데이터의 개수를 파악하기에 어려움이 있다.
그렇기에 컴퓨터에서 아두이노로 데이터를 전송할 때의 방식을 공부해보자
다음 코드를 참고해보자
아두이노의 경우 시리얼 통신중 버퍼에 저장된 데이터의 개수를 알 수 있기 때문에 위와 같이 코딩이 가능하다.
위는 cpp -> 아두이노 로 보낸데이터를 다시 수신받아 화면에 표시한다
C# 언어의 경우 시리얼 통신중 버퍼에 저장된 데이터 개수를 알 수 있어서 위 아두이노 코드와 유사하게 만들어도 된다.
cpp의 경우 찾은 자료와 나의 경험으로는 저 정도의 코딩이 한계인 것 같다.
나중에 더 좋은 방법을 찾는다면 그 방법에 맡기도록하자.
위 방식은 모두
{ 0xFF, 0xFF, Data High, Data Low } 의 프로토콜 형식을 사용하였다.
하지만 더욱 정확하고 안전하게 데이터 송수신을 위해서는 패리티 체크를 하여 패킷의 손상을 파악할 수 있다.
예를 들면 { 0xFF, 0xFF, Num, Data_1_High, Data_1_Low, ... , Data_NUM_High, Data_NUM_Low, Check_Sum_High, Check_Sum_Low } 를 사용할 수 있다.
위는 평소 프로젝트의 데이터 송수신에서 Num 개의 데이터를 다를때 자주 사용하는데, Check_Sum의 값을 수신한 데이터 모두의 합 또는 0xFFFF - Sum 을 하여 현재 패킷이 손상되었는지 또는 패킷의 데이터가 체크섬까지 잘 도달했는지 등을 파악할 수 있다.
'아두이노 (Arduino) > 통신 (Communication)' 카테고리의 다른 글
[Serial] 3. C# 아두이노 센서값 실시간 동기화하기 (3) | 2021.11.09 |
---|---|
[Serial] 2. C# 아두이노 실시간 제어하기 (0) | 2021.11.07 |
[Serial] 1. C# 아두이노와 시리얼 통신하기 (0) | 2021.11.07 |
[Serial] 1. C++ 아두이노와 시리얼 통신하기 (0) | 2021.07.29 |