티스토리 뷰

반응형

다른 강의자료는 www.codingnow.co.kr/ 여기를 참고해주세요.!!

 

코딩나우

프로그래밍 교육및 개발의뢰 받습니다.

www.codingnow.co.kr

 

https://youtu.be/mSAG_F8VNK4

 


C언어와 파이썬을 같이 사용하여 간단한 프로젝트를 진행 합니다.

아두이노의 LED를 시리얼 통신을 사용하여 파이썬 GUI로 제어합니다.

자세한 설명은 첨부 동영상을 참고해주세요.

 

LED bit제어 전체 소스.zip
0.01MB

 

1. C언어 - 아두이노

1) 회로 구성

4개의 LED를 13~10 번 포트에 연결합니다.

2) 소스파일

-. Blink.ino

아두이노 스케치 파일입니다. main.cpp에서 처리하도록 변경하였습니다.

#include "src/global.h"

void setup() 
{
  setupMain();
}

void loop() 
{
  loopMain();
}

-. src/main.cpp

아두이노 초기화와 시리얼 통신으로 받은 데이타 처리를 합니다.

#include "global.h"

//https://www.arduino.cc/reference/ko/language/variables/data-types/stringobject/

#define MAX_LED_CNT 4
unsigned char LEDS[MAX_LED_CNT] = {13,12,11,10};

void responseLedState(unsigned char state)
{
    unsigned char i,led;
    String hex;
    //digitalRead가 안되는 경우가 있어서 state를 가지고 처리함.
    led = state;
    // led = 0x00;
    // for(i=0; i<MAX_LED_CNT; i++)
    // {
    //     if(digitalRead(LEDS[i]))
    //     {
    //         led |= 0x01 << i;
    //     }
    // }
    Serial.print("Arduino LED : ");
    hex = String((led>>4)&0x0F, HEX);
    hex += String(led&0x0F, HEX);
    Serial.println(hex);
}

void setupMain() 
{
    unsigned char i;
    Serial.begin(9600);
    for(i=0; i<MAX_LED_CNT; i++){
        pinMode(LEDS[i], OUTPUT);
    }
}

void loopMain() 
{
    unsigned char state = 0, i;
    state = serialGet();

    if (state != 0xFF)
    {
        for(i=0; i<MAX_LED_CNT; i++)
        {
            if (state & (0x01 << i))
            {
                digitalWrite(LEDS[i], HIGH);
            }else{
                digitalWrite(LEDS[i], LOW);
            }
        }
        responseLedState(state);
    }
}

-. src/processSerial.cpp

시리얼 데이타를 받아 문자열을 정수로 변환하여 리턴합니다.

#include "processSerial.h"
/* String Data Types
https://www.arduino.cc/reference/ko/language/variables/data-types/stringobject/
*/
String str = "";

unsigned char AsciiToHex(unsigned char val)
{
  if(val >= '0' && val <= '9')
  {
    return val-'0';
  }
  if(val >= 'A' && val <= 'F')
  {
    return (val-'A')+10;
  }
  return 0;
}
unsigned char strToHex(String val)
{
  unsigned char ret = 0;
  ret = AsciiToHex(val[0]) << 4;
  ret += AsciiToHex(val[1]);
  return ret;
}

unsigned char serialGet(void) 
{
  unsigned char cmd = 0xFF;
  while (Serial.available()) 
  {
    str += (char)Serial.read();
    if (str.indexOf('\n') > -1 )
    {
      str.replace("\n","");//enter 삭제
      str.replace(" ","");//space 삭제
      str.toUpperCase();//대문자변환
      if(str.indexOf("LED")>-1)
      {
        str.replace("LED","");//LED 삭제
        if(str.length()==2)
        {
          cmd = strToHex(str);
          // Serial.print(cmd);
        }
      }
      str = "";
    }
  }
  return cmd;
}

2. 파이썬(GUI)

gui를 생성하고 아두이노와 시리얼 통신으로 명령을 주고 받습니다.

 

1) 소스코드

-.main.py

시리얼 통신을 초기화 하고 데이타를 주고 받습니다.

GUI를 통해 명령을 제어합니다.

import serial
import tkinter as tk
import time
import threading

# pip install serial
# pip install pyserial
# pip uninstall serial

seri = serial.Serial(port='COM9',
                    baudrate=9600,
                    parity=serial.PARITY_NONE,
                    stopbits=serial.STOPBITS_ONE,
                    bytesize=serial.EIGHTBITS) 

ledState = 0x00
def sendToAruino(led):
    global ledState
    if ledState & led:
        ledState &= (~led)
    else:
        ledState |= led

    comm = "{:02x}".format(ledState)
    # comm = "{:02x}".format(led)#01
    comm = 'LED'+comm
    print('Send : ', comm)
    comm += '\n'
    seri.write(bytes(comm, encoding='ascii'))

####################################################
## GUI 생성하기
####################################################
class LedControl():
    commands = ['0', '1', '2','3','auto']

    def __init__(self):
        self.win = tk.Tk()
        self.win.title('[파이선] 아두이노 LED 제어')
        self.isAuto = False
        self.btn = [None for i in range(len(self.commands))]
        for i, comm in enumerate(self.commands):##버튼을 만든다.
            self.btn[i] = tk.Button(self.win,text=comm,
                width=10, height=5, 
                bg='gray', fg='black',
                command=lambda cmd=comm: self.button_click(cmd)
                )
            self.btn[i].grid(column=i, row=0)

    def button_click(self, value):
        if value == 'auto':
            self.isAuto = True
        else:
            self.isAuto = False
            led = 0x01<< int(value)
            print(led)
            sendToAruino(led)

#thread 1 함수
def TH_readSerial():
    global isT1Run
    while isT1Run:
        if seri.readable():
            res = seri.readline()
            res = res.decode()[:len(res)-1]
            print(' Response :', res,'\n')
            if res.find('Arduino LED') != -1:
                res = res.replace("Arduino LED : ", "")
                led = int(res, 16)
                for i in range(len(tool.btn)):
                    if led & (0x01 << i):
                        tool.btn[i].configure(bg="yellow")
                    else:
                        tool.btn[i].configure(bg="gray")
    print('stop1 thread')

# #thread 2  함수
def TH_sendCmdAuto():
    global isT2Run
    index = 0
    while isT2Run:
        if tool.isAuto:
            led = 0x01 << index
            sendToAruino(led)
            index = (index+1) % 4
        time.sleep(0.4)
    print('stop2 thread')

#GUI class 생성
tool = LedControl()

#쓰레드 생성
isT1Run = True
t1 = threading.Thread(target=TH_readSerial)
t1.start()

isT2Run = True
t2 = threading.Thread(target=TH_sendCmdAuto)
t2.start()

#GUI 실행
tool.win.mainloop()

#GUI 종료 후
seri.close()
isT1Run = False
isT2Run = False
time.sleep(0.5)
print('Finish')
반응형