python 시리얼 통신 - 라즈베리파이4(raspberry pi 4)와 PC간 usb 시리얼 통신

개요

라즈베리 파이4와 PC간에 USB 통신에 대한 방법에 대해서 살펴보겠다.(파이썬을 이용)

라즈베리 파이4는 이전 버전과는 달리 USB-C포트를 이용해서 USB to serial을 사용할 수 있다. 이는 기존에는 라즈베리파이 제로에만 있던 기능이다.

라즈베리 파이 4 USB Gadget Mode

라즈베리 파이4는 라즈베리파이 제로와 같은 방법으로 USB to serial을 사용할 수 있다.

라즈베리 파이4의 USB-C 포트는 기본적으로 전원으로 사용하지만 해당 포트를 PC에 연결함으로서 USB를 사용한 여러가지 방법으로 사용할 수 있다.

라즈베리파이4와 PC간 USB Gadget Mode 연결

USB Gadget Mode를 사용하기 위한 셋팅은 아래와 같다.

1. config.txt 파일 수정

boot/config.txt파일을 수정한다.

해당 파일의 마지막에 아래의 내용을 추가한다.

1
dtoverlay=dwc2

2. modules 파일 수정

/etc/modules파일을 수정한다.

해당 파일에 아래와 같이 추가한다.

1
2
dwc2
g_serial

시리얼을 콘솔로 사용하고 싶다면
커맨드창에 sudo systemctl enable getty@ttyGS0.service을 입력한다.

기타 모듈

시리얼 말고도 여러가지 방법으로 USB Gadget Mode를 사용 가능하다.

가능한 리스트는 아래와 같다.

  • Serial (g_serial)
  • Ethernet (g_ether)
  • Mass storage (g_mass_storage)
  • MIDI (g_midi)
  • Audio (g_audio)
  • Keyboard/Mouse (g_hid)
  • Mass storage and Serial (g_acm_ms)
  • Ethernet and Serial (g_cdc)
  • Multi (g_multi) - Allows you to configure 2 from Ethernet, Mass storage and Serial
    In addition to the above modules, a few other (less useful) modules are included.
  • Webcam (g_webcam)
  • Printer (g_printer)
  • Gadget tester (g_zero)

더 자세한 내용은 아래 링크를 참조한다.

https://gist.github.com/gbaman/50b6cca61dd1c3f88f41

pyserial

파이썬에서 시리얼을 사용하기 위해선 pyserial을 사용한다.

인스톨은 아래와 같다.

1
pip install pyserial

pyserial을 사용하기 위해서 import는 다음과 같이 한다.

1
import serial

pyserial 접속

라즈베리파이4에서 USB Gadget Mode로 연결하였다면 장치 파일은 /dev/ttyGS0이 된다.

아래와 같이 접속을 한다.

1
2
3
4
5
# 리눅스
SER = serial.Serial('/dev/ttyGS0', 115200)

# windows
SER = serial.Serial('COM-14', 115200)

첫번째 파라미터는 장치 파일을 뜻한다. window에서 사용한다면 ‘COM-14’와 같이 사용한다.

두번째 파라미터는 속도를 뜻한다. 시리얼 통신시 양측 모두 속도가 같아야 정상적으로 통신이 가능하다.

해당 PC 또는 라즈베리 파이에서 연결되어 있는 포트 또는 장치 파일을 찾는 것은 다음과 같이 가능하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def serial_ports(self):
""" Lists serial port names

:raises EnvironmentError:
On unsupported or unknown platforms
:returns:
A list of the serial ports available on the system
"""
if sys.platform.startswith('win'):
ports = ['COM%s' % (i + 1) for i in range(256)]
elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
# this excludes your current terminal "/dev/tty"
ports = glob.glob('/dev/tty[A-Za-z]*')
elif sys.platform.startswith('darwin'):
ports = glob.glob('/dev/tty.*')
else:
raise EnvironmentError('Unsupported platform')

result = []
for port in ports:
try:
s = serial.Serial(port)
s.close()
result.append(port)
except (OSError, serial.SerialException):
pass
return result

pyserial 쓰기 및 읽기

쓰기 및 읽기는 다음과 같이 사용한다.

1
2
3
4
5
# 읽기
c = SER.read()

# 쓰기
SER.write(data)

읽고 쓰는 것은 간단하지만 시리얼 통신은 모두 byte로 이루어지기 때문에 변환이 필요하다.

str 변환 방법

파이썬에서 문자열을 바이트로 바꾸는 것은 아래와 같이 이루어진다.

1
abc_str = b'abcd'

특정 문자열을 읽고 싶을때는 아래와 같이 사용하면 된다.

1
2
3
4
5
6
7
8
9
10
11
LINE = bytearray() #라인 단위로 데이터 가져올 리스트 변수

for c in ser.read():
#line 변수에 차곡차곡 추가하여 넣는다.
LINE.append(c)
byte_line = bytes(LINE)

if byte_line.find(b'abcd') != -1:
print("abcd = True")
LINE.clear()
ser.flushInput()

읽은 문자열을 str 형식으로 변경하고 싶으면 아래와 같이 사용한다.

1
2
3
4
5
6
7
8
9
10
LINE = bytearray()

for c in ser.read():
LINE.append(c)
byte_line = bytes(LINE)

if byte_line.find(b'abcd') != -1:
str_decoded = byte_line.decode('ascii')
LINE.clear()
ser.flushInput()

반대로 특정 문자열을 쓰고 싶을때는 아래와 같이 사용한다.

1
2
msg = abcd
SER.write(msg.encode())

위에서 encode 대신 b를 붙여 사용해도 된다.

int 변환 방법

int를 변경하기 위해서는 int.from_bytes() 와 int.to_bytes()를 사용한다.

1
2
3
4
5
# int → byte 변환
foc_val = int.to_bytes(self.foc_slider.value(), length=len(str(self.foc_slider.value())), byteorder='big')

# byte → int 변환
foc_val_int = int.from_bytes(foc_val, byteorder='big')
공유하기