티스토리 뷰

반응형

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

 

코딩나우

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

www.codingnow.co.kr

 

https://youtu.be/gO23X8iSuSs

 

 

 

 

 

 

MCU의 제한된 포트 수로 인한 LED 제어 가능 수가 제한됩니다.

이런 점을 극복하기 위해  matrix 형태로 LED를 구성하게 됩니다.

이번시간에는 matirix를 어떻게 제어하는지 또한 어떻게 활용하는지 강의해 보았습니다.

자세한 사항은 첨부된 동영상을 참고해주세요.

실행결과
led matrix 제어하기 전체 소스코드.zip
0.14MB

1. C언어 - 아두이노

 1-1) 회로구성 (led matrix : 1088BS)

회로구성

1-2) 스케메틱

2) 소스코드

-.main.cpp : 주요 제어 코드

#include "global.h"
#include <MsTimer2.h>
/*
Arduino Uno Board 메인 컨트롤러 : Atmega328 
Atmega328를 3개의 타이머가 있고 PWM 출력 및 시간 관련 함수들을 제공
Timer0 - 8Bit : PWM 5/6핀, 시간 관련 함수 (delay(), millis() 등)
Timer1 - 16Bit : PWM 9/10핀 (외부 라이브러리 Servo.h 와 함께 사용 불가)
Timer2 - 8Bit : PWM 3/11핀 (외부 라이브러리 MsTimer2.h 와 함께 사용 불가)
*/

#define _CONTROL_PYTHON_EN
// #define _TEST_0_EN
// #define _DEMO_EN

unsigned char ledMap[2][COLUMN_MAX] = {
    /*ROW*/ {A5, 3, 13, A2, 6, 12, 7, 10},
    /*COL*/ {2, 8, 9, A4, 11, A3, 4, 5},
};

typedef struct{
unsigned char dispBuffer[ROW_MAX];//display data buffer
unsigned char rxBuffer[ROW_MAX];//serial data buffer
unsigned char currRow;

#if defined(_DEMO_EN) || defined(_TEST_0_EN)
unsigned long timeCurr;
unsigned long timeDealy;
#ifdef _TEST_0_EN
unsigned char idexRow;
unsigned char idexCol;
#endif
#ifdef _DEMO_EN
unsigned char imageIdex;
#endif
#endif
}valType;
valType val;

unsigned char const heart[ROW_MAX] = {
    0b00000000,//0x00
    0b01100110,//0x66
    0b10011001,//0x99
    0b10000001,//0x81
    0b10000001,//0x81
    0b01000010,//0x42
    0b00100100,//0x24
    0b00011000,//0x18
};

#ifdef _DEMO_EN
#define IMAGE_MAX 4
unsigned char const images[IMAGE_MAX][ROW_MAX] = {
    {0x00, 0x42, 0xA5, 0x00, 0x00, 0x00, 0x42, 0x3C},
    {0x00, 0x42, 0xA5, 0x42, 0x00, 0x00, 0x42, 0x3C},
    {0x00, 0x42, 0xA5, 0x00, 0x00, 0x00, 0x3C, 0x42},
    {0x00, 0x66, 0x99, 0x81, 0x81, 0x42, 0x24, 0x18},
};
#endif

void Timer2Interrupt()
{
    unsigned char i, col;
    digitalWrite(ledMap[ROW][val.currRow], LOW); //row port 초기화
    val.currRow = (val.currRow + 1) % ROW_MAX;
    col = val.dispBuffer[val.currRow]; //row의 column을 가져온다.

    for (i = 0; i < COLUMN_MAX; i++)
    {
        if (col & (0x01<<i))
            digitalWrite(ledMap[COL][i], LOW);//column on
        else
            digitalWrite(ledMap[COL][i], HIGH);//column off
    }
    digitalWrite(ledMap[ROW][val.currRow], HIGH); //row port enable
}

void setupMain() 
{
    unsigned char i;
    Serial.begin(9600);//시리얼 초기화
    memset(&val, 0x00, sizeof(val));//변수초기화
    for (i = 0; i < COLUMN_MAX; i++) //포트 초기화
    {
        pinMode(ledMap[ROW][i], OUTPUT); //row
        pinMode(ledMap[COL][i], OUTPUT); //col
    }
    memcpy(val.dispBuffer, heart, sizeof(val.dispBuffer));//heart image 넣기
    // val.dispBuffer[1] = 0x01;
    // memset(val.dispBuffer,0xff, sizeof(val.dispBuffer));
    MsTimer2::set(1, Timer2Interrupt);//timer2 interrupt
    MsTimer2::start();

#if defined(_DEMO_EN) || defined(_TEST_0_EN)
    val.timeCurr = millis();
    val.timeDealy = 1000;
#endif
}

void loopMain()
{
#ifdef _CONTROL_PYTHON_EN
    if (serialGet(val.rxBuffer))
    {
        memcpy(val.dispBuffer, val.rxBuffer, sizeof(val.dispBuffer));
    }
#endif

#if defined(_DEMO_EN) || defined(_TEST_0_EN)
    if ((millis() - val.timeCurr) > val.timeDealy)
    {
        val.timeCurr = millis();
#ifdef _DEMO_EN
        val.timeDealy = 500;
        memcpy(val.dispBuffer, &images[val.imageIdex], sizeof(val.dispBuffer));
        val.imageIdex = (val.imageIdex + 1) % IMAGE_MAX;
#endif
#ifdef _TEST_0_EN
        val.timeDealy = 100;
        memset(val.dispBuffer, 0x00, sizeof(val.dispBuffer));
        val.dispBuffer[val.idexRow] = 0x01 << val.idexCol;

        val.idexCol = (val.idexCol + 1) % COLUMN_MAX;
        if (val.idexCol == 0)
        {
            val.idexRow = (val.idexRow + 1) % ROW_MAX;
        }
#endif
    }
#endif
}

-.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(unsigned char* buffer) 
{
  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 삭제
        Serial.println(str);
        if (str.length() == (2 * ROW_MAX)) 
        {
          unsigned char i,cnt=0;

          for(i=0; i<ROW_MAX; i++)
          {
            buffer[i] = strToHex(str.substring(cnt,cnt+2));
            cnt += 2;
          }
          str = "";
          return 1;
        }
      }
      str = "";
    }
  }
  return 0;
}

2.파이썬

1) 소스코드

 

-.main.py : led 제어 GUI

import serial
import tkinter as tk
import time
import threading

# pip install serial
# pip install pyserial
# pip uninstall serial
images = ['0042A5000000423C',
          '0042A5420000423C',
          '0042A50000003C42',
          '0066998181422418']

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

def sendToAruino(img):
    comm = 'LED'+images[img]
    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('[파이선] 아두이노 Matrix 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
            sendToAruino(int(value))

# #thread 2  함수
def TH_sendCmdAuto():
    global isT1Run
    index = 0
    while isT1Run:
        if tool.isAuto:            
            sendToAruino(index)
            index = (index+1) % len(images)
        time.sleep(0.5)
    print('stop2 thread')

#GUI class 생성
tool = LedControl()

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

#GUI 실행
tool.win.mainloop()

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