이글은 2018.2.8에 있었던 오프라인 강의 노트입니다.
블루투스 모듈 연결하기
블루투스 모듈은 보통 4개의 핀을 가지고 있습니다. 모듈의 RX는 아두이노의 TX에, TX는 RX에 연결하여야 하므로 주의가 필요합니다.
참고로 I2C 연결의 경우에는 SDA핀은 SDA끼리, SCL은 SCL끼리 연결하면 됩니다.
블루투스 모듈이 다른 기기와 연결되어 있을 때에는 IDE에서 스케치를 업로드할 때 통신 오류가 생깁니다. 따라서 반드시 블루투스 모듈을 분리한 후 스케치를 업로드해야 합니다. 이런 애로를 피하기 위하여 ‘소프트웨어 시리얼’을 사용하는 방법도 있습니다.
블루투스 모듈은 새로운 안드로이드 기기에는 먼저 ‘등록(페어링)’ 절차를 거쳐야 합니다.
앱 인벤터 2 화면 디자이너
아두이노에서 앱 인벤터 2로 데이타 보내기
아두이노에서 안드로이드로 데이타를 보내서 앱 인벤터 2에서 처리할 때는 다음의 형식으로 정보를 표현하면 편합니다.
위와 같은 형식으로 Serial.print()를 이용하여 정보를 전달하는 스케치의 일부분입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// 위 생략 float temperature; float humidity; int dustDensity; //중간 생략 Serial.print('t,'); Serial.print(temerature,1); Serial.print('|'); Serial.print('h,'); Serial.print(humidity,1); Serial.print('|'); Serial.print('d,'); Serial.print(dustDensity); Serial.print('|'); //아래 생략 |
다음은 앱 인벤터 2에서 블루투스를 통하여 전달된 문자열을 다루는 방법입니다.
- 블루투스를 통하여 전달된 문자 하나를 읽어서 키,값용 문자열에 덧붙이기를 계속합니다.
- 읽은 문자가 구분자(|)이면 키,값용 문자열을 콤마(‘)를 기준으로 분리하여 리스트 항목 두 개를 만듭니다.
- 리스트의 첫 항목(키)과 두 번째 항목(값)을 읽어서 적절한 처리를 하면 됩니다.
앱 인벤터 2에서 아두이노로 데이타 보내기
앱 인벤터 2(모바일 기기)에서 아두이노로 데이터를 보낼 때에도 데이타 표현 규칙을 key,value| 형식으로 하면 편합니다.
앱 인벤터 2에서 받은 데이터를 처리하는 아두이노 스케치의 일부분
아두이노에서는 시리얼로 받은 문자가 있으면 다음과 같이 반복적으로 처리합니다.
readSerialAndSetOptins() 함수는 다음과 같은 처리를 합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
// 위 생략 void loop() { // 외부 인터럽트를 먼저 처리한다 menuVal = btn0.getButton(); upVal = btn1.getButton(); downVal = btn2.getButton(); // 시리얼로 받은 'key,value|' 형식의 데이타를 처리한다 while (Serial.available()) { readSerialAndSetOptins(); } // 메뉴별로 로직을 구분한다 switch (thisMenu) { case MENU_MAIN : doMain(); break; case MENU_SWITCH : doSwitch(); break; case MENU_COUNT_DOWN : doCountDown();break; case MENU_TIME : doTime(); break; } } void readSerialAndSetOptins() { #define READ_STR_LEN 20 #define KEY_STR_LEN 10 #define VALUE_STR_LEN 20 static char readStr[READ_STR_LEN]; static int readIdx = 0; char c = Serial.read(); if (c == '\r' || c == '\n') return; readStr[readIdx] = c; readStr[++readIdx] = '\0'; if (readIdx >= READ_STR_LEN) readIdx = 0; if (c == '|') { char key[KEY_STR_LEN]; char value[VALUE_STR_LEN]; char *ptr; // ','로 분리되는 문자열의 포인터를 돌려준다. // 이 때 ','는 '\0'로 대체 된다. ptr = strtok(readStr,","); strncpy(key,ptr,KEY_STR_LEN); // '|'로 분리되는 문자열의 포인터를 돌려준다. // NULL을 파라메타로 주면 이전 처리한 문자열 다음부터 처리한다. // strtok()함수는 파라메타로 준 문자열을 변경하므로 주의해야 한다. ptr = strtok(NULL,"|"); strncpy(value,ptr,VALUE_STR_LEN); // 키와 값을 실제로 처리하는 함수이다. setOptons(key,value); readIdx = 0; } } void setOptons(char *key, char *value) { // int i = atoi(value); // float f = atof(value); #define STRCMP_EQUAL 0 if (strcmp(key,"r") == STRCMP_EQUAL) { if (strcmp(value,"1") == STRCMP_EQUAL) relayOnOff = 1; else relayOnOff = 0; printToSerial('r',relayOnOff); } } void printToSerial(char c, int v) { Serial.print(c); Serial.print(','); Serial.print(v); Serial.print('|'); } // 아래 생략 |
1 2 3 |
while (Serial.available()) { readSerialAndSetOptins(); } |
- 시리얼을 통하여 전달된 문자 하나를 읽어서 ‘키,값’용 문자열에 덧붙이기를 계속합니다.
- 읽은 문자가 구분자(|)이면 ‘키,값’용 문자열을 콤마(‘)를 기준으로 분리하여 키와 값 두 개의 문자열로 만듭니다.
- setOptons(key,value) 함수에 키와 값을 보내 필요한 처리를 합니다.
댓글 남기기