2023.03.29
아두이노와 C# 의 시리얼 통신
1. 아두이노 통신 체크
int Count = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println(Count);
if(Count++ > 9999) Count = 0;
delay(500);
}
정상 연결 및 동작 시
0.5초마다 1씩 증가하며
시리얼 모니터에 출력된다
아두이노에 이상 없음 체크
2. C# 윈도우 폼 디자인
C# 내 간단한 윈도우 폼 디자인 도구 : textBox Dock : Fill
3. 코드 구성
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports; // 포트 설정을 위한 호출
namespace Serial_to_LCD
{
public partial class Form1 : Form
{
SerialPort ComPort = new SerialPort(); // 전역변수 ComPort 설정
public Form1()
{
InitializeComponent();
}
}
}
위와 같이 폼 로드 전에 구성을 해주고
폼 로드와 클로징 시 필요한 코드를 구성한다
private void Form1_Load(object sender, EventArgs e)
{
ComPort.PortName = "COM3"; // 아두이노가 연결된 포트 번호
ComPort.BaudRate = 9600; // 일반적으로 9600
ComPort.DataBits = 8; // 통신의 비트 설정 : 일반적으로 8비트
ComPort.Parity = Parity.None; // 통신의 정확도를 위한 패리티 검사(1의 개수의 짝/홀 여부)
ComPort.StopBits = StopBits.One; // 통신 말미 1로 지정
ComPort.Handshake = Handshake.None;
ComPort.Open();
ComPort.DiscardInBuffer(); // 수신 버퍼 데이터 삭제
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
ComPort.Close(); // 시리얼 포트 닫음
ComPort.Dispose(); // 시리얼 포트 완전 해제
ComPort = null;
}
폼 로드시 구성되는 코드 중 databits, parity, stopbits, handshake 는 시리얼 포트 세팅 옵션이다
일반적으로 위와 같은 구성이 기본값으로 구성되며, 정확한 통신 세팅을 위해선 특정 값을 지정해주지만 간단한 구성에선 제외해도 구동이 가능하다
하지만 그럼에도 여러 옵션이 있다는 것은 알아두면 나쁘지 않으니 아래에 정리해두자
databits : 8, 7, 6 parity : none, even, mark, odd, space handshake : none, Xon/Xoff, request to send, request to send Xon/Xoff
🌞 이벤트 핸들러 생성
public Form1()
{
InitializeComponent();
ComPort.DataReceived += new SerialDataReceivedEventHandler(DataReceived);
}
private void DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
string rxd = ComPort.ReadTo("\n");
}
Comport.ReadTo() 로 \n 까지 읽고 데이터를 Delegate 로 송신한다
🌞 delegate 구성
처음 보면 이해하기 어렵다 😰 delegate 는 대리자 역할이다
A 에서 B 로 데이터가 직접 전달이 아닌
delegate 라는 대리자를 통해
A -> delegate -> B
이런 식으로 데이터가 전달된다
① : SetTextDelegate 라는 함수에게 delegate 선언
② : BeginInvoke 로 대리자 비동기식 실행
③ SetTextDelegate 라는 delegate 의 인수에
textBox1.AppendText 를 실행하는 함수 지정
위 단계를 거쳐 진행이 되고, 최종적으로 실행이 되는 폼의 모양을 확인하자 * 아두이노의 시리얼 모니터가 꺼져 있어야 함 켜져 있으면 포트가 겹쳐 실행 안됨
[ 실행된 폼 ]
이렇게 실행된 폼을 활용해 컴퓨터에 구성된 포트 중 선택할 수 있는 콤보박스, 비트 전송 속도 등 옵션을 선택할 수 있게 만들 수 있다 👍
🌞 앞서 말했던 지정 옵션 빼보기
private void Form1_Load(object sender, EventArgs e)
{
ComPort.PortName = "COM3"; // 아두이노가 연결된 포트 번호
ComPort.BaudRate = 9600; // 일반적으로 9600
ComPort.DataBits = 8; // 통신의 비트 설정 : 일반적으로 8비트
ComPort.Parity = Parity.None; // 통신의 정확도를 위한 패리티 검사(1의 개수의 짝/홀 여부)
ComPort.StopBits = StopBits.One; // 통신 말미 1로 지정
ComPort.Handshake = Handshake.None;
ComPort.Open();
ComPort.DiscardInBuffer(); // 수신 버퍼 데이터 삭제
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
ComPort.Close(); // 시리얼 포트 닫음
ComPort.Dispose(); // 시리얼 포트 완전 해제
ComPort = null;
}
마지막으로 요 부분에 들어있는 시리얼 포트 세팅 옵션들 { databits, parity, stopbits, handshake } 을 빼서 실행해보자
잘 실행된다 :D
(전체 코드 구성)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports; // 포트 설정을 위한 호출
namespace Serial_to_LCD
{
public partial class Form1 : Form
{
SerialPort ComPort = new SerialPort(); // 전역변수 ComPort 설정
private delegate void SetTextDelegate(string getString);
public Form1()
{
InitializeComponent();
ComPort.DataReceived += new SerialDataReceivedEventHandler(DataReceived);
}
private void DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
string rxd = ComPort.ReadTo("\n");
this.BeginInvoke(new SetTextDelegate(SerialReceived), new object[] { rxd });
}
private void SerialReceived(string inString)
{
textBox1.AppendText(inString + "\r\n");
}
private void Form1_Load(object sender, EventArgs e)
{
ComPort.PortName = "COM3"; // 아두이노가 연결된 포트 번호
ComPort.BaudRate = 9600; // 일반적으로 9600
//ComPort.DataBits = 8; // 통신의 비트 설정 : 일반적으로 8비트
//ComPort.Parity = Parity.None; // 통신의 정확도를 위한 패리티 검사(1의 개수의 짝/홀 여부)
//ComPort.StopBits = StopBits.One; // 통신 말미 1로 지정
//ComPort.Handshake = Handshake.None;
ComPort.Open();
ComPort.DiscardInBuffer(); // 수신 버퍼 데이터 삭제
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
ComPort.Close(); // 시리얼 포트 닫음
ComPort.Dispose(); // 시리얼 포트 완전 해제
ComPort = null;
}
}
}
회고) delegate 의 존재에 대해 이해는 쉬웠지만 코드 구성에 대한 구체적인 이해가 조금 부족했다
포트로 전송되는 데이터를 받는 방법에 있어 이벤트 핸들러 외에도 여러 방법이 있었는데 이 부분에 대해 알아보는데 시간이 더 필요할 것 같다
databits, parity, stopbits, handshake 등 최근엔 옵션 지정 자체가 잘 쓰이지 않는다는 것 같은데 이 부분은 인터넷에 있는 정보 외에도 실무에서 직접 겪어보면서 알아보면 좋을것 같다(옵션은 알아두자)