Step 1. GUI + LED 제어

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