대상: 우분투에서 시리얼 장치(USB-시리얼, 보드 콘솔 등)를 연결하고 실제로 통신 테스트까지 해보고 싶은 개발자
환경: Ubuntu 18.04 기준, 터미널 사용 가능, C++/Python으로 시리얼을 쓸 예정인 사람
리눅스에서 시리얼 장치를 연결하면 제일 먼저 막히는 포인트가 보통 이거다.
- 장치는 꽂았는데 포트 이름이 뭔지 모름
Permission denied때문에 프로그램에서 못 염- 뭐가 문제인지 몰라서 보드/케이블/드라이버를 의심하게 되는 상황
이 글에서는, 우분투에서 시리얼 장치를 연결했을 때
- 장치가 제대로 인식됐는지 확인하고
/dev/ttyUSB0,/dev/ttyACM0같은 포트 이름을 찾고- 권한 문제를 해결하고
minicom/screen으로 실제 통신 테스트까지 해본 다음- 마지막에 C++/Python에서 사용할 때 간단한 주의점
까지 한 번에 정리해볼 거야.
1. 시리얼 장치 연결 후 dmesg로 장치 이름 확인하기
가장 먼저 할 일은 “커널이 이 장치를 어떻게 인식했는지”를 보는 거다.
우분투에서 USB-시리얼 어댑터나 보드의 USB 콘솔 포트를 꽂은 직후, 아래 명령어를 실행해 보자.
dmesg | tail -n 30
dmesg: 커널 메시지 출력tail -n 30: 마지막 30줄만 보기
여기에서 보통 이런 식의 로그를 볼 수 있다.
[ 1234.567890] usb 1-2: new full-speed USB device number 7 using xhci_hcd
[ 1234.678901] usb 1-2: New USB device found, idVendor=067b, idProduct=2303
[ 1234.678905] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 1234.679234] pl2303 1-2:1.0: pl2303 converter detected
[ 1234.680000] usb 1-2: pl2303 converter now attached to ttyUSB0
여기서 제일 중요한 건 마지막 줄:
pl2303 converter now attached to ttyUSB0
이 메시지가 의미하는 건:
- 이 USB-시리얼 칩셋은 PL2303이고
- 커널이 이 장치를
/dev/ttyUSB0라는 이름으로 붙였다는 뜻이다.
만약 보드에 따라서는 cdc_acm 같은 드라이버가 올라가면서
cdc_acm 1-2:1.0: ttyACM0: USB ACM device
처럼 ttyACM0 라는 이름으로 붙기도 한다.
2. /dev/ttyUSB0 vs /dev/ttyACM0 간단 정리
리눅스에서 시리얼 장치는 주로 두 가지 이름으로 많이 보인다.
/dev/ttyUSB0,/dev/ttyUSB1…/dev/ttyACM0,/dev/ttyACM1…
간단하게만 정리하면:
ttyUSB: USB-시리얼 변환 칩셋(PL2303, CP210x, FTDI 등)을 통해 연결된 가상 시리얼 포트ttyACM: 주로 CDC-ACM(USB Communications Device Class – Abstract Control Model) 장치,
보드의 USB 디버그/콘솔 포트가 이렇게 잡히는 경우가 많다.
실제로 C++/Python에서 열 때는
둘 다 그냥 “시리얼 포트”라고 생각하면 된다.
중요한 건 “내 장치가 지금 어느 이름으로 붙었는지”를 아는 것.
그걸 앞에서 본 dmesg 로그로 확인한 거다.
추가로, 현재 시스템에 어떤 시리얼 장치가 있는지도 이렇게 확인할 수 있다.
ls /dev/ttyUSB* /dev/ttyACM* 2>/dev/null
연결된 장치가 없다면 아무 것도 안 나오고,
있다면 예를 들어:
/dev/ttyUSB0
이런 식으로 표시될 거다.
3. lsusb로 장치 벤더/제품 ID 확인하기
가끔은 같은 모델의 시리얼 어댑터가 여러 개 꽂혀 있거나,
여러 보드가 섞여 있을 수도 있다. 이럴 때는 lsusb로 장치 정보를 더 자세히 보는 게 도움이 된다.
lsusb
실행하면 대략 이런 식으로 나온다.
Bus 001 Device 007: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port
Bus 001 Device 008: ID 10c4:ea60 Silicon Labs CP210x UART Bridge
여기서 중요한 건 ID 뒤에 나오는 숫자 두 개:
067b:230310c4:ea60
이게 각각 Vendor ID (VID)와 Product ID (PID)다.
이 정보는 나중에 udev 규칙을 써서 특정 장치에 고정된 이름을 붙일 때 필요하다.
예를 들어, 두 개의 USB-시리얼 장치를 항상
하나는/dev/ttyGPS, 다른 하나는/dev/ttyMOTOR이런 식으로
고정 이름을 주고 싶을 때 VID/PID 조합을 사용하게 된다.
4. 권한 문제 해결: dialout 그룹 & chmod vs udev
이제 장치 이름까지 알았는데, 프로그램에서 열려고 하면 이런 오류를 만날 수 있다.
Permission denied: '/dev/ttyUSB0'
리눅스에서는 시리얼 포트 접근 권한이 보통 특정 그룹(예: dialout)에 묶여 있다.
4-1. 현재 장치의 권한 확인
아래 명령으로 확인해보자.
ls -l /dev/ttyUSB0
예를 들어 이런 결과가 나올 수 있다.
crw-rw---- 1 root dialout 188, 0 7월 1 12:34 /dev/ttyUSB0
여기서 눈여겨볼 부분:
- 소유자:
root - 그룹:
dialout - 권한:
crw-rw----→ owner와 group에게만 read/write 허용
즉, 현재 로그인한 사용자가 dialout 그룹에 속해 있지 않으면
이 포트를 열려고 할 때 Permission denied가 뜬다.
4-2. 사용자에게 dialout 그룹 권한 부여
자기 계정을 dialout 그룹에 추가해주면 된다.
sudo usermod -aG dialout $USER
그 다음 로그아웃 후 다시 로그인해야 그룹 변경이 적용된다.
(터미널만 닫았다 여는 걸로는 부족한 경우가 많다.)
다시 로그인한 후 아래 명령으로 그룹 목록을 확인해보자.
groups
출력에 dialout이 포함돼 있으면 OK.
이제 /dev/ttyUSB0를 열 때 sudo 없이도 접근이 가능해진다.
4-3. 임시로 chmod로 권한 풀기 (테스트용)
급하게 테스트만 해보고 싶다면,
임시로 장치 권한을 널널하게 풀 수도 있다.
sudo chmod 666 /dev/ttyUSB0
이렇게 하면 모든 사용자에게 read/write 권한을 주게 된다.
다만, 재부팅하거나 장치를 뺐다 꽂으면 이 설정은 다시 초기화된다.
테스트용으로는 괜찮지만, 상시 사용 환경에서는 udev 규칙이나 dialout 그룹을 쓰는 게 좋다.
4-4. udev 규칙으로 자동 권한/이름 설정 (간단 버전)
장치를 매번 꽂을 때마다 권한을 만지는 게 귀찮다면udev 규칙을 이용해서 자동으로 설정할 수 있다.
예: 특정 VID/PID를 가진 USB-시리얼 장치에 대해 권한과 그룹을 지정하고 싶을 때
- 먼저
lsusb로 VID/PID를 확인한다. (예:067b:2303) - 규칙 파일 생성:
sudo nano /etc/udev/rules.d/99-usb-serial.rules
- 아래 내용을 예시에 맞게 추가:
SUBSYSTEM=="tty", ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", GROUP:="dialout", MODE:="0660"
- udev 재적용:
sudo udevadm control --reload-rules
sudo udevadm trigger
이제 해당 VID/PID를 가진 시리얼 장치를 꽂으면
자동으로 dialout 그룹과 0660 권한이 적용된다.
더 나아가서
SYMLINK+="ttyMYDEVICE"같은 옵션을 사용하면
항상/dev/ttyMYDEVICE라는 별칭으로 접근하는 것도 가능하다.
5. minicom/screen으로 실제 통신 테스트해보기
이제 하드웨어 연결 + 권한 문제까지 해결했으니,
실제로 데이터가 주고받아지는지 확인해 보자.
5-1. minicom 설치
sudo apt update
sudo apt install -y minicom
5-2. minicom 기본 설정
처음 한 번은 설정을 해주는 게 좋다.
sudo minicom -s
Serial port setup메뉴로 들어가서- Serial Device:
/dev/ttyUSB0(또는/dev/ttyACM0) - Bps/Par/Bits: 예를 들어
115200 8N1
- Serial Device:
- 설정 후
Save setup as dfl(기본값으로 저장)
그 다음부터는 그냥:
minicom
만 실행해도 바로 기본 포트/속도로 연결된다.
장치가 주기적으로 로그를 쏴주는 보드라면,
여기서 콘솔 메시지를 바로 볼 수 있어야 정상이다.
5-3. screen으로 간단 테스트 (대안)
screen을 이용해서도 간단히 연결해볼 수 있다.
sudo apt install -y screen
screen /dev/ttyUSB0 115200
- 종료는
Ctrl + A, 그 다음K, 그리고y입력.
6. C++/Python에서 시리얼 열 때 기본 주의사항
이제 실제 프로젝트에서 C++/Python으로 시리얼을 사용할 때
기본적으로 신경 써야 할 포인트만 짧게 짚고 넘어가자.
6-1. C++ (termios 사용 시)
리눅스에서 C++로 시리얼을 다룰 때는 보통 termios를 사용한다.
주의할 점은:
- 블로킹/논블로킹 모드를 어떻게 할지
- 입출력 버퍼 설정 (raw 모드 vs canonical) 을 어떻게 할지
- 속도 설정 시
B115200같은 매크로를 써야 한다는 점
간단한 예시는 다음 글(A4)에서 전체 코드로 다룰 예정이라
여기선 개념만 짚고 넘어가면 된다.
6-2. Python (pyserial 사용 시)
Python에서는 pyserial이 사실상의 표준이다.
설치:
pip install pyserial
간단한 예:
import serial
ser = serial.Serial(
port="/dev/ttyUSB0",
baudrate=115200,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=1.0, # 1초 타임아웃
)
ser.write(b"Hello\r\n")
data = ser.readline()
print("Received:", data)
ser.close()
여기서 가장 많이 나는 실수는:
- 포트 이름 오타 (
/dev/ttyUSB0vs/dev/ttyUSB00) - 권한 문제 해결 안 된 상태에서 열려고 하는 것
- 보드와 실제 통신 속도(baudrate)가 맞지 않는 것
이 세 가지만 조심해도
시리얼 통신 디버깅 스트레스가 상당히 줄어든다.
7. 정리 – 시리얼 문제 디버깅 루틴 만들기
우분투에서 시리얼이 안 될 때,
앞으로는 아래 순서대로만 점검해 보자.
- 하드웨어 연결 확인
- 케이블, 포트, 보드 전원, 다른 PC에서 인식 여부
- 커널 인식 확인
dmesg | tail -n 30→ 어떤 이름으로 붙었는지 (ttyUSB0,ttyACM0등)
- 장치 파일 확인
ls -l /dev/ttyUSB0→ 권한/그룹 체크
- 권한 문제 해결
sudo usermod -aG dialout $USER- 필요하다면 udev 규칙으로 VID/PID별 설정
- 터미널 프로그램으로 직접 테스트
minicom또는screen으로 실제 데이터 입출력 확인
- C++/Python 코드에서 사용
- 포트 이름, 속도, 파라미터 재확인
이 루틴이 손에 익으면,
새로운 보드나 장치가 와도 겁먹지 않고 바로 “어디까지는 정상이고, 어디부터가 문제인지”를 빠르게 구분할 수 있게 된다.
다음 글에서는
리눅스에서 C++로 termios를 사용해 시리얼 포트를 여는 샘플 코드를
완전한 예제로 정리해볼 예정이다.