기타

아두이노 <-> PC 간 시리얼 통신

제갈티 2025. 1. 7. 12:58

아두이노와 디지탈 스위치
Arduino IDE , Thonny, GUI app

const int switchPin = 2;  // 스위치가 연결된 디지털 핀
int lastSwitchState = HIGH;
int currentSwitchState;

void setup() {
  Serial.begin(9600);  // 시리얼 통신 시작
  pinMode(switchPin, INPUT_PULLUP);  // 내부 풀업 저항 사용
}

void loop() {
  currentSwitchState = digitalRead(switchPin);
  
  // 스위치 상태가 변경되었을 때만 신호 전송
  if (currentSwitchState != lastSwitchState) {
    if (currentSwitchState == LOW) {  // 스위치가 눌렸을 때
      Serial.println("1");  // 트리거 신호 전송
    }
    delay(50);  // 디바운싱
  }
  
  lastSwitchState = currentSwitchState;
}

- arduino code

import sys
import serial
import serial.tools.list_ports
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QMessageBox
from PyQt5.QtCore import QTimer
from PyQt5.QtGui import QPalette, QColor

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()
        self.initSerial()
        
    def initUI(self):
        self.setGeometry(100, 100, 400, 300)
        self.setWindowTitle('Arduino Signal Color Change Demo')
        
        # 중앙 위젯 설정
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        
        # 초기 색상 설정
        self.current_color = 0  # 0: 흰색, 1: 빨간색
        self.updateColor()
        
    def initSerial(self):
        try:
            # 사용 가능한 포트 찾기
            ports = list(serial.tools.list_ports.comports())
            if not ports:
                raise Exception("사용 가능한 시리얼 포트가 없습니다.")
            
            # 연결된 포트 출력
            print("사용 가능한 포트:")
            for port in ports:
                print(f"- {port.device}")
            
            # 첫 번째 사용 가능한 포트 사용
            port = ports[0].device
            print(f"\n{port}에 연결을 시도합니다...")
            
            self.serial = serial.Serial(port, 9600, timeout=1)
            print("시리얼 포트 연결 성공!")
            
            # 타이머 설정
            self.timer = QTimer()
            self.timer.timeout.connect(self.readSerial)
            self.timer.start(100)  # 100ms 마다 체크
            
        except Exception as e:
            QMessageBox.critical(self, "오류", f"시리얼 포트 연결 실패: {str(e)}")
            self.close()
            
    def readSerial(self):
        try:
            if self.serial.in_waiting:
                data = self.serial.readline().decode().strip()
                print(f"수신된 데이터: {data}")  # 디버깅용
                if data == "1":
                    self.current_color = 1 - self.current_color  # 색상 토글
                    self.updateColor()
        except Exception as e:
            print(f"데이터 읽기 오류: {str(e)}")
                
    def updateColor(self):
        palette = self.centralWidget().palette()
        if self.current_color == 0:
            palette.setColor(QPalette.Window, QColor('white'))
            print("색상 변경: 흰색")
        else:
            palette.setColor(QPalette.Window, QColor('red'))
            print("색상 변경: 빨간색")
        self.centralWidget().setAutoFillBackground(True)
        self.centralWidget().setPalette(palette)
        
    def closeEvent(self, event):
        try:
            if hasattr(self, 'serial'):
                self.serial.close()
                print("시리얼 포트 연결 종료")
        except Exception as e:
            print(f"포트 종료 오류: {str(e)}")
        event.accept()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

- 파이썬 코드

먼저 아두이노 코드를 로딩한 후
나중에 파이썬 코드를 돌려야 시리얼포트 충돌이 안생김!