기타

ArduinoPLC <-> PC 간 UDP 통신 OK

제갈티 2025. 1. 9. 13:03

아두이노가 PLC 처럼 작동한다

#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>

// MAC 주소 설정
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 177);
unsigned int localPort = 8888;

// PLC 입력 설정
const int inputPin = 2;  // X0 입력 접점
word X0_status = 0;     // 입력 상태
word prev_X0_status = 0;  // 이전 입력 상태

EthernetUDP Udp;

void setup() {
  Serial.begin(9600);
  Serial.println("Starting PLC Simulation...");
  
  pinMode(inputPin, INPUT_PULLUP);  // PLC 입력 설정
  
  // 이더넷 초기화
  Ethernet.begin(mac, ip);
  Udp.begin(localPort);
  
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield not found!");
    while (true) delay(1);
  }
  
  Serial.println("PLC Ready!");
}

void loop() {
  // 입력 상태 읽기
  X0_status = !digitalRead(inputPin);  // Pull-up 저항으로 인해 반전
  
  // 상태 변경 감지
  if (X0_status != prev_X0_status) {
    // 상태가 변경되면 UDP로 전송
    Udp.beginPacket(IPAddress(192, 168, 0, 51), 8888);
    Udp.write((byte*)&X0_status, sizeof(word));
    Udp.endPacket();
    
    Serial.print("Input Status Changed: ");
    Serial.println(X0_status);
    
    prev_X0_status = X0_status;
  }
  
  delay(10);  // 디바운싱
}

- 아두이노 코드


import sys
import socket
import struct
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget
from PyQt5.QtCore import QTimer
from PyQt5.QtGui import QPalette, QColor

class PLCMonitor(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()
        self.initUDP()
        
    def initUI(self):
        self.setGeometry(100, 100, 400, 300)
        self.setWindowTitle('PLC Input Monitor')
        
        # 중앙 위젯 설정
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        
        # 초기 색상 설정
        self.current_color = 0  # 0: 흰색, 1: 빨간색
        self.updateColor()
        
    def initUDP(self):
        try:
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            self.sock.bind(('192.168.0.51', 8888))
            self.sock.setblocking(False)
            
            print("UDP 소켓 생성 성공!")
            
            # 데이터 수신 타이머
            self.timer = QTimer()
            self.timer.timeout.connect(self.readPLCInput)
            self.timer.start(50)  # 50ms마다 확인
            
        except Exception as e:
            print(f"소켓 생성 오류: {str(e)}")
            
    def readPLCInput(self):
        try:
            data, addr = self.sock.recvfrom(1024)
            if len(data) >= 2:
                x0_status = struct.unpack('H', data[:2])[0]
                print(f"받은 입력 상태: {x0_status}")
                
                # 입력 상태에 따라 색상 변경
                self.current_color = x0_status
                self.updateColor()
                
        except BlockingIOError:
            pass
        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):
        if hasattr(self, 'sock'):
            self.sock.close()
        event.accept()

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

- 파이썬 코드