라즈베리파이 아두이노 시리얼 통신

바둑이·2021년 10월 14일
1

라즈베리파이와 아두이노 사이에는 SPI, I2C, UART 등 다양한 통신 방법들을 적용할 수 있습니다. 하지만 아두이노의 입출력 핀 전압이 5V인 반면에 라즈베리파이의 GPIO 입출력 핀 전압은 3.3V이기 때문에 직접적으로 결선할 경우 문제가 발생하게 됩니다. 따라서 가장 간편하게 사용할 수 있는 Serial(UART) 통신을 설명하려고 합니다.

시리얼통신은 라즈베리파이와 아두이노를 USB케이블로 연결하는 것으로 간단하게 구현할 수 있으며 전압에 따른 문제 또한 발생하지 않습니다.

  1. 아두이노 Idle 설치하기

    $ sudo apt-get install arduino

패키지 설치를 위해 라즈베리파이에 update 명령어를 통해 업데이트 시켜주고 위 명령어를 입력하여 아두이노 패키지를 설치한다. 이때 설치된 패키지는 권한을 아직 가지고 있지 않은 상태이므로 바로 실행시키지 말고 아래 명령어를 입력하여 아두이노 패키지가 시리얼 포트에 엑세스 할 수 있는 권한을 얻도록 해야 합니다.

$ sudo usermod -a -G tty pi
$ sudo usermod -a -G dialout pi

위 과정을 완료하였다면 아두이노 패키지가 성공적으로 라즈베리파이에 설치되었습니다. 이제 아두이노를 실행시키고 라즈베리파이에 아두이노를 연결한 후에 포트를 설정하고 (포트명은 아마 "/dev/ttyACM0"일 것입니다.) blink 예제를 업로드하여 제대로 동작하는지 확인해봅니다.

  1. 시리얼 통신하기
 
// 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를 눌러주면 됩니다.

만약 종료를 하지 않을경우 터미널을 종료해도 계속해서 프로그램이 동작하며 아두이노를 다시 연결시 ttyACM0(ttyACM0로 접속시) 포트는 사용하지 못하기 때문에 테스트 종료시에 유의해야 합니다.

profile
안녕하세용('<')/

0개의 댓글