아두이노로 LED matrix 제어하기 #4 : LedControl Library 3

2017. 10. 10. 16:03

Arduino/Display

Arduino LedControl Library #3

이전 글에 이어서 LedControl Library의 setRow() 함수에 대한 활용과 또 다른 출력 함수인 setColumn() 함수에 대해서 알아 보겠습니다.

setRow() with Array

    byte value0 = B00000000;
    byte value1 = B00100010;
    byte value2 = B01110111;
    byte value3 = B01111111;
    byte value4 = B01111111;
    byte value5 = B00111110;
    byte value6 = B00011100;
    byte value7 = B00001000;
    lc.setRow(0, 0, value0);
    lc.setRow(0, 1, value1);
    lc.setRow(0, 2, value2);
    lc.setRow(0, 3, value3);
    lc.setRow(0, 4, value4);
    lc.setRow(0, 5, value5);
    lc.setRow(0, 6, value6);
    lc.setRow(0, 7, value7);

이제 까지의 예제는 모든 행이 같은 값을 출력했습니다. 따라서 byte 값도 하나만 있으면 됐고, For문을 이용해서 쉽게 처리가 가능했습니다. 하지만, 위 코드와 같이 모든 행의 내용이 다를 경우에는 코드가 복잡해 집니다. 이를 해결하기 위해서 byte 데이터를 배열로 구성할 수 있습니다.

    byte value[8] = { B00000000,
                      B00100010,
                      B01110111,
                      B01111111,
                      B01111111,
                      B00111110,
                      B00011100,
                      B00001000 };
    int i;
    for (i = 0; i < 8; i++) {
      lc.setRow(0, i, value[i]);
    }

같은 코드를 배열을 이용하여 표현하였습니다. byte type 배열 value는 크기가 8이므로 "0"부터 "7"까지의 배열 멤버를 가지게 되고, 각각 초기화로 주어진 8개의 값을 저장합니다. 또, setRow() 함수에서 정수형 변수 i 가 두 군데 사용되었기 때문에 배열 멤버를 같은 인덱스의 row에 출력합니다. 이 때문에, 배열 멤버 0번부터 7번까지 순환하는 것과 LED 모듈 0번 행부터 7번 행까지 순환하는 것이 하나의 For문으로 가능하게 되었습니다.

#include "LedControl.h"
LedControl lc = LedControl(12,11,10,3);
void setup() { 
  lc.shutdown(0, false);
  lc.shutdown(1, false);
  lc.shutdown(2, false); 
  lc.setIntensity(0,2);
  lc.setIntensity(1,2);
  lc.setIntensity(2,2);
  lc.clearDisplay(0);
  lc.clearDisplay(1);
  lc.clearDisplay(2);
}
void loop() {
    byte value[8] = { B00000000,
                      B00100010,
                      B01110111,
                      B01111111,
                      B01111111,
                      B00111110,
                      B00011100,
                      B00001000 }; 
    int i;
    for (i = 0; i < 8; i++) {
      lc.setRow(0, i, value[i]);
      lc.setRow(1, i, value[i]);
      lc.setRow(2, i, value[i]);
    }
    delay(1000);
    lc.clearDisplay(0);
    lc.clearDisplay(1);
    lc.clearDisplay(2);
    delay(1000);
}

위의 배열을 이용한 예제입니다. delay() 함수와 clearDisplay() 함수를 이용해서 하트 모양이 blink 하도록 했습니다. For문에 의해 첫 번째 행부터 마지막 행까지 차례로 출력하지만 워낙 실행 속도가 빠르기 때문에 한번에 화면 전체를 출력하는 듯 보이게 됩니다.

결과 화면입니다.

#include "LedControl.h"
LedControl lc = LedControl(12,11,10,3);
void setup() { 
  lc.shutdown(0, false);
  lc.shutdown(1, false);
  lc.shutdown(2, false); 
  lc.setIntensity(0,2);
  lc.setIntensity(1,2);
  lc.setIntensity(2,2);
  lc.clearDisplay(0);
  lc.clearDisplay(1);
  lc.clearDisplay(2);
}
void loop() {
    byte value[8] = { B00000000,
                      B00100010,
                      B01110111,
                      B01111111,
                      B01111111,
                      B00111110,
                      B00011100,
                      B00001000 }; 
    int i;
    for (i = 0; i < 8; i++) {
      lc.setRow(0, i, value[i]);
      lc.setRow(1, i, value[i]);
      lc.setRow(2, i, value[i]);
      delay(500);
    }
    delay(500);
    lc.clearDisplay(0);
    lc.clearDisplay(1);
    lc.clearDisplay(2);
    delay(500);
}

이번 예제는 For문 안쪽에 delay() 함수를 한번 더 넣어서 한 줄씩 출력되는 것을 확인할 수 있도록 했습니다.

setColumn(), examples

LedControl 라이브러리에서 제공하는 LED matrix 출력함수 중 마지막 하나는 setColumn() 함수입니다. setRow()함수와 동작은 동일하나 이름 그대로 행(row)이 아닌 열(column) 방향으로 byte 단위 출력을 합니다. 바로 위에서 실행한 setRow() 함수 예제에서 함수명만 setColumn()으로 변경하면 아래와 같습니다.

#include "LedControl.h"
LedControl lc = LedControl(12,11,10,3);
void setup() { 
  lc.shutdown(0, false);
  lc.shutdown(1, false);
  lc.shutdown(2, false); 
  lc.setIntensity(0,2);
  lc.setIntensity(1,2);
  lc.setIntensity(2,2);
  lc.clearDisplay(0);
  lc.clearDisplay(1);
  lc.clearDisplay(2);
}
void loop() {
    byte value[8] = { B00000000,
                      B00100010,
                      B01110111,
                      B01111111,
                      B01111111,
                      B00111110,
                      B00011100,
                      B00001000 }; 
    int i;
    for (i = 0; i < 8; i++) {
      lc.setColumn(0, i, value[i]);
      lc.setColumn(1, i, value[i]);
      lc.setColumn(2, i, value[i]);
      delay(500);
    }
    delay(500);
    lc.clearDisplay(0);
    lc.clearDisplay(1);
    lc.clearDisplay(2);
    delay(500);
}

결과 화면을 보면 하트 모양이 왼쪽으로 회전하여 출력되었습니다. setRow() 함수와 결과는 같으면서 출력하는 동작만 열 방향으로 하고 싶다면 출력 데이터를 그에 맞게 제공해야 합니다.

    byte value1[8] = {
                      B00000000,
                      B00011000,
                      B00111100,
                      B00111100,
                      B00011000,
                      B00011000,
                      B00000000,
                      B00011000
                    };
    byte value2[8] = {
                      B00000000,
                      B00111100,
                      B01100110,
                      B00000110,
                      B00011100,
                      B00011000,
                      B00000000,
                      B00011000
                    };

추가로 예제 몇 가지 만들어 보겠습니다. 이제까지 예제들은 패턴이 하트 모양 하나였지만, 패턴이 늘어나 바로 위 코드처럼 매번 배열을 하나씩 만든다면 코딩하기가 까다롭습니다.

byte value[2][8] = {
{
  B00000000,
  B00011000,
  B00111100,
  B00111100,
  B00011000,
  B00011000,
  B00000000,
  B00011000
},
{
  B00000000,
  B00111100,
  B01100110,
  B00000110,
  B00011100,
  B00011000,
  B00000000,
  B00011000
}
};

패턴이 많아 진다면 위와 같이 2차원 배열로 데이터를 구성하는 것이 좋습니다. 패턴이 많아져도 배열명 하나로 모두 처리할 수 있고, 또 For문을 이용해 자동화할 수도 있기 때문입니다.

#include "LedControl.h"
LedControl lc = LedControl(12,11,10,3);
byte value[2][8] = {
{
  B00000000,
  B00011000,
  B00111100,
  B00111100,
  B00011000,
  B00011000,
  B00000000,
  B00011000
},
{
  B00000000,
  B00111100,
  B01100110,
  B00000110,
  B00011100,
  B00011000,
  B00000000,
  B00011000
}
};
void setup() { 
  lc.shutdown(0, false);
  lc.shutdown(1, false);
  lc.shutdown(2, false); 
  lc.setIntensity(0,2);
  lc.setIntensity(1,2);
  lc.setIntensity(2,2);
  lc.clearDisplay(0);
  lc.clearDisplay(1);
  lc.clearDisplay(2);
}
void loop() { 
    int i;
    for (i = 0; i < 8; i++) {
      lc.setRow(0, i, value[0][i]);
      lc.setRow(1, i, value[0][i]);
      lc.setRow(2, i, value[0][i]);
    }
    delay(1000);
    for (i = 0; i < 8; i++) {
      lc.setRow(0, i, value[1][i]);
      lc.setRow(1, i, value[1][i]);
      lc.setRow(2, i, value[1][i]);
    }
    delay(1000);
}

2차원 배열을 이용해 2가지 패턴을 번갈아 출력하는 소스입니다. 배열 선언 부분을 setup() 함수 위쪽으로 올려서 loop() 함수내에서 매번 선언되는 것을 피했습니다.

#include "LedControl.h"
LedControl lc = LedControl(12,11,10,3);
byte value[][8] = {
{
  B00000000,
  B00100000,
  B00110000,
  B11111000,
  B11111100,
  B11111000,
  B00110000,
  B00100000
},
{
  B00000000,
  B00001000,
  B00001100,
  B01111110,
  B01111111,
  B01111110,
  B00001100,
  B00001000
},
{
  B00000000,
  B00000010,
  B00000011,
  B00011111,
  B00011111,
  B00011111,
  B00000011,
  B00000010
},
{
  B00000000,
  B00000000,
  B00000000,
  B00000111,
  B00000111,
  B00000111,
  B00000000,
  B00000000
}
};
void setup() { 
  lc.shutdown(0, false);
  lc.shutdown(1, false);
  lc.shutdown(2, false); 
  lc.setIntensity(0,2);
  lc.setIntensity(1,2);
  lc.setIntensity(2,2);
  lc.clearDisplay(0);
  lc.clearDisplay(1);
  lc.clearDisplay(2);
}
void loop() {
  int i, j;
  for (i = 0; i < 4; i++) {
    for (j = 0; j < 8; j++) {
      lc.setRow(0, j, value[i][j]);
      lc.setRow(1, j, value[i][j]);
      lc.setRow(2, j, value[i][j]);
    }
    delay(500);      
  }
  lc.clearDisplay(0);
  lc.clearDisplay(1);
  lc.clearDisplay(2);
  delay(500);
}

패턴이 4가지입니다. 2차원 배열로 구성했으며 중첩 For문을 이용해서 출력하도록 했습니다.

#include "LedControl.h"
LedControl lc = LedControl(12,11,10,3);
byte value[][8] = {
{
  B00000000,
  B00000000,
  B00000000,
  B00000000,
  B00000000,
  B00000000,
  B00000000,
  B00000000
},{
  B00000000,
  B00000000,
  B00000000,
  B10000000,
  B11000000,
  B10000000,
  B00000000,
  B00000000
},{
  B00000000,
  B10000000,
  B11000000,
  B11100000,
  B11110000,
  B11100000,
  B11000000,
  B10000000
},{
  B00000000,
  B00100000,
  B00110000,
  B11111000,
  B11111100,
  B11111000,
  B00110000,
  B00100000
},{
  B00000000,
  B00001000,
  B00001100,
  B01111110,
  B01111111,
  B01111110,
  B00001100,
  B00001000
},{
  B00000000,
  B00000010,
  B00000011,
  B00011111,
  B00011111,
  B00011111,
  B00000011,
  B00000010
},{
  B00000000,
  B00000000,
  B00000000,
  B00000111,
  B00000111,
  B00000111,
  B00000000,
  B00000000
},{
  B00000000,
  B00000000,
  B00000000,
  B00000001,
  B00000001,
  B00000001,
  B00000000,
  B00000000
}};
void setup() { 
  lc.shutdown(0, false);
  lc.shutdown(1, false);
  lc.shutdown(2, false); 
  lc.setIntensity(0,2);
  lc.setIntensity(1,2);
  lc.setIntensity(2,2);
  lc.clearDisplay(0);
  lc.clearDisplay(1);
  lc.clearDisplay(2);
}
void loop() {
  int i, j;
  for (i = 0; i < 8; i++) {
    for (j = 0; j < 8; j++) {
      lc.setRow(0, j, value[i][j]);
      lc.setRow(1, j, value[i][j]);
      lc.setRow(2, j, value[i][j]);
    }
    delay(500);      
  }
}

패턴을 8개로 늘렸습니다. 데이터를 2차원 배열로 선언하는 부분에서 첫 번째 첨자는 생략되어 있습니다. 초기화하는 인수 개수에 따라 자동으로 범위가 정해지기 때문에 생략 가능합니다.

#include "LedControl.h"
LedControl lc = LedControl(12,11,10,3);
byte value[][8] = {
{
  B00000000,
  B00000000,
  B00000000,
  B10000000,
  B11000000,
  B10000000,
  B00000000,
  B00000000
},
{
  B00000000,
  B10000000,
  B11000000,
  B11100000,
  B11110000,
  B11100000,
  B11000000,
  B10000000
},
{
  B00000000,
  B00100000,
  B00110000,
  B11111000,
  B11111100,
  B11111000,
  B00110000,
  B00100000
},
{
  B00000000,
  B00001000,
  B00001100,
  B01111110,
  B01111111,
  B01111110,
  B00001100,
  B00001000
},
{
  B00000000,
  B00000010,
  B00000011,
  B00011111,
  B00011111,
  B00011111,
  B00000011,
  B00000010
},
{
  B00000000,
  B00000000,
  B00000000,
  B00000111,
  B00000111,
  B00000111,
  B00000000,
  B00000000
},
{
  B00000000,
  B00000000,
  B00000000,
  B00000001,
  B00000001,
  B00000001,
  B00000000,
  B00000000
},
{
  B00000000,
  B00000000,
  B00000000,
  B00000000,
  B00000000,
  B00000000,
  B00000000,
  B00000000
}
};
void setup() { 
  lc.shutdown(0, false);
  lc.shutdown(1, false);
  lc.shutdown(2, false); 
  lc.setIntensity(0,2);
  lc.setIntensity(1,2);
  lc.setIntensity(2,2);
  lc.clearDisplay(0);
  lc.clearDisplay(1);
  lc.clearDisplay(2);
}
void loop() {
  int i, j;
  for (i = 0; i < 16; i++) {
    for (j = 0; j < 8; j++) {
      if (i <= 7) {
        lc.setRow(0, j, value[i][j]);
      }
      if (i >= 4 && i <= 11) {
        lc.setRow(1, j, value[i - 4][j]);
      } 
      if (i >= 8) {
        lc.setRow(2, j, value[i - 8][j]);
      }
    }
    delay(500);      
  }
}

패턴은 8개로 동일하고 For문만 약간 수정해서 3개 모듈을 통과하는 Flow animation을 표현했습니다. Flow animation은 다음 글에서 좀더 좋은 방식으로 구성하도록 할 예정입니다.

이상으로 LedControl Library에 대한 소개를 마치고, 다음 글에선 숫자, 문자 출력 등 라이브러리를 활용하는 예제를 작성해 보겠습니다.

Comments