리눅스 시리얼 통신 예제 (Beaglebone black to arduino with RHT02)
--
이번 예제는 리눅스에서 시리얼(UART)을 이용하여 다른 보드와 통신하는 예제이다.
온습도 센서를 직접 BBB에 연결하여 사용하기에는 약간 어려움이 있기 때문에 아두이노에서 센서에대한 데이터를 관리하고 BBB보드에서 센서값을 요청하여 가져오는 방식으로 구현하였다.
따라서 전체적인 구조는 다음과 같다.
BBB보드(리눅스) --USB--> 아두이노 우노 --> RHT02
소스를 보면 알겠지만, BBB보드에서 'R'을 아두이노로 보내면 아두이노에서 온습도와 quality값을 리턴하도록 만들어져있다.
소스코드는 링크를 기반으로 만들어졌으며 kdlp(Ref. 참조)를 보고 초기화 코드를 약간 변경하여 만들었다.
중간에 있는 sleep(3);의 경우 시리얼 통신을 초기화 할 때에 아두이노가 리셋 되는 현상이 있기 때문에 넣은 코드이다.
왜 아두이노가 리셋 되는지에 대해서는 아직 아는 바가 없다. (어떤 검색어로 해야할 지도 모르겠고;;)
BBB의 소스코드는 다음과 같다.
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 | #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <termios.h> #include <fcntl.h> #define BUF_MAX 512 int main( void) { int fd,i=0; char buf[BUF_MAX]; char tmp, read_byte=0; struct termios newtio; // fd = open( "/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NONBLOCK ); fd = open( "/dev/ttyUSB0", O_RDWR | O_NOCTTY ); if(fd<0) { fprintf(stderr,"ERR\n"); exit(-1); } memset( &newtio, 0, sizeof(newtio) ); newtio.c_cflag = B115200; newtio.c_cflag |= CS8; newtio.c_cflag |= CLOCAL; newtio.c_cflag |= CREAD; newtio.c_iflag = IGNPAR; // newtio.c_iflag = ICRNL; newtio.c_oflag = 0; newtio.c_lflag = 0; newtio.c_cc[VTIME] = 0; newtio.c_cc[VMIN] = 0; tcflush (fd, TCIFLUSH ); tcsetattr(fd, TCSANOW, &newtio ); sleep(3); while(1) { write( fd, "R", 1); i = read(fd,buf,BUF_MAX); buf[i] = '\0'; printf("%s",buf); sleep(1); } close( fd); return 0; } | cs |
아두이노쪽의 소스코드는 다음과 같다.
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 85 86 87 88 89 90 91 92 | // // FILE: dht21_test.ino // AUTHOR: Rob Tillaart // VERSION: 0.1.02 // PURPOSE: DHT library test sketch for DHT21 && Arduino // URL: // // Released to the public domain // #include <dht.h> dht DHT; unsigned long last_millis, current_millis; char buf; char set_flag=0; int chk =0; #define DHT21_PIN 5 void setup() { Serial.begin(115200); /* Serial.println("DHT TEST PROGRAM "); Serial.print("LIBRARY VERSION: "); Serial.println(DHT_LIB_VERSION); Serial.println(); Serial.println("Type,\tstatus,\tHumidity (%),\tTemperature (C)"); */ last_millis = millis(); current_millis = millis(); chk = DHT.read21(DHT21_PIN); } void loop() { current_millis = millis(); // READ DATA if (current_millis > last_millis +2000) { chk = DHT.read21(DHT21_PIN); last_millis = current_millis; } if(Serial.available()) { buf = Serial.read(); if (buf == 'R') set_flag = 1; buf = '\0'; } if(set_flag ==1){ Serial.print("DHT21 \t"); switch (chk) { case DHTLIB_OK: Serial.print("OK\t"); break; case DHTLIB_ERROR_CHECKSUM: Serial.print("CHKSUM ERR\t"); break; case DHTLIB_ERROR_TIMEOUT: Serial.print("TIMEOUT ERR\t"); break; case DHTLIB_ERROR_CONNECT: Serial.print("CONNECT ERR\t"); break; case DHTLIB_ERROR_ACK_L: Serial.print("ACK ERR\t"); break; case DHTLIB_ERROR_ACK_H: Serial.print("ACK ERR\t"); break; default: Serial.print("UNKNOWN ERR\t"); break; } // DISPLAY DATA Serial.print(DHT.humidity, 1); Serial.print("\t"); Serial.println(DHT.temperature, 1); set_flag =0; } //delay(2000); } // // END OF FILE // | cs |
아두이노 보드의 경우 2초마다 내부적으로 센서값을 갱신하게 되며, 호스트에서 'R'문자가 들어오게 되면, 플래그를 켜서 가지고 있는 데이터를 BBB보드로 넘겨 주도록 되어 있다.
이러한 방식으로 BBB보드는 각 센서 노드에 대하여 일정한 시간으로 접근 할 수 있게 된다.
Ref.
http://forum.falinux.com/zbxe/index.php?document_srl=405836&mid=network_programming
https://wiki.kldp.org/wiki.php/Serial-Programming-HOWTO
--