파이썬 시리얼 통신 완벽 가이드: pyserial과 struct 활용법

2025. 10. 20. 12:01·파이썬/Basic
반응형

 

목차

  • 1. 왜 파이썬으로 시리얼 통신을 할까?
  • 2. `pyserial` - 시리얼 통신의 시작
    • 2.1. 설치 및 포트 확인
    • 2.2. 기본 사용법: 연결, 송신, 수신
    • 2.3. 간단한 예제: 아두이노와 문자열 주고받기
  • 3. `struct` - 바이너리 데이터 다루기
    • 3.1. 왜 문자열이 아닌 바이너리 데이터를 사용할까?
    • 3.2. 핵심 함수: `pack`과 `unpack`
    • 3.3. 데이터 구조를 정의하는 '포맷 문자열'
  • 4. 실전 예제: `pyserial`과 `struct`로 센서 데이터 받기
    • 4.1. 아두이노 코드: 정수와 실수를 struct로 전송
    • 4.2. 파이썬 코드: 수신 후 struct로 해석
  • 5. 결론

1. 왜 파이썬으로 시리얼 통신을 할까?

아두이노, 라즈베리파이, 각종 산업용 장비 등 많은 하드웨어는 시리얼 통신(Serial Communication)을 통해 외부와 데이터를 주고받습니다. 파이썬은 쉽고 강력한 pyserial 라이브러리를 제공하여 이러한 장치들과 손쉽게 통신할 수 있는 환경을 제공합니다.

단순한 텍스트를 넘어 온도, 습도 같은 센서 값이나 모터 제어 명령 등 정수, 실수 형태의 데이터를 주고받을 때는 바이너리(binary) 형식으로 변환하는 과정이 필요합니다. 이때 struct 모듈이 빛을 발합니다. 이 두 가지를 조합하면 매우 안정적이고 효율적인 데이터 통신이 가능합니다.

2. pyserial - 시리얼 통신의 시작

pyserial은 파이썬에서 시리얼 포트(COM 포트)를 제어하기 위한 표준 라이브러리입니다.

2.1. 설치 및 포트 확인

먼저 pip을 이용해 pyserial을 설치합니다.

pip install pyserial

설치 후, 장치가 어떤 COM 포트에 연결되었는지 확인해야 합니다.

  • Windows: 장치 관리자 → 포트 (COM & LPT) 에서 확인 (예: `COM3`)
  • Linux: 터미널에서 `ls /dev/tty*` 명령어로 확인 (예: `/dev/ttyUSB0` 또는 `/dev/ttyACM0`)
  • macOS: 터미널에서 `ls /dev/cu.*` 명령어로 확인 (예: `/dev/cu.usbmodem1411`)

2.2. 기본 사용법: 연결, 송신, 수신

기본적인 사용법은 매우 간단합니다. `serial.Serial` 객체를 생성하고, `write()`와 `read()` 메서드를 사용하면 됩니다.

import serial
import time

# 시리얼 포트와 보드레이트를 설정하여 객체 생성
# 포트 이름은 실제 연결된 포트에 맞게 수정해야 함
# 보드레이트(baudrate)는 장치와 동일하게 설정해야 함
ser = serial.Serial('COM3', 9600, timeout=1)

# 데이터 보내기 (bytes 형태로 인코딩 필요)
ser.write(b'Hello Arduino\n')

# 잠시 대기
time.sleep(1)

# 데이터 읽기
if ser.in_waiting > 0:
    # readline()은 \n을 만날 때까지 읽음
    line = ser.readline().decode('utf-8').rstrip()
    print(line)

# 포트 닫기
ser.close()

`write()`는 바이트(bytes)를 보냅니다!

파이썬3부터 문자열과 바이트가 명확히 구분됩니다. `ser.write()`로 데이터를 보낼 때는 반드시 바이트 형태로 보내야 합니다. 문자열 앞에 `b`를 붙이거나 (`b'hello'`), `.encode()` 메서드를 사용 (`'hello'.encode('utf-8')`)하여 바이트로 변환할 수 있습니다.

2.3. 간단한 예제: 아두이노와 문자열 주고받기

파이썬에서 '1'을 보내면 LED를 켜고, '0'을 보내면 끄는 간단한 예제입니다.

아두이노 코드

void setup() {
  Serial.begin(9600);
  pinMode(13, OUTPUT);
}

void loop() {
  if (Serial.available() > 0) {
    char data = Serial.read();
    if (data == '1') {
      digitalWrite(13, HIGH);
      Serial.println("LED ON");
    } else if (data == '0') {
      digitalWrite(13, LOW);
      Serial.println("LED OFF");
    }
  }
}

파이썬 코드

import serial
ser = serial.Serial('COM3', 9600)

ser.write(b'1') # LED 켜기
response = ser.readline().decode().strip()
print(f"Arduino says: {response}")

ser.close()

3. struct - 바이너리 데이터 다루기

3.1. 왜 문자열이 아닌 바이너리 데이터를 사용할까?

문자열 "3.14"는 4바이트를 차지하지만, 실제 4바이트 실수(float)는 훨씬 더 정밀한 값을 표현할 수 있습니다. 여러 센서 데이터를 보낼 때 "temp:25.5,humi:60.2"처럼 문자열로 보내면 파싱(parsing) 과정이 번거롭고 데이터 크기도 커집니다. `struct`를 사용해 정수, 실수 등을 정해진 규격의 바이트 덩어리(struct)로 만들어 보내면, 파싱 없이 바로 데이터로 변환할 수 있어 효율적입니다.

3.2. 핵심 함수: `pack`과 `unpack`

`struct` 모듈의 핵심은 두 함수입니다.

  • struct.pack(format, v1, v2, ...): 주어진 포맷에 따라 값들을 바이트 객체로 압축(packing)합니다.
  • struct.unpack(format, buffer): 바이트 객체를 주어진 포맷에 따라 값들의 튜플로 해제(unpacking)합니다.

3.3. 데이터 구조를 정의하는 '포맷 문자열'

`pack`과 `unpack`의 첫 인자인 포맷 문자열은 데이터의 구조, 순서, 크기를 정의합니다.

문자 C 타입 파이썬 타입 크기(byte)
< 리틀 엔디안 (Little-endian) -
B unsigned char integer 1
h short integer 2
i int integer 4
f float float 4

예를 들어, 포맷 '<Bf'는 '리틀 엔디안 방식으로, 1바이트 부호 없는 정수(B) 1개와 4바이트 실수(f) 1개가 순서대로 있다'는 의미입니다.

4. 실전 예제: `pyserial`과 `struct`로 센서 데이터 받기

아두이노가 LED 상태(0 또는 1)와 가상의 온도 값(실수)을 `struct`를 이용해 파이썬으로 보내는 예제입니다.

4.1. 아두이노 코드: 정수와 실수를 struct로 전송

// 데이터 구조체 정의
struct SensorData {
  byte ledState;     // 1바이트 정수
  float temperature; // 4바이트 실수
};

SensorData data;

void setup() {
  Serial.begin(9600);
  data.ledState = 1; // 초기 LED 상태
}

void loop() {
  // 가상의 온도 값 생성
  data.temperature = 20.0 + (millis() % 1000) / 100.0;

  // 구조체를 바이트 배열로 전송
  Serial.write((byte*)&data, sizeof(data));

  delay(1000);
}

4.2. 파이썬 코드: 수신 후 struct로 해석

import serial
import struct

# 포맷 문자열 (아두이노 struct와 일치해야 함)
# < : Little-endian
# B : unsigned char (1 byte)
# f : float (4 bytes)
data_format = '<Bf'
data_size = struct.calcsize(data_format) # 포맷의 총 바이트 크기 계산 (5)

ser = serial.Serial('COM3', 9600)

print(f"Waiting for {data_size} bytes of data...")

while True:
    if ser.in_waiting >= data_size:
        # 정확히 필요한 바이트 수만큼 읽기
        packet = ser.read(data_size)

        # unpack을 사용하여 바이트를 데이터로 변환
        # 결과는 튜플로 반환됨
        unpacked_data = struct.unpack(data_format, packet)

        led_state = unpacked_data[0]
        temperature = unpacked_data[1]

        print(f"Received -> LED State: {led_state}, Temperature: {temperature:.2f} C")

ser.close() # 실제로는 루프를 빠져나올 로직이 필요

`struct.calcsize()`의 중요성

데이터를 읽을 때 `ser.read(struct.calcsize(format))` 처럼 정확한 크기를 지정하면, 데이터가 깨지거나 동기화가 맞지 않는 문제를 예방할 수 있습니다. 통신 프로토콜을 설계할 때 매우 유용한 함수입니다.

5. 결론

파이썬으로 하드웨어와 시리얼 통신을 할 때 `pyserial`은 통신 채널을, `struct`는 데이터의 형식을 담당하는 환상의 조합입니다.

  • 간단한 제어 신호나 텍스트는 `pyserial`만으로 충분합니다.
  • 여러 종류의 센서 데이터나 수치 데이터를 주고받을 때는 `struct`를 함께 사용하면 훨씬 간결하고 안정적인 코드를 작성할 수 있습니다.

이 가이드를 바탕으로 여러분의 파이썬 프로젝트와 다양한 하드웨어를 성공적으로 연결해보시길 바랍니다.

#파이썬 #pyserial #struct #시리얼통신 #아두이노 #PythonSerial #BinaryData

'파이썬 > Basic' 카테고리의 다른 글

딕셔너리 빈 값 제거 완전 가이드: 깔끔한 데이터 정리 기법  (2) 2025.06.04
Python의 UnicodeDecodeError 해결하기: cp949 코덱 오류  (0) 2025.05.09
Python JSON 라이브러리 비교: json vs ujson vs orjson  (0) 2025.02.26
Geopy : 지리 정보 다루기  (2) 2025.02.10
lru_cache : 캐싱 메모리  (0) 2025.02.08
'파이썬/Basic' 카테고리의 다른 글
  • 딕셔너리 빈 값 제거 완전 가이드: 깔끔한 데이터 정리 기법
  • Python의 UnicodeDecodeError 해결하기: cp949 코덱 오류
  • Python JSON 라이브러리 비교: json vs ujson vs orjson
  • Geopy : 지리 정보 다루기
코샵
코샵
나의 코딩 일기장
    반응형
  • 코샵
    끄적끄적 코딩 공방
    코샵
    • 분류 전체보기 (730)
      • 스마트팜 (1)
      • 상품 추천 (223)
      • DataBase (0)
        • MongoDB (4)
        • PostgreSQL (0)
      • 하드웨어 (19)
      • 일기장 (4)
      • 파이썬 (131)
        • Basic (42)
        • OpenCV (8)
        • Pandas (15)
        • PyQT (3)
        • SBC(Single Board Computer) (1)
        • 크롤링 (14)
        • Fast API (29)
        • Package (6)
      • Unity (138)
        • Tip (41)
        • Project (1)
        • Design Pattern (8)
        • Firebase (6)
        • Asset (2)
      • Linux (5)
      • C# (97)
        • Algorithm (11)
        • Window (7)
      • TypeScript (51)
        • CSS (10)
      • Git (11)
      • SQL (5)
      • Flutter (10)
        • Tip (1)
      • System (1)
      • BaekJoon (6)
      • Portfolio (2)
      • MacOS (1)
      • 유틸리티 (1)
      • 서비스 (6)
      • 자동화 (3)
      • Hobby (10)
        • 물생활 (10)
        • 식집사 (0)
  • 인기 글

  • 태그

    카페24리뷰
    셀레니움
    unity
    상품 리뷰 크롤링
    라떼우유
    파이썬
    유니티
    리스트
    list
    learntocode
    codingtips
    appdevelopment
    rtsp
    programming101
    스크립트 실행 순서
    리뷰이관
    리뷰관리
    programmerlife
    Python
    codingcommunity
    스크립트 실행
    믈레코비타멸균우유
    cv2
    ipcamera
    카페24리뷰이관
    쇼핑몰리뷰
    스마트스토어리뷰
    devlife
    긴유통기한우유
    C#
  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
코샵
파이썬 시리얼 통신 완벽 가이드: pyserial과 struct 활용법
상단으로

티스토리툴바