박민혀기

라즈베리파이4 UART 통신 본문

Raspiberry Pi

라즈베리파이4 UART 통신

박민혀기 2024. 11. 8. 00:04

현재 진행하고 있는 VisionKart에서 마지막 부분인 통신 프로토콜 부분을 진행하고 있다.

RS232에서 uart 통신으로 변경되어 개발에 있어 더 수월해진 것 같다.

 

메인 컨트롤 보드에는 STM32(메인 MCU) + 모터 드라이버 + 각종 통신 모듈/포트 + CM4(RaspberryPi4)가 한 기판 위에 올라가서 통신을 주고 받는다. 나는 당연하게도 uart0(TXD0, RXD0)  포트를 사용하려고 회로 설계와 디자인을 모두 살펴보면서 확인하였다. 하지만 설계와 실제 디자인이 다른 것 같아 보드 설계자한테 물어보니 uart0 포트가 stm32와 끊어져 있는 것 같다는 얘기를 받았다. (아무리 봐도 이상해서 한 시간은 계속 확인해 본 것 같다.)

그에 따라  자연스럽게 다음 포트인 uart3(TXD3, RXD3)를 사용하게 됐다.

 

라즈베리파이에서 uart를 사용하기 위해서 크고 작은 설정들을 해줘야 한다.

(UART1을 사용하기 위해서는 Bluetooth 활성화를 꺼야한다.)다음 사진과 같이 Serial Port는 Enable, Serial Console은 Disable로 설정해줘야한다.

 

그 이후 다음 명령어로 config 파일을 연 후 파일 맨 아래 사용하고 싶은 uart 포트를 추가해주고 재부팅한다.(20241107기준 /boot/config.txt 파일을 보면 /boot/firmware/config.txt를 수정하라고 나온다.)

$ sudo nano /boot/firmware/config.txt 	==> 이걸로 설정
$ sudo nano /boot/config.txt		==> 예전 버전

실제로 나는 uart3만 추가하고 다시 재부팅하였다.

 

C++, WiringPi를 활용하여 uart 통신을 할 경우 /dev/ttyAMAn 과 같은 형식으로 접근하게 되는데, 이 과정에서 추가한 uart3가 AMA3인지 매칭이 되지 않아 포트 하나하나 확인해 보았다. 결과는  /dev/ttyAMAn에서 n과 추가한 dtoverlay=uartn의 n이 같은 수를 의미하고 있었다. 따라서 나는 uart3를 사용하기 위해 /dev/ttyAMA3가 있는지 확인하면 됐고, dtoverlay=uart3만 추가하면 사용이 가능했었다.

 

다음 명령어를 통해 정상적으로 포트가 열려 있는지 확인할 수 있다.

ttyS0, ttyAMA3 활성화된 모습

 

라즈베리파이에서 uart를 사용할 수 있는 핀맵이다. 참고하면 좋을 듯하다. (나는 보통 CM4를 사용하기 때문에 따로 회로도를 확인해야 해서 큰 의미는 없다...)

참고한 블로그에서 친절하게 정리해 주셨다..

 

나는 테스트 프로그램을 에코 프로그램으로 테스트해보았다.

외부 라이브러리는 wiringPi만 사용하였고, wiringPi 설치는 아래 포스팅에서 간단하게 설치할 수 있다.

https://forthe-future.tistory.com/23

 

라즈베리파이 WiringPi Install

apt-get update, apt-get upgrade 완료 후 진행 WiringPi 설치 다운로드 pi@raspberrypi:~$ git clone https://github.com/WiringPi/WiringPi 빌드 pi@raspberrypi:~$ cd WiringPi/ pi@raspberrypi:~$ ./build 설치확인 pi@raspberrypi:~$ gpio -v

forthe-future.tistory.com

 

동작은 문자 하나를 입력하면 전송한 문자 하나를 받아 그대로 출력하는 프로그램이다.

물론 동작에서 TXD3와 RXD3 핀이 쇼트되어 있어야 한다.

코드의 설명은 따로 하지 않아도 이해하는데 그리 어렵지 않을 것이다.

#include <wiringPi.h>
#include <wiringSerial.h>
#include <iostream>
#include <unistd.h>

int main(){
        int serial_port;
        const char* device = "/dev/ttyAMA3";

        if((serial_port = serialOpen(device, 115200)) < 0){
                std::cerr << "Failed to open serial port" << std::endl;
                return 1;
        }

        if(wiringPiSetup() == -1){
                std::cerr << "Failed to initialize WiringPi" << std::endl;
                return 1;
        }

        std::cout << "Already use UART TXD3/RXD3 port (ttyAMA3)..." << std::endl;


        char send_char;
        std::cout << "Enter a character to send: ";
        std::cin >> send_char;
        serialPutchar(serial_port, send_char);

        while (!serialDataAvail(serial_port)) {
                usleep(100);
        }

        char received_char = serialGetchar(serial_port);
        std::cout << "Echoed back: " << received_char << std::endl;

        serialClose(serial_port);
        return 0;
}

 

실행 화면 & 컴파일 명령어

 

이로써 라즈베리파이 환경에서 uart 통신이 가능하게 환경을 구축하고 wiringPi를 활용한 프로그램도 작성해 보았다.

이제 실제로 전송되는 8바이트 정도의 데이터를 주고 받는 프로그램을 구현할 계획이다.