0. 순서

더보기

👉 Step 1. GUI + LED 제어 맛보기

  • 버튼 1개
  • 포트·보드레이트 코드에 고정
  • GUI → 시리얼 → 아두이노 → 로그 흐름 경험 중심

 

Step 2. 포트 선택 추가

  • 포트 선택 콤보박스 추가
  • “어떤 장치와 통신하는가” 개념 학습
  • Step 2는 기능 확장이 아니라, 통신 대상 선택이라는 개념을 추가하는 단계입니다.

 

Step 3. 문자열 송신/수신 추가

  • 자유 문자열 전송 입력창 추가
  • TX / RX 개념 명확화
  • LED 제어 + Echo 응답 확인

 

Step 4. QTimer 수신 처리 추가

  • 주기적 수신 처리 구조 도입
  • GUI 멈춤 현상 체험
  • “왜 비동기가 필요한가” 문제 제기

 

Step 5. QThread 비동기 수신 추가

  • RX 전용 스레드 분리
  • Signal / Slot 구조 학습
  • 안정적인 GUI + 실시간 수신 구현

 

1. 목표

더보기

목표

  • 이 단계의 목표는 PC 프로그램(PySide6)에서 시리얼 통신을 경험해보는 것입니다.
    이론보다 동작 경험을 우선합니다.
  • PC 프로그램(PySide6)에서 버튼을 클릭할 수 있다.
  • 버튼 클릭 시 아두이노로 문자 하나가 전송(TX)되는 것을 이해한다.
  • 아두이노가 LED를 켜거나 끄는 것을 확인한다.
  • 아두이노가 보낸 응답 메시지(RX)를 화면에서 확인한다.
  • GUI → 시리얼 → 아두이노 → 응답 흐름을 눈으로 확인한다.

 

다루는 것

  • LED ON / OFF 제어
  • 시리얼 문자열 "1", "0" 전송
  • 시리얼 응답 한 줄 수신
  • 로그 창에 TX / RX 출력

 

다루지 않는 것

  • 시리얼 포트 선택
  • 보드레이트 변경
  • QThread / QTimer
  • 예외 처리
  • 여러 줄 수신

 

2. 아두이노 스케치 구현 

: 교재 P.110 ~ 143

더보기
// Arduino: LED control + Echo
// - '1' 수신: LED ON
// - '0' 수신: LED OFF
// - 그 외 문자열: 그대로 echo 출력

const int LED_PIN = 13;

void setup() {
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);

  Serial.begin(9600);
  while (!Serial) { ; }
  Serial.println("READY");
}

void loop() {
  if (Serial.available() > 0) {
    String msg = Serial.readStringUntil('\n');
    msg.trim();

    if (msg == "1") {
      digitalWrite(LED_PIN, HIGH);
      Serial.println("LED:ON");
    } else if (msg == "0") {
      digitalWrite(LED_PIN, LOW);
      Serial.println("LED:OFF");
    } else {
      Serial.print("ECHO:");
      Serial.println(msg);
    }
  }
}

 

3. PySide6 앱 1단계 구현

└─ 3.1 전체 소스 코드

더보기
# Step 1: 버튼 하나로 LED ON/OFF
# 목적: GUI → 시리얼 → 아두이노 → 로그

import sys
import serial

from PySide6.QtWidgets import (
    QApplication, QMainWindow, QPushButton,
    QTextEdit, QVBoxLayout, QWidget
)


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Serial LED Test")
        self.resize(320, 260)

        # ⚠ 1단계: 포트/보드레이트 고정 
        # Ardurino IDE 에서 확인 후 반영할 것
        self.ser = serial.Serial("COM10", 9600, timeout=1)

        self.led_on = False

        self.btn_led = QPushButton("LED OFF")
        self.log = QTextEdit()
        self.log.setReadOnly(True)

        layout = QVBoxLayout()
        layout.addWidget(self.btn_led)
        layout.addWidget(self.log)

        central = QWidget()
        central.setLayout(layout)
        self.setCentralWidget(central)

        self.btn_led.clicked.connect(self.toggle_led)

    def toggle_led(self):
        self.led_on = not self.led_on
        msg = "1" if self.led_on else "0"
        self.ser.write((msg + "\n").encode())
        self.log.append(f"TX: {msg}")

        line = self.ser.readline().decode().strip()
        if line:
            self.log.append(f"RX: {line}")

        self.btn_led.setText("LED ON" if self.led_on else "LED OFF")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec())

└─ 3.2 전체 동작 흐름

더보기
[ LED 버튼 클릭 ]
        ↓
[ "1" 또는 "0" 전송 (TX) ]
        ↓
[ Arduino LED ON / OFF ]
        ↓
[ 상태 메시지 수신 (RX) ]
        ↓
[ 로그 창에 표시 ]

└─ 3.3 시리얼 연결 (고정)

더보기
self.ser = serial.Serial("COM10", 9600, timeout=1)
  • 이번 단계에서는 포트와 보드레이트를 고정
  • 연결이 된다는 경험이 목적
  • Arduino IDE 에서 포트 확인 후 적용

└─ 3.4 버튼 클릭 → 문자열 전송(TX)

더보기
msg = "1" if self.led_on else "0"
self.ser.write((msg + "\n").encode())
  • 버튼 상태에 따라 "1" 또는 "0" 전송
  • 이 한 줄이 TX의 전부

└─ 3.5 아두이노 응답 수신(RX)

더보기
line = self.ser.readline().decode().strip()
  • 아두이노가 Serial.println()으로 보낸 한 줄 수신
  • 받은 내용을 그대로 화면에 출력


4. 테스트

더보기

정상 동작 확인

  • 프로그램 실행 시 에러가 발생하지 않는다.
  • 버튼을 누르면 아두이노 LED가 켜졌다/꺼진다.
  • 로그 창에 아래와 같은 형태가 보인다.
TX: 1
RX: LED:ON

TX: 0
RX: LED:OFF