[아두이노] [강좌] 46. 블루투스 통신 (5) - 프로토콜 만들기 (2)

드디어 블루투스 통신의 마지막 강좌. 


지난 강좌에 이어 프로토콜을 만들어 데이터를 주고받는 실습을 해보자. 지난 강좌에서는 스마트 폰에서 데이터를 보내고, 아두이노에서 받은 데이터를 분석하여 LED를 켜고 끄거나, 모터를 돌리고 멈추는 실습을 진행했었다. 


 

그리고 데이터의 길이를 유동적으로 사용하고, 연속해서 들어오지 않을 경우를 방지하기 위해 '시작 문자'와 '종료 문자'를 사용한 프로토콜에 대해서도 알아봤었다. 



다시 한 번 말하지만, 프로토콜은 사용하는 사람 마음대로 정하면 된다. 단, 보내는 쪽과 받는 쪽에서 같게 적용되어야 하고.



지난 강좌에서 예고한대로, 이번 강좌에서는 스마트 폰에서 모터의 속도를 제어하는 실습과, 아두이노에서 스마트 폰으로 값을 전달하는 실습을 진행할 예정이다. 




우선 모터 속도 제어 실습.


LED를 켜고 끄는 기능에 모터 기능까지 추가해보자. '시작 문자'는 이전 예제와 마찬가지로 '#'을 사용할거고,N'종료 문자'는 '@'를 사용할거다. 



참고로, 아스키 코드 중에는 코드 번호 0x02가 "STX"라는 시작 문자로 지정되어 있다. 0x03은 "ETX",N'종료 문자'. 하지만 "STX"나 "ETX" 문자를 사용하지 않고 '#'과 '@' 같은 문자를 사용하는 이유는, 스마트 폰에서 "STX"나 "ETX"를 입력할 수 있는 방법이 없기 때문;; 




우선 데이터 형식과 커맨드를 만들자. 


LED와 모터를 제어할 것이고, LED는 On/Off 기능을, 모터는 속도 제어 기능을 제어할 것이다. LED On/Off 기능을 "ON", "OFF"로 하면 나중에 LED On인지, 모터 On인지 헷갈릴 수 있으니까 "ON", "OFF" 앞에 "LED"라고 붙여주자. 그리고 "LED"와 "ON/OFF" 사이를 ',(콤마)'로 구분.


모터 역시 앞에 "MOTOR"라고 붙인 후 뒤에 0~255까지의 속도 값을 문자로 줄 것이다. "MOTOR"와 속도 값은 역시 ','로 구분.


표로 보면 이해가 빠를 것이다.



* 데이터 형식 : '#(시작 문자)' + 커맨드 + ',(콤마,구분자)' + 데이터 + '@(종료 문자)'

커맨드 (문자)

데이터 (문자) 

동작 

예시 

LED

 OFF

LED Off 

#LED,OFF@

 ON

LED On 

#LED,ON@ 

MOTOR

속도 값 (0~255)

모터 속도 조절 

#MOTOR,200@ 



'예시' 부분을 보면 쉽게 이해할 수 있을 것이다. 



제어할 센서나 모듈을 나타내는 ',' 앞 부분을 '커맨드', 제어 동작을 나타내는 부분을 '데이터'라고 칭하도록 하겠다. 


즉, 이 프로토콜은 다음과 같이 정의할 수 있다.



 #커맨드,데이터@



소스로 구현해보자.



ProtocolTest03.ino


int ledPin = 13;

int dcPin1 = 7;

int dcPin2 = 8;


String rxData = "";

boolean bStart = false;

int dataCnt = 0;


void setup() {

  // put your setup code here, to run once:

  pinMode(ledPin, OUTPUT);

  pinMode(dcPin1, OUTPUT);

  pinMode(dcPin2, OUTPUT);

  digitalWrite(dcPin2, LOW);

  

  Serial1.begin(115200);

}


void loop() {

  // put your main code here, to run repeatedly:

  if(Serial1.available()) {

    char data = Serial1.read();

    

    if(bStart) {

      if(data == N'@') {

        parseData(rxData);

        bStart = false;

        rxData = "";

      } else {

        rxData += data;

      }

    } else {

      if(data == N'#') bStart = true;

    }

  }

}


void parseData(String rxStr) {

  String cmd = rxStr.substring(0, rxStr.indexOf(','));

  String data = rxStr.substring(rxStr.indexOf(',')+1);

  

  if(cmd == "LED") {

    if(data == "ON") digitalWrite(ledPin, HIGH);

    else if(data == "OFF") digitalWrite(ledPin, LOW);

  } else if(cmd == "MOTOR") {

    analogWrite(dcPin1, data.toInt());

  }

}


 


parseData() 함수 부분 외의 다른 코드는 이전 강좌의 예제와 동일하므로 설명은 생략한다.


parseData() 함수에서는 매개 변수로 받은 String 타입의 데이터를 String.substring() 함수와 String.indexOf() 함수를 이용하여 커맨드와 데이터를 분리 또는 추출한다. 그리고 분리된 커맨드와 데이터를 각각 검사하여 해당하는 기능을 수행한다. 


String.substring() 함수와 String.indexOf() 함수에 대한 설명은 String 관련 강좌를 참조.



업로드 한 후 실행해보자.





입력 중간에 공백 문자가 들어가지 않도록 유의. (',' 다음에 자꾸 공백 문자가 자동 입력됨. ㅜㅜ)



아무튼 모터 속도가 전송한 데이터에 따라 달라지는 것을 확인할 수 있다. 


이 예제에 모터를 하나 더 추가하고, 방향을 제어하는 프로토콜을 추가한다면 스마트 폰으로 제어하는 RC 카를 만들 수 있다. 우와!!

brown_and_cony-35 




마지막으로, 아두이노에서 스마트 폰으로 데이터를 전달하는 실습을 해보자. 


무슨 데이터를 보낼까? 조도 센서를 이용해서 밝기 값을 보내볼까? 좋다. 3초에 한 번씩 조도 값을 읽어 보내는 기능을 만들어보자. 


참고로, 보내는 건 아주 쉽다. 그냥 시리얼로 보내면 됨. +_+



 ProtocolTest04.ino

 

 int lightPin = A0;

 unsigned long preMillis = 0;


 void setup() {

    Serial1.begin(115200);

 }


 void loop() {

   unsigned long curMillis = millis();


   if(curMillis - preMillis > 3000) {

     preMillis = curMillis;

     Serial1.print(analogRead(A0));

   }

 }





끝. 너무 쉽죠??


소스를 업로드한 후 확인해보자. 



 


brown_and_cony-76 



뭔가 좀 끊기는 듯 하지만 값이 가긴 간다. 



지금은 채팅 앱으로 테스트 중이라 그냥 데이터가 오는 것만 확인하면 되지만, 만일 앱을 직접 만들어 값을 사용하는 경우에는 위 영상처럼 데이터가 끊어져 들어오면 처리하기 어려울 것이다. 


이럴 경우에 뭐가 필요하다??


프.로.토.콜.



위에서 실습한 모터 예제의 프로토콜을 여기에도 적용해보자. 



 

 #커맨드,데이터@



 

* 데이터 형식 : '#(시작 문자)' + 커맨드 + ',(콤마,구분자)' + 데이터 + '@(종료 문자)'

커맨드 (문자)

데이터 (문자) 

예시 

LIGHT

밝기 값 (0~1023)

#LIGHT,123@ 



아두이노의 소스는 단 한 줄만 변경하면 된다. 



 

   if(curMillis - preMillis > 3000) {

     preMillis = curMillis;

     Serial1.print("#LIGHT,");

     Serial1.print(analogRead(A0));

     Serial1.print("@");

   }


 



어익후, 두 줄이네. 



별 거 아니다. 여기에 "TEMP"나, "HUM" 같은 커맨드를 추가한 후 온도 값이나 습도 값을 보낼 수도 있다. 그러면 데이터를 받는 앱 쪽에서 그 데이터를 가지고 처리하면 된다. 처리하는 방법은, 시작 문자와 종료 문자를 구분하는 아두이노 소스와 동일한 방식을 사용하면 됨. 물론 사용되는 함수 이름이나 방식은 조금 다르겠지만. 



자, 이 것으로 블루투스 강좌는 마치도록 하겠다. 블루투스를 이용하는 프로젝트가 많기 때문에 데이터를 보내거나 받아서 처리하는 법까지 함께 설명하느라 강좌가 길어졌다. 힘든 여정이었..ㅜㅜ



그럼 다음 강좌에서 또 만나요. 안녕!

0
0
이 글을 페이스북으로 퍼가기 이 글을 트위터로 퍼가기 이 글을 카카오스토리로 퍼가기 이 글을 밴드로 퍼가기

임베디드 보드

번호 제목 글쓴이 날짜 조회수
58 아두이노 [강좌] 50. 와이파이 통신 (4) - WebServer 예제 icon 양재동메이커 03-21 9,553
57 아두이노 [강좌] 49. 와이파이 통신 (3) - WebClient 예제 icon 양재동메이커 03-21 13,225
56 아두이노 [강좌] 48. 와이파이 통신 (2) - 커맨드 모드 사용하기 (WiFly 쉴드) icon 양재동메이커 03-20 8,638
55 아두이노 [강좌] 47. 와이파이 통신 (1) - 와이파이란 무엇인가 icon 양재동메이커 03-20 12,404
54 아두이노 [강좌] 46. 블루투스 통신 (5) - 프로토콜 만들기 (2) icon 양재동메이커 03-20 8,929
53 아두이노 [강좌] 45. 블루투스 통신 (4) - 프로토콜 만들기 (1) icon 양재동메이커 03-20 10,415
52 아두이노 [강좌] 44. 블루투스 통신 (3) - RN42 모듈에서 직접 접속하기 icon 양재동메이커 03-20 7,750
51 아두이노 [강좌] 43. 블루투스 통신 (2) - 스마트폰과 통신하기 icon 양재동메이커 03-20 9,851
50 아두이노 [강좌] 42. 블루투스 통신 (1) - RN42 블루투스 모듈 실습하기 icon 양재동메이커 03-20 10,987
49 아두이노 [강좌] 41. 서보 모터 (2) - Servo 함수 알아보기 icon 양재동메이커 03-20 12,710
48 아두이노 [아두이노 강좌] 40. 서보 모터 (1) - 서보 모터 동작 방식 icon 양재동메이커 03-20 12,638
47 아두이노 [강좌] 39. 스텝 모터 (3) - 모터 드라이버 EasyDriver(A3967) 사용하기 icon 양재동메이커 03-20 8,988
46 아두이노 [강좌] 38. 스텝 모터 (2) - Stepper 함수 알아보기 icon 양재동메이커 03-20 12,549
45 아두이노 [강좌] 37. 스텝 모터 (1) - 스텝 모터 동작 방식 icon 양재동메이커 03-20 9,329
44 아두이노 [강좌] 36. DC 모터 (2) - DC 모터 드라이버 실습하기 (TB6612FNG) icon 양재동메이커 03-20 9,197
43 아두이노 [강좌] 35. DC 모터 (1) - DC 모터 동작 방식 icon 양재동메이커 03-20 11,469
42 아두이노 [강좌] 34. SPI 통신 (3) - 기압 센서(MPL115A1) 실습하기 icon 양재동메이커 03-20 8,142
41 아두이노 [강좌] 33. SPI 통신 (2) – SPI 함수 알아보기 icon 양재동메이커 03-20 14,509
40 아두이노 [강좌] 32. SPI 통신 (1) - SPI 통신이란 무엇인가 icon 양재동메이커 03-20 18,981
39 아두이노 [강좌] 31. I2C 통신 (3) - 온도 센서(TMP102) 실습하기 icon 양재동메이커 03-20 14,795