시리얼 통신에 대해서

1. ROS 2를 배우기 전에 알아두면 좋은 시리얼 통신 기초

ROS 2로 로봇이나 드론을 개발하다 보면 컴퓨터만으로 모든 장치를 직접 제어하기는 어렵습니다. 센서 값을 읽어야 하고, 모터 제어 보드에 명령을 보내야 하며, 배터리 상태나 GPS 정보도 받아와야 합니다.

이때 자주 사용하는 통신 방식이 바로 시리얼 통신입니다.

시리얼 통신은 오래전부터 사용되어 온 기본적인 통신 방식이지만, 지금도 로봇, 드론, 산업 장비, 센서 모듈, 제어 보드에서 매우 많이 사용됩니다. 구조가 단순하고 이해하기 쉬우며, ROS 2와 실제 하드웨어를 연결할 때도 자주 등장합니다.

이 글에서는 본격적으로 ROS 2 시리얼 통신 코드를 작성하기 전에 알아두면 좋은 내용을 살펴보겠습니다.

2. 시리얼 통신은 무엇인가요?

시리얼 통신은 데이터를 한 줄로 순서대로 보내는 통신 방식입니다.

여기서 시리얼은 직렬이라는 뜻입니다. 여러 개의 데이터를 동시에 보내는 것이 아니라, 하나의 통로를 통해 데이터를 차례대로 보냅니다.

아래 그림처럼 데이터를 한 줄로 줄 세워서 보내는 방식이라고 생각하시면 됩니다.

예를 들어 센서 보드가 거리 값을 측정해서 DIST:120이라는 데이터를 보낸다고 하겠습니다. 이 데이터는 한 번에 통째로 순간 이동하는 것이 아니라, 문자 또는 바이트 단위로 순서대로 전달됩니다.

받는 쪽에서는 들어온 데이터를 순서대로 모아서 다시 하나의 의미 있는 데이터로 해석합니다.

즉, 시리얼 통신은 데이터를 보내는 길이고, 그 데이터가 어떤 의미인지는 개발자가 정한 규칙에 따라 해석됩니다.

3. ROS 2에서 시리얼 통신이 필요한 이유

ROS 2는 로봇 시스템을 구성하는 데 매우 좋은 구조를 가지고 있습니다. 토픽, 서비스, 액션 같은 기능을 이용해서 여러 프로그램이 서로 데이터를 주고받을 수 있습니다.

하지만 실제 센서 보드나 제어 보드가 항상 ROS 2를 직접 사용하는 것은 아닙니다.

예를 들어 작은 STM32 보드, Arduino, ESP32, 모터 제어 보드, GPS 모듈, 배터리 관리 장치 같은 장치들은 ROS 2 노드로 직접 동작하지 않는 경우가 많습니다. 이런 장치들은 보통 UART, RS-232, RS-485 같은 방식으로 데이터를 주고받습니다.

그래서 ROS 2 컴퓨터와 외부 장치 사이에 시리얼 통신이 필요합니다.

예를 들어 거리 센서 보드가 시리얼로 거리 값을 보내면, ROS 2 노드는 그 값을 읽어서 /distance 토픽으로 발행할 수 있습니다.

반대로 ROS 2에서 모터 명령을 보내야 할 때는 다음과 같은 구조가 됩니다.

이 구조를 사용하면 ROS 2 내부에서는 토픽으로 데이터를 주고받고, 실제 하드웨어와 연결되는 부분만 시리얼 노드가 담당하게 됩니다.

4. 전체 구조를 그림으로 보면 더 쉽습니다

ROS 2와 센서 보드, 제어 보드가 연결되는 구조는 다음과 같이 생각할 수 있습니다.

센서 값을 읽는 경우에는 방향이 반대가 됩니다.

이렇게 보면 시리얼 노드는 ROS 2와 실제 하드웨어 사이에서 번역기 역할을 한다고 볼 수 있습니다.

5. 시리얼 통신에서 가장 중요한 약속

시리얼 통신은 보내는 쪽과 받는 쪽이 같은 약속을 가지고 있어야 합니다.

사람으로 비유하면 한쪽은 한국어로 말하는데 다른 쪽은 영어로 듣고 있으면 대화가 되지 않는 것과 비슷합니다. 통신에서도 속도와 형식이 맞아야 정상적으로 데이터를 주고받을 수 있습니다.

가장 대표적인 설정은 다음과 같습니다.

시리얼 통신 기본 설정

baud rate     : 통신 속도
data bits     : 데이터 비트 수
parity        : 오류 확인용 패리티 사용 여부
stop bits     : 데이터 끝을 표시하는 비트 수

처음에는 이 용어들이 어렵게 느껴질 수 있습니다. 하지만 실제로는 대부분 다음과 같은 설정을 많이 사용합니다.

115200 8N1

이 표현은 다음과 같은 뜻입니다.

115200 : 통신 속도
8      : 데이터 비트 8개
N      : 패리티 없음
1      : 스톱 비트 1개

즉, 115200 8N1은 “115200 속도로, 데이터 8비트씩, 패리티 없이, 스톱 비트 1개로 통신하겠습니다”라는 의미입니다.

센서 보드가 115200으로 보내는데 ROS 2 컴퓨터가 9600으로 받으면 데이터가 깨져 보입니다. 그래서 시리얼 통신이 안 될 때는 baud rate가 맞는지 먼저 확인해야 합니다.

6. TX와 RX 연결 이해하기

시리얼 통신에서 가장 많이 보는 핀이 TX와 RX입니다.

TX는 데이터를 보내는 핀입니다. RX는 데이터를 받는 핀입니다.

두 장치를 연결할 때는 TX와 RX를 서로 교차해서 연결해야 합니다.

이것을 사람의 대화로 생각하면 쉽습니다.

즉, 보내는 쪽은 받는 쪽으로 연결되어야 합니다. TX끼리 연결하거나 RX끼리 연결하면 서로 말만 하거나 듣기만 하는 상태가 되어 통신이 되지 않습니다.

또 하나 중요한 것은 GND입니다.

GND는 두 장치가 같은 기준 전압을 사용하도록 맞춰주는 역할을 합니다. GND를 연결하지 않으면 신호의 기준이 맞지 않아서 통신이 불안정하거나 아예 되지 않을 수 있습니다.

실제로 시리얼 통신이 안 될 때는 코드보다 배선 문제가 더 흔한 경우도 많습니다. 특히 TX, RX 방향과 GND 연결은 꼭 확인해야 합니다.

7. UART, RS-232, RS-485의 차이

시리얼 통신을 공부하다 보면 UART, RS-232, RS-485라는 용어를 보게 됩니다. 처음에는 모두 비슷해 보이지만, 실제로는 사용하는 환경과 전기적 특성이 다릅니다.

간단히 구분하면 다음과 같습니다.

그림으로 보면 다음과 같이 이해할 수 있습니다.

ROS 2 강의에서 처음 다루는 시리얼 통신은 보통 UART 기반으로 시작하는 것이 좋습니다. 구조가 단순하고, 센서 보드나 제어 보드를 연결하는 예제로 사용하기 좋기 때문입니다.

8. 데이터 형식은 개발자가 정해야 합니다

시리얼 통신은 데이터를 주고받는 길입니다. 하지만 이 길을 통해 어떤 모양의 데이터를 보낼지는 개발자가 정해야 합니다.

예를 들어 거리 센서 값을 보낸다면 다음과 같이 정할 수 있습니다.

DIST:120

이 데이터는 “거리 값이 120입니다”라는 의미로 사용할 수 있습니다.

온도와 습도를 같이 보낸다면 다음처럼 만들 수도 있습니다.

TEMP:25.3,HUM:61.2

모터 명령을 보낸다면 다음과 같이 만들 수 있습니다.

MOTOR:100

LED를 제어한다면 다음처럼 만들 수 있습니다.

LED:ON

이런 방식은 문자열 기반 통신입니다. 사람이 읽기 쉽고, 터미널에서 바로 확인할 수 있어서 처음 배우기에 좋습니다.

데이터가 흘러가는 모습을 그림으로 보면 다음과 같습니다.

처음에는 이렇게 사람이 읽을 수 있는 문자열 방식으로 시작하는 것이 좋습니다. 나중에 더 빠른 속도나 안정성이 필요하면 바이너리 프로토콜, 체크섬, 패킷 구조를 추가하면 됩니다.

9. 메시지의 시작과 끝을 정하는 이유

시리얼 통신에서는 데이터가 계속 이어져서 들어옵니다. 그래서 받는 쪽에서는 어디부터 어디까지가 하나의 메시지인지 알아야 합니다.

가장 쉬운 방법은 줄바꿈 문자를 사용하는 것입니다.

DIST:120\n

여기서 \n은 줄바꿈을 의미합니다. ROS 2 노드는 \n이 나올 때까지 데이터를 모으고, 줄바꿈이 들어오면 하나의 메시지로 처리할 수 있습니다.

조금 더 명확하게 만들고 싶다면 시작 문자와 끝 문자를 사용할 수 있습니다.

<DIST:120>

이 경우 <는 시작, >는 끝을 의미합니다.

이 방식을 사용하면 데이터가 조금 섞이거나 중간에 깨졌을 때도 다음 메시지를 다시 찾기 쉽습니다.

실제 로봇이나 드론에서는 잘못된 데이터 하나가 동작에 영향을 줄 수 있습니다. 그래서 메시지의 시작과 끝을 명확히 정하는 습관이 중요합니다.

10. 체크섬은 데이터가 깨졌는지 확인하는 방법

시리얼 통신은 단순하지만 항상 완벽하게 데이터가 전달된다고 보장할 수는 없습니다. 노이즈가 있거나 배선이 불안정하거나 통신 중간에 문제가 생기면 데이터가 깨질 수 있습니다.

그래서 조금 더 안정적인 통신에서는 체크섬을 사용합니다.

체크섬은 데이터가 제대로 도착했는지 확인하기 위한 값입니다.

간단한 구조는 다음과 같습니다.

<데이터,체크섬>

예를 들어 다음과 같은 형태로 보낼 수 있습니다.

<DIST:120,CK:45>

수신 쪽은 DIST:120 데이터를 이용해서 다시 체크섬을 계산합니다. 그리고 받은 체크섬 값과 비교합니다.

송신 쪽 계산 체크섬  = 45
수신 쪽 계산 체크섬  = 45

결과: 정상 데이터

만약 값이 다르면 데이터가 전송 중에 깨졌다고 판단할 수 있습니다.

송신 쪽 체크섬 = 45
수신 쪽 체크섬 = 31

결과: 오류 데이터

11. ROS 2 시리얼 노드의 역할

ROS 2에서 시리얼 노드는 하드웨어와 ROS 2 시스템 사이의 변환기 역할을 합니다.

센서 값을 읽는 경우에는 다음과 같은 흐름이 됩니다.

모터 명령을 보내는 경우에는 반대 방향입니다.

즉, ROS 2 시리얼 노드는 두 가지 일을 합니다.

첫 번째는 시리얼 데이터를 읽어서 ROS 2 토픽으로 바꾸는 일입니다.

두 번째는 ROS 2 토픽이나 명령을 받아서 시리얼 데이터로 바꾸는 일입니다.

이렇게 역할을 나누면 다른 ROS 2 노드들은 시리얼 통신의 세부 내용을 몰라도 됩니다. 센서 값은 토픽으로 받고, 제어 명령은 토픽으로 보내면 됩니다.

12. 리눅스에서 시리얼 장치

ROS 2는 Ubuntu 같은 리눅스 환경에서 많이 사용합니다. 리눅스에서는 시리얼 장치가 파일처럼 표시됩니다.

USB to UART 모듈을 연결하면 보통 다음과 같은 이름으로 나타납니다.

/dev/ttyUSB0
/dev/ttyUSB1
/dev/ttyACM0

구조를 간단히 보면 다음과 같습니다.

ROS 2 노드는 /dev/ttyUSB0 같은 장치 파일을 열어서 데이터를 읽고 씁니다.

다만 장치를 뺐다가 다시 연결하면 번호가 바뀔 수 있습니다.

이렇게 되면 ROS 2 노드가 기존 포트 이름을 찾지 못할 수 있습니다. 실제 장비에서는 이런 문제를 줄이기 위해 udev rule을 사용해서 장치 이름을 고정하는 방법을 사용하기도 합니다.

우분투에서 USB 장치 심볼릭 링크 만들기

13. 통신 테스트는 ROS 2 코드 작성 전에 먼저 합니다

처음부터 ROS 2 코드를 작성해서 테스트하면 문제가 생겼을 때 원인을 찾기 어렵습니다.

통신이 안 되는 이유가 배선 문제인지, 포트 문제인지, 권한 문제인지, 코드 문제인지 구분하기 어렵기 때문입니다.

그래서 먼저 터미널 프로그램으로 시리얼 데이터가 들어오는지 확인하는 것이 좋습니다.

Ubuntu에서는 screen, minicom, cutecom 같은 도구를 사용할 수 있습니다.

예를 들어 다음 명령으로 포트를 열 수 있습니다.

screen /dev/ttyUSB0 115200

이 명령은 /dev/ttyUSB0 포트를 115200 속도로 열겠다는 의미입니다.

테스트 흐름은 다음과 같습니다.

터미널에서 데이터가 정상적으로 보이면 하드웨어 연결과 기본 통신 설정은 어느 정도 맞다고 볼 수 있습니다. 그다음 ROS 2 노드를 작성하면 문제를 훨씬 쉽게 찾을 수 있습니다.

Leave a Comment