이런거 저런거 그런거

8x8 Led Matrix를 전체 컨트롤 해 보기 본문

이것저것 해보기/아두이노 가지고 놀기

8x8 Led Matrix를 전체 컨트롤 해 보기

빵진 2019. 9. 17. 21:15

 

8x8 Led Matrix를 전체 컨트롤 해 보기

 

 

우선 아래 왼쪽 테이블과 같이 핀을 연결한다.

ex> Led Matrix 1번핀 -> Uno 2번핀

그리고 Matrix Led의 핀맵을 보고 Uno에 해당하는 핀 번호를 찾아보면

  ex> Matrix Led의 Row 0을 컨트롤 하려면 Matrix Led의 9번 핀 ---> Uno의 10번 핀.

  즉, Uno의 10번핀은 Matrix Led Row 0을 컨트롤 하는 핀

 

이렇게 연결하면 아래와 같이 깔끔(?)하게 연결 할 수 있다. (적어도 선이 날라다니진 않으니...)

그리고 테스트 코드를 돌려서 홀수인 곳만 켜보면~

#define ARRAY_SIZE(x) (sizeof((x))/sizeof((x)[0]))

unsigned int rows[] = {10, A1, 9, 13, 2, 8, 3, 6};
unsigned int cols[] = {A0, 4, 5, 11, 7, 12, A2, A3};

void setup()
{
  int i;
  for (i = 0; i < ARRAY_SIZE(rows); i++) {
    pinMode(rows[i], OUTPUT);
    pinMode(cols[i], OUTPUT);

    if (i % 2) {
      digitalWrite(rows[i], HIGH);
      digitalWrite(cols[i], LOW);
    } else {
      digitalWrite(rows[i], LOW);
      digitalWrite(cols[i], HIGH);
    }
  }
}

void loop()
{
  delay(200); //200ms delay
}

 

 

이번엔 무엇을 출력해 볼까 하다 그 분께서 사람 얼굴(?)을 그려주셨다

(http://dotmatrixtool.com/#)

모듈 특성 상 한 번에 여러 라인을 그릴 수 없고 한 번에 한 라인만 그릴 수 있다.

즉, 켜고 싶은 column을 설정하고 -> row에 전원을 켜서 -> 해당 row의 원하는 column에만 불이 켜지는 방법이다.

그래서 8개 row를 순차적으로 하나하나 그리되 이 동작을 빠~르게 해서 잔상효과를 이용하여 그림이 그려진 척하는 것이다.

 

테스트 해 보았을때는 10ms로 했더니 부족하고 2ms로....

#define ARRAY_SIZE(x) (sizeof((x))/sizeof((x)[0]))

unsigned int rows[] = {10, A1, 9, 13, 2, 8, 3, 6};
unsigned int cols[] = {A0, 4, 5, 11, 7, 12, A2, A3};

unsigned char shape[][8][8] = {
  //Face
  {
    {1, 1, 1, 1, 1, 1, 1, 1},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {1, 1, 1, 0, 0, 1, 1, 1},
    {0, 1, 0, 0, 0, 0, 1, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 1, 0, 0, 0, 0, 1, 0},
    {0, 0, 1, 1, 1, 1, 0, 0},
  },
};

void setup()
{
  int i;
  for (i = 0; i < ARRAY_SIZE(rows); i++) {
    pinMode(rows[i], OUTPUT);
    pinMode(cols[i], OUTPUT);

    //led off
    digitalWrite(rows[i], LOW);
    digitalWrite(cols[i], HIGH);
  }
}

void loop()
{
  static int row = 0, prev_row = 7;
  int i;

  //turn off previous row
  digitalWrite(rows[prev_row], LOW);

  //turn on columns
  for (i = 0; i < 8; i++) {
    if (shape[0][row][i]) {
      digitalWrite(cols[i], LOW);
    } else {
      digitalWrite(cols[i], HIGH);
    }
  }

  //turn on current row
  digitalWrite(rows[row], HIGH);

  row = (row + 1) % 8;
  prev_row = (prev_row + 1) % 8;
  delay(2); //10ms delay
}

 

짜잔 성공~!

 

참고로 위와 같이 loop()에서 delay()를 사용하면서 구현하는 것은 좋지 않은 방법이다.

loop()가 delay()에 설정된 시간만큼 delay되기 때문에 loop()에 다른 동작동작이 있다면 그만큼 지연되기 때문이다.

다른 대안으로는 아래와 같이 2가지 방법을 생각 할 수 있는데

1. SimpleTimer를 이용

https://playground.arduino.cc/Code/SimpleTimer/

falling 방식의 timer로서 loop()안에서 SimpleTimer클래스의 run()을 호출해줘야한다.

loop()에 있는 다른 코드에 의해 지연 될 수 있으므로 정확한 타이머라고 볼 수는 없지만

적어도 엄격하게 주기적으로 실행될 필요가 없는 경우엔 사용하기 괜찮은 방법이다.

 

2. HW Timer Interrupt를 이용

아두이노에는 HW Timer가 있다. 이를 이용하여 인터럽트를 등록 후 사용하는 것이다.

정확한 타이밍에 호출되어야 하는 경우 사용하는게 좋다.

아두이노의 HW Timer 사양과 사용 방법에 대해 다음에 알아 볼 계획이다.

직접 레지스터를 설정해가며 이용 할 수도 있겠지만 쉽게 사용하는 방법은 TimerOne 라이브러리를 이용하는 것이다.

https://playground.arduino.cc/Code/Timer1/

 

Arduino Playground - Timer1

:: Timer1 :: This library is a collection of routines for configuring the 16 bit hardware timer called Timer1 on the ATmega168/328. There are 3 hardware timers available on the chip, and they can be configured in a variety of ways to achieve different func

playground.arduino.cc

 

 

 

이것저것 그려보고 싶지만 귀찮기도하고.. 어차피 배열 0/1 바꾸는게 전부라....

8x8에 원하는 모양을 그리는 것으로 만족~

Comments