라즈베리파이와 아두이노 사이에는 SPI, I2C, UART 등 다양한 통신 방법들을 적용할 수 있습니다. 하지만 아두이노의 입출력 핀 전압이 5V인 반면에 라즈베리파이의 GPIO 입출력 핀 전압은 3.3V이기 때문에 직접적으로 결선할 경우 문제가 발생하게 됩니다. 따라서 가장 간편하게 사용할 수 있는 Serial(UART) 통신을 설명하려고 합니다.
시리얼통신은 라즈베리파이와 아두이노를 USB케이블로 연결하는 것으로 간단하게 구현할 수 있으며 전압에 따른 문제 또한 발생하지 않습니다.
아두이노 Idle 설치하기
$ sudo apt-get install arduino
패키지 설치를 위해 라즈베리파이에 update 명령어를 통해 업데이트 시켜주고 위 명령어를 입력하여 아두이노 패키지를 설치한다. 이때 설치된 패키지는 권한을 아직 가지고 있지 않은 상태이므로 바로 실행시키지 말고 아래 명령어를 입력하여 아두이노 패키지가 시리얼 포트에 엑세스 할 수 있는 권한을 얻도록 해야 합니다.
$ sudo usermod -a -G tty pi
$ sudo usermod -a -G dialout pi
위 과정을 완료하였다면 아두이노 패키지가 성공적으로 라즈베리파이에 설치되었습니다. 이제 아두이노를 실행시키고 라즈베리파이에 아두이노를 연결한 후에 포트를 설정하고 (포트명은 아마 "/dev/ttyACM0"일 것입니다.) blink 예제를 업로드하여 제대로 동작하는지 확인해봅니다.
// just that the Arduino IDE doesnt compile these files.
#ifdef RaspberryPi
//include system librarys
#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>
// Find Serial device on Raspberry with ~ls /dev/tty*
// ARDUINO_UNO "/dev/ttyACM0"
// FTDI_PROGRAMMER "/dev/ttyUSB0"
// HARDWARE_UART "/dev/ttyAMA0"
char device[]= "/dev/ttyACM0";
// filedescriptor
int fd;
unsigned long baud = 9600;
unsigned long time=0;
//prototypes
int main(void);
void loop(void);
void setup(void);
void setup(){
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
}
}
void loop(){
// Pong every 3 seconds
if(millis()-time>=3000){
serialPuts (fd, "Pong!\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);
}
}
// main function for normal c++ programs on Raspberry
int main(){
setup();
while(1) loop();
return 0;
}
#endif //#ifdef RaspberryPi
위 코드는 wiringPi 라이브러리를 활용하여 아두이노와 통신할 수 있는 예제 코드입니다. 여기서 "/dev/ttyACM0" 부분은 아두이노가 연결된 장치의 포트명을 말하는 것으로 가끔씩 에러가 발생할 경우 ACM1, ACM2 이렇게 순차적으로 증가할 수 있으니 유의하도록 해야 합니다.
라즈베리파이의 USB포트 구성 목록을 확인하려면 다음과 같은 명령어를 입력하면 됩니다.
$ dmesg|tail
그럼 이제 위 소스코드를 컴파일 해봅니다. 저는 소스코드의 파일명을 test.c로 하였으며 hello라는 이름으로 컴파일했습니다. 컴파일할 때는 파일이 저장된 디렉토리로 들어간 후에 하도록 합니다.
$ sudo gcc test.c -o hello -l wiringPi -DRaspberryPi
$ sudo ./hello
아래는 간단하게 구현한 아두이노 소스코드이며 1초마다 라즈베리파이로 Hello World 문자를 송신할 것입니다.
void setup(){
Serial.begin(9600);
}
void loop(){
Serial.println("Hello World");
delay(1000);
}
위와 같은 결과가 나오면 성공입니다. 여기서 실행된 프로그램을 종료하려면 Ctrl + C를 눌러주면 됩니다.