[매드] 아두이노 강좌 - 44. DOTMATRIX(MAX7219) 한개 모듈 동작


안녕하세요~ 매드 입니다.

오늘은 DOTMATRIX 에 대해서 알아보도록 하겠습니다.

DOT MATRIX를 구동하는 방법에 여러가지가 있는데 오늘 할 것은 
아두이노에서 DOT MATRIX 구동에 많이 사용되는 MAX7219 칩셋이 사용된 
DOT MATRIX에 대해서 알아보도록 하겠습니다.


44-1. DOT MATRIX란?

<DOT MATRIX(출처:구글사진)>

사실 도트 매트릭스는 별거 없습니다. 제가 아직 7-세그먼트에 대해서 소개한적은 없지만 7-세그먼트 구동에 대해서 아시는 분이라면 아마 큰 문제 없이 이해하시리라 생각되네요.

도트 매트릭스는 가로x세로 해서 LED로 구성된 것이라고 보시면 되는데요. 점이 길게 모이면 선이되고 선이 모이면 면이되는 방식을 이용한 것이라고 생각하시면 됩니다.

<도트 매트릭스 회로(출처:구글사진)>

위 사진과 같이 도트 매트릭스 내부는 LED의 모임으로 구성되어 있는데요. ROW, COL을 이용하여 '내가 원하는 위치' 에 LED를 점등할 수 있는 것이 도트 매트릭스의 장점이 되겠지요. 여기서 문득 떠오르신 분이 있으신지 모르겠지만 이 도트매트릭스의 LED를 RGB LED로 구성하고 좀 더 작고 조밀하게 만든것이 우리가 현재 사용하고 있는 LED 모니터가 되겠습니다~ 간단하죠? 

<도트 매트릭스 연결(출처:구글사진)>

도트 매트릭스의 ROW, COL을 각각 제어하려면 위 사진처럼 아두이노와 선다발로 연결해 주고 하나씩 제어해줘야 합니다. ㅠ.. 저렇게 '병렬'로 연결하면 속도를 빠르게 제어할 있는 장점이 있지만 선도 많이 필요하고 프로그램도 복잡해지는 단점이 있습니다. 

그래서! 우리는 이렇게 '병렬'로 된것을 '직렬'로 제어하기 위해 IC를 사용하게 되는데요.
그것이 아두이노 도트 매트릭스에서 많이 사용하는 MAX7219 IC 입니다.


44-2. MAX7219 도트 매트릭스


<MAX7219 도트 매트릭스 연결(출처:구글사진)>

단적으로 위 사진과 같이 MAX7219 IC를 사용한 도트매트릭스와 아두이노의 연결을 보면 이전에 '병렬' 연결과 '직렬' 연결의 차이를 확연하게 알 수 있습니다. 전원과 DATA, CLK 라인만 있으면 데이터를 쭉~~ 써서 도트매트릭스를 제어할 수 있는 것이죠. 여기에 CS 핀이라고 있는데요. 이것은 Chip Select의 약자로 도트매트릭스(max7219)가 여러개 있다면 그때 그때 어떤 IC를 제어할 것인지 선택할 수 있는 핀이라고 보시면 됩니다. 
캬.. 병렬이라면 도트매트릭스를 2개만 연결할려고 해도 머리가 아파오는데 직렬은 정말 간편하죠? ㅎㅎ

단점은 직렬 연결은 속도가 다르다는 점입니다.


<직렬 병렬 데이터 통신(출처:구글사진)>

직렬의 경우 병렬로 한꺼번에 보내는 데이터를 하니씩 나눠서 보내야하기 때문에 병렬보다 속도가 느릴 수 밖에 없죠. 하지만! 필요한 선의 개수나 제어 응용 및 편의성에서 직렬이 편리하기 때문에 현재는 대부분 직렬을 이용한 통신이 많이 발전해 있고 굉장히 고속 통신이 가능합니다. 
단적으로 우리가 사용하는 USB, SATA 같은 것들이 직렬 통신의 장점을 살린 것들이고 직렬과 병렬을 모두 응용한 것이 PCI-E 같은 통신들이라고 보시면 될 것 같네요. 

이제 기본은 된것 같고 아두이노와 연결해서 동작을 시켜 볼까요?~

아두이노와 max7219를 사용한 도트 매트릭스를 연결합니다.

아두이노 우노    도트매트릭스(MAX7219)
5V                   VCC
GND                GND
D12                 DIN
D10                 CS
D11                 CLK


44-3. 펌웨어 코드

unsigned char i;
unsigned char j;
/*Port Definitions*/
int Max7219_pinCLK = 11;
int Max7219_pinCS = 10;
int Max7219_pinDIN = 12;

int vol;
int val;

unsigned char disp1[65][8] = {
  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0

  {0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0

  {0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //0

  {0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}, //0

  {0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF}, //0

  {0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF}, //0 

  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF}, //0
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, //0

  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F}, //0
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F}, //0
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F}, //0
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F}, //0
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07}, //0
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, //0
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, //0
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //0
};

void Write_Max7219_byte(unsigned char DATA)
{
  unsigned char i;
  digitalWrite(Max7219_pinCS, LOW);
  for (i = 8; i >= 1; i--)
  {
    digitalWrite(Max7219_pinCLK, LOW);
    digitalWrite(Max7219_pinDIN, DATA & 0x80); // Extracting a bit data
    DATA = DATA << 1;
    digitalWrite(Max7219_pinCLK, HIGH);
  }
}

void Write_Max7219(unsigned char address, unsigned char dat)
{
  digitalWrite(Max7219_pinCS, LOW);
  Write_Max7219_byte(address); //address,code of LED
  Write_Max7219_byte(dat); //data,figure on LED
  digitalWrite(Max7219_pinCS, HIGH);
}

void Init_MAX7219(void)
{
  Write_Max7219(0x09, 0x00); //decoding :BCD
  Write_Max7219(0x0a, 0x03); //brightness
  Write_Max7219(0x0b, 0x07); //scanlimit;8 LEDs
  Write_Max7219(0x0c, 0x01); //power-down mode:0,normal mode:1
  Write_Max7219(0x0f, 0x00); //test display:1;EOT,display:0
}

void setup()
{
  Serial.begin(9600);
  pinMode(Max7219_pinCLK, OUTPUT);
  pinMode(Max7219_pinCS, OUTPUT);
  pinMode(Max7219_pinDIN, OUTPUT);
  delay(50);
  for (i = 1; i < 9; i++)
  {
    Write_Max7219(i, disp1[0][i - 1]);
  }
  Init_MAX7219();
}

void loop()
{
  for (j = 0; j < 64; j++)
  {
    for (i = 1; i < 9; i++)
    {
      Write_Max7219(i, disp1[64 - j][i - 1]);
      delay(10);
    }
  }
}

위 코드를 응용해서 사용하지는 않았지만 도트매트릭스 동작을 영상을 통해서 따라해보면 아마 금방 익숙해지실 겁니다.
내가 원하는 위치에 점을 찍고 이것을 응용해서 그림이나 글자를 만들 수 있는 것이죠~


그럼 건승하시기를 바랍니다!! :)
다음 시간에 뵐께여~~ ㅋㅋ


댓글 쓰기

1 댓글

  1. 안녕하세요~ 질문있습니다. 강좌잘 보고 있습니다. 위 강좌와 관련없는 질문입니다.
    릴레이라는 부품이 있는데요. 1,2,4,8 짜리 이렇게 여러가지가 있는데요.
    아누이노 한대에 릴레이를 몇개까지 연결해서 사용할수 있을까요?
    시간이 되신다면 8포트 릴레이 연결해서 테스트 하는 영상 부탁드려도 될까요?
    감사합니다.앞으로 좋은 영상 부탁드려요

    답글삭제