파이썬 시리얼 통신 완벽 가이드: 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)
  • 인기 글

  • 태그

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

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

티스토리툴바