우분투에서 Serial 장치 확인 및 권한 설정하는 방법

대상: 우분투에서 시리얼 장치(USB-시리얼, 보드 콘솔 등)를 연결하고 실제로 통신 테스트까지 해보고 싶은 개발자
환경: Ubuntu 18.04 기준, 터미널 사용 가능, C++/Python으로 시리얼을 쓸 예정인 사람

리눅스에서 시리얼 장치를 연결하면 제일 먼저 막히는 포인트가 보통 이거다.

  • 장치는 꽂았는데 포트 이름이 뭔지 모름
  • Permission denied 때문에 프로그램에서 못 염
  • 뭐가 문제인지 몰라서 보드/케이블/드라이버를 의심하게 되는 상황

이 글에서는, 우분투에서 시리얼 장치를 연결했을 때

  1. 장치가 제대로 인식됐는지 확인하고
  2. /dev/ttyUSB0, /dev/ttyACM0 같은 포트 이름을 찾고
  3. 권한 문제를 해결하고
  4. minicom/screen 으로 실제 통신 테스트까지 해본 다음
  5. 마지막에 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:2303
  • 10c4: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-시리얼 장치에 대해 권한과 그룹을 지정하고 싶을 때

  1. 먼저 lsusb로 VID/PID를 확인한다. (예: 067b:2303)
  2. 규칙 파일 생성:
sudo nano /etc/udev/rules.d/99-usb-serial.rules
  1. 아래 내용을 예시에 맞게 추가:
SUBSYSTEM=="tty", ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", GROUP:="dialout", MODE:="0660"
  1. 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
  • 설정 후 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/ttyUSB0 vs /dev/ttyUSB00)
  • 권한 문제 해결 안 된 상태에서 열려고 하는 것
  • 보드와 실제 통신 속도(baudrate)가 맞지 않는 것

이 세 가지만 조심해도
시리얼 통신 디버깅 스트레스가 상당히 줄어든다.


7. 정리 – 시리얼 문제 디버깅 루틴 만들기

우분투에서 시리얼이 안 될 때,
앞으로는 아래 순서대로만 점검해 보자.

  1. 하드웨어 연결 확인
    • 케이블, 포트, 보드 전원, 다른 PC에서 인식 여부
  2. 커널 인식 확인
    • dmesg | tail -n 30 → 어떤 이름으로 붙었는지 (ttyUSB0, ttyACM0 등)
  3. 장치 파일 확인
    • ls -l /dev/ttyUSB0 → 권한/그룹 체크
  4. 권한 문제 해결
    • sudo usermod -aG dialout $USER
    • 필요하다면 udev 규칙으로 VID/PID별 설정
  5. 터미널 프로그램으로 직접 테스트
    • minicom 또는 screen으로 실제 데이터 입출력 확인
  6. C++/Python 코드에서 사용
    • 포트 이름, 속도, 파라미터 재확인

이 루틴이 손에 익으면,
새로운 보드나 장치가 와도 겁먹지 않고 바로 “어디까지는 정상이고, 어디부터가 문제인지”를 빠르게 구분할 수 있게 된다.

다음 글에서는
리눅스에서 C++로 termios를 사용해 시리얼 포트를 여는 샘플 코드를
완전한 예제로 정리해볼 예정이다.

댓글 남기기