라즈베리파이 아두이노 시리얼 통신 c언어 - lajeubelipai adu-ino silieol tongsin ceon-eo

라즈베리파이와 아두이노 간의 USB Serial 통신 테스트

라즈베리파이와 아두이노를 연결하여 사용하는 경우에는 이들 디바이스 간에 데이터 통신이 필요하게 된다. 가장 쉬운 연결방법은 아두이노의 USB 단자를 라즈베리파이의 USB 포트에 연결하면 되는데 여기서는 이렇게 연결된 디바이스 간에 데이터를 송수신하는 예제를 작성해보려고 한다

아두이노의 USB 단자가 라즈베리파이에 연결되는 관계로 라즈베리파이에 아두이노 개발환경을 설치하고 아두이노의 프로그램을 작성하여 업로드하는 것이 편리할 것이다. Arduino IDE의 시리얼 모니터를 이용하여 Arduino IDE가 실행되고 있는 컴퓨터와 아두이노 간의 시리얼 통신 방법도 소개한다.

테스트 환경

PC (Windows 7)

라즈베리파이 B+

아두이노 UNO

Node.js

라즈베리파이에 아두이노 개발환경 설치

라즈베리파이에서 vncserver를 실행한다

$ sudo vncserver

다른 시스템에서 vnc 클라이언트(TightVNC Viewer) 프로그램을 실행하고 LXTerminal 에서 다음과 같이 아두이노를 설치한다

VNC클라이언트의 LXTerminal에서 아두이노를 설치해야만 아래의 화면과 같은 Arduino IDE를 사용할 수 있었으므로 PuTTY와 같은 일반 원격접속으로 아두이노를 설치하고 나중에 VNC 클라이언트를 실행하면 Arduino IDE가 등록되지 않아서 사용할 수 없었다

현재 시스템 업데이트

$ sudo apt-get update

$ sudo apt-get upgrade

아두이노 패키지 설치

$ sudo apt-get install arduino

아두이노 패키지에 시리얼포트 접근권한 부여

$ sudo usermod -a -G tty pi

$ sudo usermod -a -G dialout pi

위와 같이 VNC 클라이언트의 LXTerminal 상에서 아두이노를 설치한 후 TightVNC Viewer의 툴바에서 '메뉴' > 개발 > Arduino IDE 를 확인한다

라즈베리파이 아두이노 시리얼 통신 c언어 - lajeubelipai adu-ino silieol tongsin ceon-eo

위의 화면과 같이 실행된 Arduino IDE에서는 많은 아두이노용 예제 프로그램을 내장하고 있는데, 파일 > 예제 > Basics > Blink 를 선택하고 컴파일 아이콘을 눌러 컴파일하고 업로드 아이콘을 눌러 업로드하면 즉시 아두이노에서 실행되므로 아두이노 보드의 중간에 있는 LED가 2초 간격으로 깜박거리게 된다

Arduino IDE와 아두이노 보드 간의 시리얼 통신

Arduino IDE에서 제공하는 툴(도구 > 시리얼 모니터)을 이용하면 키보드에서 입력한 문자열을 아두이노 보드에 시리얼통신으로 전달할 수 있다. 즉, Arduino IDE가 실행되고 있는 라즈베리파이에 별도의 코드를 작성하여 실행하지 않아도 간단한 문자열은 Arduino IDE에서 제공하는 툴을 이용하여 아두이노 보드에 전달할 수 있다. 물론 라즈베리파이의 USB 포트에 아두이노의 USB 단자를 연결해야 한다. 시리얼통신 프로그램이나 일반 프로그램의 디버깅 용도로 유용할 것이다. Arduino IDE에서 시리얼 모니터를 이용하여 시리얼 통신을 테스트하는 방법은 여기를 참조하세요

라즈베리파이의 USB 포트에 아두이노 USB 단자 연결

가장 간편한 시리얼통신 방법이며 아두이노 보드를 구입하면 포함되어 있는 USB 케이블을 이용하여 라즈베리파이와 아두이노를 연결한다. 이렇게 하면 Arduino IDE에서 제공하는 시리얼 모니터를 이용하여 시리얼 통신 테스트를 할 수도 있도 디버깅 문자열을 화면에 출력할 수도 있다. 그리고 Arduino IDE와 무관하게 라즈베리파이에 시리얼 통신을 위한 별도의 코드를 작성하여 시리얼통신을 테스트할 수도 있다. 

라즈베리파이에 연결된 USB 디바이스 확인

$ dmesg | tail

위의 명령으로 USB 시리얼포트를 확인한 결과 아래처럼 'ttyUSB0' 으로 확인된다. 시스템마다 다를 수 있으므로 반드시 확인해야 한다

확인된 포트 이름은 시리얼통신 코드에 포함되어야 한다

$ dmesg | tail

[ 3542.613456] usb 1-1.5: New USB device found, idVendor=1a86, idProduct=7523

[ 3542.613499] usb 1-1.5: New USB device strings: Mfr=0, Product=2, SerialNumber=0

[ 3542.613519] usb 1-1.5: Product: USB2.0-Serial

[ 3543.019388] usbcore: registered new interface driver usbserial

[ 3543.019556] usbcore: registered new interface driver usbserial_generic

[ 3543.019706] usbserial: USB Serial support registered for generic

[ 3543.030803] usbcore: registered new interface driver ch341

[ 3543.030980] usbserial: USB Serial support registered for ch341-uart

[ 3543.031099] ch341 1-1.5:1.0: ch341-uart converter detected

[ 3543.055141] usb 1-1.5: ch341-uart converter now attached to ttyUSB0

C언어와 wiringPi 라이브러리를 이용한 시리얼통신 예제

Arduino IDE 의 시리얼 모니터를 이용한 시리얼 통신이 아닌 개발자가 작성한 코드를 이용하여 라즈베리와 아두이노간의 시리얼 통신을 테스트하려고 한다.

라즈베리파이에 WiringPi 라이브러리를 설치하고 아래와 같은 시리얼 통신 예제를 작성한다

serial_test.c

#include <stdio.h> //for printf #include <stdint.h> //uint8_t definitions #include <stdlib.h> //for exit(int); #include <string.h> //for errno #include <errno.h> //error output //wiring Pi #include <wiringPi.h> #include <wiringSerial.h> char device[]= "/dev/ttyUSB0"; // filedescriptor int fd; unsigned long baud = 9600; unsigned long time=0; int main() { printf("%s \n", "Raspberry Startup!"); fflush(stdout); //get filedescriptor if ((fd = serialOpen (device, baud)) < 0) { fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ; exit(1); //error } //setup GPIO in wiringPi mode if (wiringPiSetup () == -1) { fprintf (stdout, "Unable to start wiringPi: %s\n", strerror (errno)) ; exit(1); //error } while(1) { // Pong every 3 seconds if(millis()-time>=3000) { serialPuts (fd, "Hello\n"); // you can also write data from 0-255 // 65 is in ASCII 'A' serialPutchar (fd, 65); time=millis(); } // read signal if(serialDataAvail (fd)) { char newChar = serialGetchar (fd); printf("%c", newChar); fflush(stdout); } } return 0; }

C언어 코드의 컴파일 및 실행C언어 코드의 컴파일 및 실행

$ sudo gcc serial_test.c -o serial_test -l wiringPi -DRaspberryPi

$ sudo ./serial_test

위에서 실행된 프로그램을 종료하려면 ...

CTRL + C

아두이노 측에서 대응하는 시리얼 통신 코드

라즈베리파이로부터 전달된 시리얼 데이터를 수신하여 그대로 다시 라즈베리파이 측으로 되돌려 전달하는 에코우 프로그램

VNC 클라이언트 프로그램에서 메뉴 > 개발 > Arduino IDE를 선택하여 에디터 영역에 다음과 같은 코드를 입력하고 serial_test.ino 등으로 라즈베리파이 파일 시스템에 저장하고 컴파일, 아두이노에 업로드하면 아두이노에서 실행되는 것을 확인할 수 있다

void setup() {
  // initialize digital pin 13 as an output.
  pinMode(13, OUTPUT);
  Serial.begin(9600);
}

// the loop function runs over and over again forever
void loop() {
  String msg = "";
  digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);              // wait for a second
  digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);              // wait for a second
  if(Serial.available())
  {
    msg = Serial.readString();
    Serial.println(msg);
  }
}

Arduino IDE의 도구 > 시리얼 모니터를 선택하면 Arduino IDE에서 아두이노를  향하여 시리얼 데이터를 전송할 수도 있고 아두이노가 전송하는 시리얼 데이터를 수신하여 출력할 수도 있으므로 아두이노 코드를 디버깅할 때 유용할 것이다

Arduino IDE 상에서 아두이노와 시리얼 데이터를 주고 받으려면 먼저 도구 > 시리얼포트 에서 아두이노가 연결된 포트를 선택한다