본문 바로가기

Arduino

Arduino + 8x8 Dot matrix - 1 (아두이노 + 도트 매트릭스)



Arduino 로 8x8 Dot matrix 를 구동시켜 보았습니다.

저 놈을 동작 시키기 위해서는 아두이노의 핀을 총 동원하면 별도 부품 없이도 가능합니다.
하지만 지난번에 74HC595 를 구동시켜 봤으니 그놈과 결합해서 해보았습니다... 다들 이렇게 하더군요 ㅎ

준비물
- Arduino
- 74HC595 x2
- 240ohm 저항 x8

제가 구입한 Dot matrix 는 SZ411288K-16P 란 모델명을 가진 녀석으로 엘레파츠에서 3,500원에 구할 수 있는 녀석입니다.



이 도트 매트릭스는 64개의 LED를 단순히 직렬 병렬 연결한 것입니다.

이놈을 동작 시켜야할 순서는 요렇습니다.
1. 왼쪽 세로로 된 라인에서 첫번째 라인 선택 (첫번재 라인만 ON, 나머지 라인은 모두 OFF)
2. 첫번째 라인에서 켜야할 LED를 선택해서 ON
3. 두번째 라인 선택 (두번째 라인만 ON, 나머지 라인 모두 OFF)
4. 두번째 라인에서 켜야할 LED 선택
....
이렇게 8줄을 반복하는것을 빨리 동작시키면
사용자가 볼때는 매트릭스가 동시에 들어오고, 또한 켜진채 유지되는것처럼 보이게 됩니다.


쉽겠거니 생각했는데 이런걸 처음 해보는 저로서는 사실 연결하는 것부터 만만치 않았습니다.

사진과 같은 순서로 핀 번호가 되어 있습니다.

모델명을 위로 놓고 반시계방향으로 핀 번호가 붙습니다.

저는 두개의 74HC595 중에 하나는 라인선택용으로, 하나는 LED 선택용으로 쓸껀데

세로라인 선택에 쓸 74HC595 의 PIN15, PIN0~7 는 순서대로
데이터시트를 참고해서 9, 14, 8, 12, 1, 7, 2, 5 핀에다가 꽂으면 됩니다. (왜 순서대로 만들어 놓지 않은걸까 ;;)

LED선택에 쓸 74HC595 칩은 PIN15, PIN0~7 을
13, 3, 4, 10, 6, 11, 15, 16 순서로 꽂습니다.

시프트 레지스터와 LED는 이렇게 연결했고 

시프트 레지스터와 아두이노를 연결해야하는데요.
그런데...
시프트 레지스터 두개는 MCU또는 아두이노의 3개 핀만으로도 제어가 가능합니다.
74HC595 의 9번핀을 다른 74HC595 의 데이터 입력 핀으로 연결해서 쓰는건데..사실 이 방법이 보통인데
전 그냥 아두이노의 6개 핀을 써서 두개의 시프트레지스터를 제어하는걸로 했습니다.
왜냐면 .. 아는 내용으로 빨리 구동시켜 보고 싶어서 ㅜㅜ

3핀으로 할 수 있는걸 6핀으로 동작시킴

매트릭스의 구동순서는 한줄만 켜고 다음줄로 이동하는걸 반복합니다.
그런데 주의해야할 점은 다음 줄로 이동한 직후
다시 LED on/off 정보를 넣기 전까지
잠시나마 이전 LED ON 정보를 가지고 있기때문에 살짝 잔상이 남는걸 볼 수 있습니다.
이걸 막기 위해서 LED를 모두 off하고 다음줄로 넘어가야 합니다.


그리고 스케치는

전 쉽게 떠오르는게 2차원 배열이라서 그렇게 했는데, 다른분들이 만든 코드를 보니
다들 배열보다는 비트데이터를 만들어 쓰시더군요.
도트매트릭스는 이미 오래된 기술이기 때문에 PC에서 쉽게 쓸 수 있는
폰트제너리이트 유틸도 쉽게 구할 수 있더군요.. 하지만 이것도 비트로 데이터가 나옵니다.

나중에 배열 안쓰는걸로 고쳐야 겠네요. ㅜㅜ


도트매트릭스 스케치입니다. 구동시키면 1초단위로 꺼짐->O->X를 반복해서 보여줍니다.

int DataPin_1 = 4;  //pin 14 on the 75HC595 (+)
int HoldPin_1 = 3;  //pin 12
int ShiftPin_1 = 2;  //pin 11
int DataPin_2 = 7; //pin 14 on the 75HC595 (-)
int HoldPin_2 = 6; //pin 12
int ShiftPin_2 = 5; //pin 11

#define numOfRegisterPins 8

boolean registers[numOfRegisterPins];

void setup(){
  pinMode(DataPin_1, OUTPUT);
  pinMode(HoldPin_1, OUTPUT);
  pinMode(ShiftPin_1, OUTPUT);
 
  pinMode(DataPin_2, OUTPUT);
  pinMode(HoldPin_2, OUTPUT);
  pinMode(ShiftPin_2, OUTPUT);

  //reset all register pins
  clearMatrix();
  writeMatrix(1);
  writeMatrix(2);
 
  delay(1);
}              

//set all register pins to HIGH
void clearMatrix(){
  for(int i = numOfRegisterPins - 1; i >=  0; i--){
     registers[i] = HIGH;
  }
}

/* set 74HC595 and out
    index:1 - select row shift register
    index:2 - select column shift register */
void writeMatrix(int index){
  if (index == 1) {
    digitalWrite(HoldPin_1, LOW);
    for(int i = numOfRegisterPins - 1 ; i >= 0; i--){
      digitalWrite(ShiftPin_1, LOW);
      int val = registers[i];
      digitalWrite(DataPin_1, val);
      digitalWrite(ShiftPin_1, HIGH);
    }
    digitalWrite(HoldPin_1, HIGH);
  }
  else if (index == 2) {
    digitalWrite(HoldPin_2, LOW);
    for(int i = numOfRegisterPins - 1; i >= 0; i--){
      digitalWrite(ShiftPin_2, LOW);
      int val = registers[i];
      digitalWrite(DataPin_2, val);
      digitalWrite(ShiftPin_2, HIGH);
    }
    digitalWrite(HoldPin_2, HIGH);
  } else {
    //nothing
  }
}

/* Set one line register
    line: line number
    dot[8]: LED set to On/Off */
void setLineMatrix(int line, boolean dot[8]) {
   
  clearMatrix(); //prevent flicker
  writeMatrix(2);
 
  boolean col[8] = {0,0,0,0,0,0,0,0};
  col[line] = 1; // select one line
  for (int i = 0; i < 8; i++) { //set line
    registers[i] = col[i];
  }
  writeMatrix(1);
  for (int i = 0; i < 8; i++) { //set dots
    registers[i] = dot[i];
  }
  writeMatrix(2);
  delay(1); //delay for readability
}

/* set matrix
    dot[8][8]: matrix array
    delay: display time (ms) */
void setFullMatrixTime(boolean dot[8][8], int mdelay) {
  boolean col[8] = {};
  int i,j;
  unsigned long endTimer = millis() + mdelay;
 
  while(millis() < endTimer) {
    for (i = 0; i < 8; i++) {
      for (j = 0; j < 8; j++) {
        col[j] = dot[i][j];     
      }
      setLineMatrix(i, col);   
    }
  }
}

void loop(){
  //temp array for testing
  boolean dot0[8][8] = {{1,1,1,1,1,1,1,1},
                        {1,1,1,1,1,1,1,1},
                        {1,1,1,1,1,1,1,1},
                        {1,1,1,1,1,1,1,1},
                        {1,1,1,1,1,1,1,1},
                        {1,1,1,1,1,1,1,1},
                        {1,1,1,1,1,1,1,1},
                        {1,1,1,1,1,1,1,1}};
                       
  boolean dot1[8][8] = {{0,1,1,1,1,1,1,0},
                        {1,0,1,1,1,1,0,1},
                        {1,1,0,1,1,0,1,1},
                        {1,1,1,0,0,1,1,1},
                        {1,1,1,0,0,1,1,1},
                        {1,1,0,1,1,0,1,1},
                        {1,0,1,1,1,1,0,1},
                        {0,1,1,1,1,1,1,0},};
 
   boolean dot2[8][8] = {{1,1,0,0,0,0,1,1},
                         {1,0,1,1,1,1,0,1},
                         {0,1,1,1,1,1,1,0},
                         {0,1,1,1,1,1,1,0},
                         {0,1,1,1,1,1,1,0},
                         {0,1,1,1,1,1,1,0},
                         {1,0,1,1,1,1,0,1},
                         {1,1,0,0,0,0,1,1},};
  // display during 1 second
  setFullMatrixTime(dot0,1000);
  setFullMatrixTime(dot1,1000);
  setFullMatrixTime(dot2,1000);
}