반응형

카테고리를 c# 으로 해야 할지 Arduino 로 해야할지 조금 고민이 되는 포스트  입니다.

음....

arduino 로 하는게 좋겠네요. 따지고 보면 C# 으로 만든 어플이 중요한게 아니라 아두에노에서 시리얼 통신으로 메시지를 받는게 중요한거니까요.

일단 한번 해보겠습니다. 자 시작하죠.

 

우선 이번 포스트에서 다룰 주제는 아래와 같습니다.

  • C# 에서 시리얼 통신 사용하기
  • 시리얼 통신으로 문자열 송신하기
  • 아두이노에서 문자열 수신하기
  • LCD 에 수신된 문자열 표시하기

간단하죠?

내용도 간단하니까 걱정 붙들어 매시고 따라오시면 됩니다.

 

 

C#에서 시리얼 통신 사용하기

먼저 비주얼 스튜디오를 열고 c# .net 플랫폼을 선택하신 후 window form 프로젝트를 하나 만들어 줍니다.

window forms 앱 을 선택합니다.
적당히 이름을 만들어 주세요. 닷넷 버전은 그냥 건드리지 않았습니다.

 

이렇게 하시고 만들기를 누르시면 윈도우 창이 나올텐데요.

간단하게 label, combobox, button 을 하나씩 만들어주고 사이즈를 적당히 조절합니다.

간단한 메뉴 구성 완료

 

이제 폼이 실행되면 combobox 에 연결 가능한 시리얼 포트를 띄워 주겠습니다. 그리고 버튼을 누르면 해당 포트로 메시지를 전달하도록 할 예정입니다.

만들어진 UI 상단에 Form1 이라고 써있는 타이틀바를 더블클릭해 줍니다.

그럼 아래와 같이 Load 이벤트와 함께 함수가 하나 만들어 집니다.

이제 이번 포스트에 필요한 지시문과 콤보박스에 시리얼을 연결하는 방법을 소개해 드리겠습니다.

먼저 맨윗줄 지시문이 있는 그룹에 아래와 같이 추가해 줍니다.

using System.IO.Ports;

 

그런 다음 이번 예제에서 사용할 시리얼 포트를 만들어 주고요 

public partial class Form1 : Form
{
  private SerialPort mySerial; //<-- 요 부분이죠

  public Form1()
  {
  	InitializeComponent();
  }

 

아까 만들어 진 Form1_Load 함수에 아래와 같이 시리얼포트를 생성해주고 콤보박스에는 데이터를 담습니다.

private void Form1_Load(object sender, EventArgs e)
{
  mySerial = new SerialPort();
  comboBox1.DataSource = SerialPort.GetPortNames();

}

 

이제는 콤보박스의 선택정보가 변경될 때 시리얼 포트가 열려있지 않다면 포트이름과 설정을 지정해 주고 열도록 하겠습니다. 

UI 메뉴에서 콤보 박스를 더블클릭하면 함수가 자동으로 생성되는데요. 만들어진 함수에 아래와 같이 코드를 작성하시면 됩니다.

private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
  if (mySerial.IsOpen) // 특정 포트가 이미 열려 있다면 설정이 되지 않기 때문에 우선 닫는다.
  {
  	mySerial.Close();
  }
  if (!mySerial.IsOpen)  //시리얼포트가 닫혀있을 때만
  {
    mySerial.PortName = comboBox1.Text;  // 선택된 combobox 의 이름으로 포트명을 지정하자
    mySerial.BaudRate = 9600;  //아두이노에서 사용할 전송률를 지정하자
    mySerial.DataBits = 8;
    mySerial.StopBits = StopBits.One;
    mySerial.Parity = Parity.None;

    mySerial.Open();  //시리얼포트 열기
  }
  else
  {
    MessageBox.Show("해당포트가 이미 열려 있습니다.");
  }
}

 

 

 

 

시리얼 통신으로 문자열 송신하기

뭐 거의 다 되었습니다. 이제 버튼을 누르면 아두이노로 메시지를 전달하기만 하면 됩니다.

문자열을 전송하기 위한 byte 배열로 바꾸어주는 함수를 하나 만들어 보겠습니다.

private byte[] StringToByte(string _str)
{
  byte[] tmpBytes = Encoding.UTF8.GetBytes(_str);
  return tmpBytes;
}

요렇게 만들어 주었다면 이제 UI 생성하는 페이지에서 만들어 두었던 버튼을 두번 클릭하여 버튼을 눌렀을때 실행할 함수를 하나 만들어 줍시다.

그런다음 아래와 같이 메시지를 보내보겠습니다.

private void button1_Click(object sender, EventArgs e)
{
  byte[] datas = StringToByte("Hello Arduino?\n"); // 줄바꿈 기호인 \n 은 끝에 꼭 들어가야 합니다.
  mySerial.Write(datas, 0, datas.Length);
}

 

자 C# 어플리케이션은 완성이 되었습니다. 

 

벌써요?

네 벌써 완료 되었습니다. 정상적으로 동작한다면 아두이노 LCD 에 Hello Arduino? 가 뜰 것입니다.

제 포스트를 보시면서 천천히 하셔도 아마 15분이면 충분할만한 분량이지요. 

 

전체 코드도 올립니다.

더보기

 

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 csharp2arduino_serial
{
    public partial class Form1 : Form
    {
        private SerialPort mySerial;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            mySerial = new SerialPort();
            comboBox1.DataSource = SerialPort.GetPortNames();

        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
        	if (mySerial.IsOpen)
            {
                mySerial.Close();
            }
            if (!mySerial.IsOpen)  //시리얼포트가 닫혀있을 때만
            {
                mySerial.PortName = comboBox1.Text;  // 선택된 combobox 의 이름으로 포트명을 지정하자
                mySerial.BaudRate = 9600;  //아두이노에서 사용할 전송률를 지정하자
                mySerial.DataBits = 8;
                mySerial.StopBits = StopBits.One;
                mySerial.Parity = Parity.None;

                mySerial.Open();  //시리얼포트 열기
            }
            else
            {
                MessageBox.Show("해당포트가 이미 열려 있습니다.");
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // 텍스트 박스 추가한 버전
            string myMsg = textBox1.Text;
            if (myMsg != "")
            {
                myMsg += "\n";
            }
            else
            {
                myMsg = "Hello Arduino?\n";
            }
            byte[] datas = StringToByte(myMsg);
            mySerial.Write(datas, 0, datas.Length);
        }

        private byte[] StringToByte(string _str)
        {
            byte[] tmpBytes = Encoding.UTF8.GetBytes(_str);
            return tmpBytes;
        }
    }
}

 

 

 

아두이노에서 시리얼 메시지 받기

아두이노에서 시리얼 메시지를 받는것은 사실 매우 쉽습니다. 아두이노 기본 예제 중에 Serial 을 사용하는 것을 많이 보셨죠? 아두이노는 Serial 을 사용하기 위하여 별도로 설정할것이 거의 없습니다.

아두이노를 열어 주시고 아래와 같이 코드를 작성합니다.

String myStr = "";

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop() {

  if(Serial.available()){//시리얼에 데이터가 있다면

    char data = (char)Serial.read();//한 문자씩 읽어 문자형 변수에 담고
    
    if((int)data != 10){ //개행문자 '\n' -> newline 이 아니라면 스트링에 계속 저장
      myStr += data;
      
    }else{
      // \n 을 만나면 여기로 와서 문자열을 출력하면 된다.

      // LCD 에 문자를 여기서 출력하면 됨

      //그리고 문자열은 다시 초기화를 해주겠습니다.
      myStr = "";
    }
  }
}

 

완전 간단하죠? 시리얼 신호가 들어오면 \n 이라는 줄바꿈 문자열이 오기 전까지 계속해서 한글자씩 문자열 변수에 추가를 해주었다가 \n 을 만나면 필요한 결과를 수행하고 원래 문자열 변수를 초기화 하는 것이죠.

 

 

물론 아직 LCD 를 붙이지 않았으므로 시리얼을 받아도 뭔가 표시는 안되겠지요?

그래서 이제 LCD 를 붙여 보겠습니다.

 

 

 

 

아두이노 OLED LCD 에 시리얼 통신 결과 출력하기

 

지난 LCD 예제를 참고하시면 되며 이번에는 바로 시리얼을 출력해 보겠습니다.

2020/05/26 - [DIY/Arduino] - 0.96 inch OLED 디스플레이 구동하기

 

0.96 inch OLED 디스플레이 구동하기

가끔 아두이노로 무엇인가를 만들어 보려고 하다보면 디스플레이가 있으면 하는 생각이 들때가 있습니다. 아두이노는 작은 컴퓨터이기는 하지만 모름지기 컴퓨터라 한다면 입력장치 - 중앙처��

diy-dev-design.tistory.com

 

상단에 필요한 요소들을 추가해주고 기본적인 셋팅을 해준뒤 제 포스트의 주제인 DIY DEV DESIGN 을 출력하고 시작하겠습니다. ㅋ

(작성자의) 편의상 그냥 전체 코드블럭을 올립니다. 라이브러리나 LCD 구동 관련된사항은 위 포스트에서 확인하시면 됩니다.

#include <Wire.h> 
#include <Adafruit_SSD1306.h>
#include <splash.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <gfxfont.h>
#include <Fonts/FreeMono9pt7b.h>


#define OLED_ADDR   0x3C

// reset pin not used on 4-pin OLED module
Adafruit_SSD1306 display(-1);  // -1 = no reset pin

//#if (SSD1306_LCDHEIGHT != 64)
//#error("Height incorrect, please fix Adafruit_SSD1306.h!");
//#endif

String myStr = "";
int linegap = 2;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
  display.setFont();
  display.clearDisplay();
  display.display();
  display.setTextSize(1);

  draw_text(2, 25, "DIY DEV DESIGN", false); // 폰트 표시를 쉽게 하기 위해 제가 만든 함수 입니다.
  draw_text(3, 4, "C# -> Arduino Serial", false);

  display.display();
  delay(3000);
  
}

void loop() {

  if(Serial.available()){//시리얼에 데이터가 있다면

    char data = (char)Serial.read();//한 문자씩 읽어 문자형 변수에 담고
    
    if((int)data != 10){ //개행문자 '\n' -> newline 이 아니라면 스트링에 계속 저장
      myStr += data;
      
    }else{
      // \n 을 만나면 여기로 와서 문자열을 출력하면 된다.

      // LCD 에 문자를 여기서 출력하면 됨
      display.clearDisplay();
      draw_text(2, 10, myStr, false);
      display.display();
      //그리고 문자열은 다시 초기화를 해주겠습니다.
      myStr = "";
    }
  }
}

void draw_text (int line, int xPos, String txt, bool isSelected)
{
   int cHeight = (line-1) * 8 + ((line-1) * linegap);
   if(isSelected)
   {
      display.fillRect(xPos - 2, cHeight, 127, 8, WHITE);
      display.setTextColor(BLACK);
   }else{
      display.setTextColor(WHITE);
   }
   display.setCursor(xPos, cHeight);
   display.print(txt);
}

 

음 뭐 간단하다면 간단한 내용이죠?

 

자 아두이노를 컴파일하고 올려야 하는데요. 아까 c#에서 만들어놓은 APP 을 실행해 놓으면 소스가 업로드 되지 않습니다. App 을 열어두었다면 끄고 업로드를 해야 합니다.

 

 

 

 

결과 확인하기

이제 결과를 확인해 보겠습니다.

먼저 아두이노를 업로드 해보면 아래와 같은 화면이 나오게 됩니다.

ㅎㅎ 저렇게 작은 글씨가 보이는게 귀엽네요. 

 

만들어 두었던 시리얼 통신용 어플을 실행해 볼까요?

간단한 화면

이제 버튼을 눌러보면 아래와 같이 아두이노와 연결된 OLED LCD 에 전송한 글자가 표시됩니다.

성공!

 

전송한 메시지가 잘 표시가 되네요.

우하하하핫

이때가 기분이 제일 좋은 순간이지요. 

 

 

끝으로..

C# 으로 개발하기 귀찮은 분들을 위해 테스트용 앱을 만들어 보았습니다.

요렇게 하단에 메시지 박스를 이용해서 원하는 메시지를 보낼 수 있는 툴입니다.

아두이노 LCD 에는 이렇게 받아지죠.

시리얼 통신으로 받은 메시지들

 

시리얼 메시지 테스터는 아래 파일을 다운로드 받으셔서 압축을 해제하신 후 실행하시면 됩니다.

csharp2arduino_serial.7z
0.00MB

 

바이러스 따위는 없으니 안심하셔도 됩니다. 

 

이렇게 해서 간단하게 아두이노로 PC 에서 메시지를 보내는 방법을 설명해 드렸습니다.

만약 다른 정보일지라도 문자열로 바꾸어서 보내준뒤 아두이노 코드에서 해석해서 받으면 어떤 정보든 전달하는 것이 가능하겠죠? 어렵지 않으리라 생각됩니다.

 

C# 레퍼런스는 정말 어마어마 하게 많기 때문에 우리가 생각하는 거의 모든 것들을 만들어 내는 것이 가능할 것입니다. 

아두이노같은 작은 컴퓨터에서 우리가 PC 로 하는 많은 것들을 알려주고 동작하게 하는 것. 아두이노 만큼 손쉽게 실제 동작하는 기구를 만들 수 있는 도구가 또 어디 있겠습니까? 

시작이 어렵지 잘만들어진 레퍼런스 하나면 바로 첫 삽을 뜰 수 있답니다.

일단 통신만 뚫었다면 그 다음은 일사 천리아니겠습니까? 

 

예를 들면 제가 아두이노를 이용해서 TV 리모컨 신호를 해킹한 적이 있는데요. 적외선 기능이 없는 노트북에서 TV 를 켜고 채널을 바꾸는것도 간단한 프로젝트로 해볼만할 것 같습니다. 

 

 

그럼 이만~

뎃글, 공감 은 블로그 작성자에게 큰 힘이 된답니다. 
도움이 되었다 생각되시면  클릭!!  부탁드려요~

 

 

2020/06/17 - [DIY/Arduino] - [DIY] 아두이노로 통합(만능) 리모콘 만들기 3/3

2020/05/26 - [DIY/Arduino] - 0.96 inch OLED 디스플레이 구동하기

2020/03/23 - [DIY/Arduino] - Arduino(아두이노) 무작정 시작하기

2019/06/27 - [DIY/Arduino] - 아두이노를 이용한 간단한 화분 자동 물주기 시스템

 

반응형

+ Recent posts