Arduino LedControl Library : 숫자, 문자 출력하기
이전 글에서 살펴봤던 LedControl Library 기본 함수를 이용해서 숫자와 문자(영문자)를 출력하는 함수를 작성하겠습니다.
숫자, 문자 패턴 만들기
LedControl 라이브러리에서 숫자, 문자 표현을 제공하는 함수는 따로 없습니다. 이전 예제에서 하트, 화살표 모양을 출력했듯이 숫자, 문자 모양을 setRow()
함수 등을 이용해 직접 구성해야 합니다.
LedControl.h 헤더 파일을 열어 보면, setDigit(), setChar()
함수가 있지만 이들은 matrix LED가 아닌 7-segment LED를 위한 함수입니다. segment LED는 7개의 LED를 통해서 나올 수 있는 패턴이 거의 정해져 있지만, matrix LED는 64개의 LED를 이용하여 만들 수 있는 패턴이 다양하기 때문에 라이브러리에 같이 담지 않은 듯 합니다.
숫자, 문자 패턴을 구성하는 것은 점을 찍어 비트맵 폰트를 만드는 것과 동일합니다. 이미 이전 글에서 하트, 화살표 모양을 출력하는 예제를 다루었고, 모양이 숫자로 바뀔 뿐이므로 자세한 설명은 생략하겠습니다.
위 그림에서 보듯이 숫자, 문자를 표현하기 위해 원하는 위치의 LED를 켜는 것처럼 byte 배열의 해당하는 bit를 숫자 "1"로 세팅하여 비트맵을 만듭니다. 이전 글에서 setRow()
함수를 이용해서 byte 단위로 출력하는 방법과 출력할 내용 즉 byte들을 배열로 구성하여 처리하는 내용을 다루었는데, 위와 같이 비트맵을 만들고 배열로 구성하여 동일한 방법으로 처리하면 됩니다.
#include "LedControl.h"
LedControl lc = LedControl(12,11,10,3);
byte digits[10][8] = {
{
B00111000,
B01000100,
B01000100,
B01000100,
B01000100,
B01000100,
B01000100,
B00111000
},
{
B00010000,
B00110000,
B00010000,
B00010000,
B00010000,
B00010000,
B00010000,
B00111000
},
{
B00111000,
B01000100,
B00000100,
B00000100,
B00001000,
B00010000,
B00100000,
B01111100
},
{
B00111000,
B01000100,
B00000100,
B00011000,
B00000100,
B00000100,
B01000100,
B00111000
},
{
B00000100,
B00001100,
B00010100,
B00100100,
B01000100,
B01111100,
B00000100,
B00000100
},
{
B01111100,
B01000000,
B01000000,
B01111000,
B00000100,
B00000100,
B01000100,
B00111000
},
{
B00111000,
B01000100,
B01000000,
B01111000,
B01000100,
B01000100,
B01000100,
B00111000
},
{
B01111100,
B00000100,
B00000100,
B00001000,
B00010000,
B00100000,
B00100000,
B00100000
},
{
B00111000,
B01000100,
B01000100,
B00111000,
B01000100,
B01000100,
B01000100,
B00111000
},
{
B00111000,
B01000100,
B01000100,
B01000100,
B00111100,
B00000100,
B01000100,
B00111000
}
};
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 < 10; i++) {
for (j = 0; j < 8; j++) {
lc.setRow(0, j, digits[i][j]);
lc.setRow(1, j, digits[i][j]);
lc.setRow(2, j, digits[i][j]);
}
delay(500);
}
}
"0 ~ 9"까지의 숫자를 byte type 2차원 배열로 구성한 후, 0.5초마다 3개의 LED matrix에 같은 숫자를 출력하도록 구성한 소스입니다. 결과는 아래와 같습니다.
문자도 위와 같은 방법으로 만들어 사용할 수 있습니다. 펜과 종이로 직접 그려보며 만들 수도 있고, 엑셀로 표를 만들어 구성할 수도 있는데, 이를 byte 단위 비트열로 변환하는 것까지 하려면 여간 귀찮은게 아닐 듯 합니다. 이 작업을 쉽게 하기 위한 좋은 방법은 전용 에디터를 이용하는 것입니다. 구글에서 "Led matrix editor" 등으로 검색해보면 온라인상에서 쉽게 편집할 수 있도록 기능을 제공하는 사이트들을 여럿 찾을 수 있습니다. 제가 사용했던 패턴들도 모두 이러한 방법으로 그저 가져오기만 한 것입니다.
위 링크를 따라가면 제가 이용한 사이트를 볼 수 있습니다. 기본으로 제공하는 숫자, 문자, 기호 등을 저처럼 그대로 이용할 수도 있고, Shift 기능을 이용해 이전 예제에서 사용한 화살표 애니메이션을 만들 수도 있습니다.
#include "LedControl.h"
LedControl lc = LedControl(12,11,10,3);
byte chars[][8] = {
{
B00000000,
B00111100,
B01100110,
B01100110,
B01111110,
B01100110,
B01100110,
B01100110
},{
B00000000,
B01111100,
B01100110,
B01100110,
B01111100,
B01100110,
B01100110,
B01111100
},{
B00000000,
B00111100,
B01100110,
B01100000,
B01100000,
B01100000,
B01100110,
B00111100
},{
B00000000,
B01111100,
B01100110,
B01100110,
B01100110,
B01100110,
B01100110,
B01111100
},{
B00000000,
B01111110,
B01100000,
B01100000,
B01111100,
B01100000,
B01100000,
B01111110
},{
B00000000,
B01111110,
B01100000,
B01100000,
B01111100,
B01100000,
B01100000,
B01100000
},{
B00000000,
B00111100,
B01100110,
B01100000,
B01100000,
B01101110,
B01100110,
B00111100
},{
B00000000,
B01100110,
B01100110,
B01100110,
B01111110,
B01100110,
B01100110,
B01100110
},{
B00000000,
B00111100,
B00011000,
B00011000,
B00011000,
B00011000,
B00011000,
B00111100
},{
B00000000,
B00011110,
B00001100,
B00001100,
B00001100,
B01101100,
B01101100,
B00111000
},{
B00000000,
B01100110,
B01101100,
B01111000,
B01110000,
B01111000,
B01101100,
B01100110
},{
B00000000,
B01100000,
B01100000,
B01100000,
B01100000,
B01100000,
B01100000,
B01111110
},{
B00000000,
B01100011,
B01110111,
B01111111,
B01101011,
B01100011,
B01100011,
B01100011
},{
B00000000,
B01100011,
B01110011,
B01111011,
B01101111,
B01100111,
B01100011,
B01100011
},{
B00000000,
B00111100,
B01100110,
B01100110,
B01100110,
B01100110,
B01100110,
B00111100
},{
B00000000,
B01111100,
B01100110,
B01100110,
B01100110,
B01111100,
B01100000,
B01100000
},{
B00000000,
B00111100,
B01100110,
B01100110,
B01100110,
B01101110,
B00111100,
B00000110
},{
B00000000,
B01111100,
B01100110,
B01100110,
B01111100,
B01111000,
B01101100,
B01100110
},{
B00000000,
B00111100,
B01100110,
B01100000,
B00111100,
B00000110,
B01100110,
B00111100
},{
B00000000,
B01111110,
B01011010,
B00011000,
B00011000,
B00011000,
B00011000,
B00011000
},{
B00000000,
B01100110,
B01100110,
B01100110,
B01100110,
B01100110,
B01100110,
B00111110
},{
B00000000,
B01100110,
B01100110,
B01100110,
B01100110,
B01100110,
B00111100,
B00011000
},{
B00000000,
B01100011,
B01100011,
B01100011,
B01101011,
B01111111,
B01110111,
B01100011
},{
B00000000,
B01100011,
B01100011,
B00110110,
B00011100,
B00110110,
B01100011,
B01100011
},{
B00000000,
B01100110,
B01100110,
B01100110,
B00111100,
B00011000,
B00011000,
B00011000
},{
B00000000,
B01111110,
B00000110,
B00001100,
B00011000,
B00110000,
B01100000,
B01111110
}};
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 < 26; i++) {
for (j = 0; j < 8; j++) {
lc.setRow(0, j, chars[i][j]);
lc.setRow(1, j, chars[i][j]);
lc.setRow(2, j, chars[i][j]);
}
delay(500);
}
}
위 사이트에서 알파벳 대문자만 가져와서 숫자 예제와 같은 방식으로 출력하는 소스를 만들었습니다. 소문자와 다른 기호들도 같은 방식으로 가져와 사용하면 됩니다.
#include "LedControl.h"
LedControl lc = LedControl(12,11,10,3);
byte digits[10][8] = {
{
B00111000,
B01000100,
B01000100,
B01000100,
B01000100,
B01000100,
B01000100,
B00111000
},
{
B00010000,
B00110000,
B00010000,
B00010000,
B00010000,
B00010000,
B00010000,
B00111000
},
{
B00111000,
B01000100,
B00000100,
B00000100,
B00001000,
B00010000,
B00100000,
B01111100
},
{
B00111000,
B01000100,
B00000100,
B00011000,
B00000100,
B00000100,
B01000100,
B00111000
},
{
B00000100,
B00001100,
B00010100,
B00100100,
B01000100,
B01111100,
B00000100,
B00000100
},
{
B01111100,
B01000000,
B01000000,
B01111000,
B00000100,
B00000100,
B01000100,
B00111000
},
{
B00111000,
B01000100,
B01000000,
B01111000,
B01000100,
B01000100,
B01000100,
B00111000
},
{
B01111100,
B00000100,
B00000100,
B00001000,
B00010000,
B00100000,
B00100000,
B00100000
},
{
B00111000,
B01000100,
B01000100,
B00111000,
B01000100,
B01000100,
B01000100,
B00111000
},
{
B00111000,
B01000100,
B01000100,
B01000100,
B00111100,
B00000100,
B01000100,
B00111000
}
};
byte chars[][8] = {
{
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000
},{
B00000000,
B00111100,
B01100110,
B01100110,
B01111110,
B01100110,
B01100110,
B01100110
},{
B00000000,
B01111100,
B01100110,
B01100110,
B01111100,
B01100110,
B01100110,
B01111100
},{
B00000000,
B00111100,
B01100110,
B01100000,
B01100000,
B01100000,
B01100110,
B00111100
},{
B00000000,
B01111100,
B01100110,
B01100110,
B01100110,
B01100110,
B01100110,
B01111100
},{
B00000000,
B01111110,
B01100000,
B01100000,
B01111100,
B01100000,
B01100000,
B01111110
},{
B00000000,
B01111110,
B01100000,
B01100000,
B01111100,
B01100000,
B01100000,
B01100000
},{
B00000000,
B00111100,
B01100110,
B01100000,
B01100000,
B01101110,
B01100110,
B00111100
},{
B00000000,
B01100110,
B01100110,
B01100110,
B01111110,
B01100110,
B01100110,
B01100110
},{
B00000000,
B00111100,
B00011000,
B00011000,
B00011000,
B00011000,
B00011000,
B00111100
},{
B00000000,
B00011110,
B00001100,
B00001100,
B00001100,
B01101100,
B01101100,
B00111000
},{
B00000000,
B01100110,
B01101100,
B01111000,
B01110000,
B01111000,
B01101100,
B01100110
},{
B00000000,
B01100000,
B01100000,
B01100000,
B01100000,
B01100000,
B01100000,
B01111110
},{
B00000000,
B01100011,
B01110111,
B01111111,
B01101011,
B01100011,
B01100011,
B01100011
},{
B00000000,
B01100011,
B01110011,
B01111011,
B01101111,
B01100111,
B01100011,
B01100011
},{
B00000000,
B00111100,
B01100110,
B01100110,
B01100110,
B01100110,
B01100110,
B00111100
},{
B00000000,
B01111100,
B01100110,
B01100110,
B01100110,
B01111100,
B01100000,
B01100000
},{
B00000000,
B00111100,
B01100110,
B01100110,
B01100110,
B01101110,
B00111100,
B00000110
},{
B00000000,
B01111100,
B01100110,
B01100110,
B01111100,
B01111000,
B01101100,
B01100110
},{
B00000000,
B00111100,
B01100110,
B01100000,
B00111100,
B00000110,
B01100110,
B00111100
},{
B00000000,
B01111110,
B01011010,
B00011000,
B00011000,
B00011000,
B00011000,
B00011000
},{
B00000000,
B01100110,
B01100110,
B01100110,
B01100110,
B01100110,
B01100110,
B00111110
},{
B00000000,
B01100110,
B01100110,
B01100110,
B01100110,
B01100110,
B00111100,
B00011000
},{
B00000000,
B01100011,
B01100011,
B01100011,
B01101011,
B01111111,
B01110111,
B01100011
},{
B00000000,
B01100011,
B01100011,
B00110110,
B00011100,
B00110110,
B01100011,
B01100011
},{
B00000000,
B01100110,
B01100110,
B01100110,
B00111100,
B00011000,
B00011000,
B00011000
},{
B00000000,
B01111110,
B00000110,
B00001100,
B00011000,
B00110000,
B01100000,
B01111110
},{
B00000000,
B00000000,
B00000000,
B00111100,
B00000110,
B00111110,
B01100110,
B00111110
},{
B00000000,
B01100000,
B01100000,
B01100000,
B01111100,
B01100110,
B01100110,
B01111100
},{
B00000000,
B00000000,
B00000000,
B00111100,
B01100110,
B01100000,
B01100110,
B00111100
},{
B00000000,
B00000110,
B00000110,
B00000110,
B00111110,
B01100110,
B01100110,
B00111110
},{
B00000000,
B00000000,
B00000000,
B00111100,
B01100110,
B01111110,
B01100000,
B00111100
},{
B00000000,
B00011100,
B00110110,
B00110000,
B00110000,
B01111100,
B00110000,
B00110000
},{
B00000000,
B00000000,
B00111110,
B01100110,
B01100110,
B00111110,
B00000110,
B00111100
},{
B00000000,
B01100000,
B01100000,
B01100000,
B01111100,
B01100110,
B01100110,
B01100110
},{
B00000000,
B00000000,
B00011000,
B00000000,
B00011000,
B00011000,
B00011000,
B00111100
},{
B00000000,
B00001100,
B00000000,
B00001100,
B00001100,
B01101100,
B01101100,
B00111000
},{
B00000000,
B01100000,
B01100000,
B01100110,
B01101100,
B01111000,
B01101100,
B01100110
},{
B00000000,
B00011000,
B00011000,
B00011000,
B00011000,
B00011000,
B00011000,
B00011000
},{
B00000000,
B00000000,
B00000000,
B01100011,
B01110111,
B01111111,
B01101011,
B01101011
},{
B00000000,
B00000000,
B00000000,
B01111100,
B01111110,
B01100110,
B01100110,
B01100110
},{
B00000000,
B00000000,
B00000000,
B00111100,
B01100110,
B01100110,
B01100110,
B00111100
},{
B00000000,
B00000000,
B01111100,
B01100110,
B01100110,
B01111100,
B01100000,
B01100000
},{
B00000000,
B00000000,
B00111100,
B01101100,
B01101100,
B00111100,
B00001101,
B00001111
},{
B00000000,
B00000000,
B00000000,
B01111100,
B01100110,
B01100110,
B01100000,
B01100000
},{
B00000000,
B00000000,
B00000000,
B00111110,
B01000000,
B00111100,
B00000010,
B01111100
},{
B00000000,
B00000000,
B00011000,
B00011000,
B01111110,
B00011000,
B00011000,
B00011000
},{
B00000000,
B00000000,
B00000000,
B01100110,
B01100110,
B01100110,
B01100110,
B00111110
},{
B00000000,
B00000000,
B00000000,
B00000000,
B01100110,
B01100110,
B00111100,
B00011000
},{
B00000000,
B00000000,
B00000000,
B01100011,
B01101011,
B01101011,
B01101011,
B00111110
},{
B00000000,
B00000000,
B00000000,
B01100110,
B00111100,
B00011000,
B00111100,
B01100110
},{
B00000000,
B00000000,
B00000000,
B01100110,
B01100110,
B00111110,
B00000110,
B00111100
},{
B00000000,
B00000000,
B00000000,
B00111100,
B00001100,
B00011000,
B00110000,
B00111100
}
};
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 < 10; i++) {
for (j = 0; j < 8; j++) {
lc.setRow(0, j, digits[i][j]);
lc.setRow(1, j, digits[i][j]);
lc.setRow(2, j, digits[i][j]);
}
delay(500);
}
delay(1000);
for (i = 0; i < 26; i++) {
for (j = 0; j < 8; j++) {
lc.setRow(0, j, chars[i+1][j]);
lc.setRow(1, j, chars[i+1][j]);
lc.setRow(2, j, chars[i+1][j]);
}
delay(500);
}
delay(1000);
for (i = 0; i < 26; i++) {
for (j = 0; j < 8; j++) {
lc.setRow(0, j, chars[i+27][j]);
lc.setRow(1, j, chars[i+27][j]);
lc.setRow(2, j, chars[i+27][j]);
}
delay(500);
}
delay(1000);
}
마지막으로, 숫자와 영문 대소문자를 각각 digits, chars 배열에 저장하여 출력하는 소스입니다. 세 번의 For문을 이용해서 숫자, 영문 대문자, 소문자를 차례로 출력하도록 했습니다. 숫자 배열의 첫 번째 항목 즉, digits[0][ ]
은 숫자 "0"이고, 마지막 항목 digits[9][ ]
는 숫자 "9"입니다. 배열 첨자와 저장된 값이 같기 때문에 For문을 이용해 반복해서 출력하기에 편리합니다.
영문자 배열 첫 번째 항목 chars[0][ ]
은 아무것도 출력하지 않는 공백입니다. 출력된 문자를 지우거나 공백 자체를 표현할 때 사용하기 위해서 추가했습니다. 따라서, 바로 이어지는 영문 대문자 26개는 chars[1][ ]
에서 chars[27][ ]
까지 저장되어 있고, 소문자는 chars[28][ ]
부터 저장되어 있습니다. 결과 화면은 생략하였습니다.
숫자, 문자 출력함수 만들기
이 글 도입부에서 언급했듯이, LedControl 라이브러리는 숫자, 문자 출력 관련 함수를 제공하지 않습니다. 출력하기 위한 패턴이 미리 저장되어 있지 않기 때문인데, 패턴을 배열로 저장하는 부분을 완성했으므로 관련 함수도 만들어 사용할 수 있습니다. 우선 숫자를 출력하는 함수를 먼저 작성하겠습니다.
void loop() {
int i;
for (i = 0; i < 8; i++) {
lc.setRow(0, i, digits[0][i]);
lc.setRow(1, i, digits[0][i]);
lc.setRow(2, i, digits[0][i]);
}
}
위 코드는 숫자 "0"을 세 개의 LED 모듈에 동일하게 출력합니다. 숫자 하나이기 때문에, "0"부터 "9"까지 반복시키는 For문은 없지만, 패턴 하나를 출력하기 위한 For문은 필요합니다. 패턴 하나를 표현하기 위해선 "0"번 행에서 "7"번 행까지 8개의 행을 모두 출력해야 하기 때문입니다. 패턴 하나 출력할 때마다 매번 For문이 나온다면 전체 소스가 상당히 길어질 텐데, 이를 함수로 처리하여 간략히 할 수 있습니다.
void loop() {
setDigits(0);
}
void setDigits(int digit) {
int i;
for (i = 0; i < 8; i++) {
lc.setRow(0, i, digits[digit][i]);
lc.setRow(1, i, digits[digit][i]);
lc.setRow(2, i, digits[digit][i]);
}
}
위 코드는 함수를 사용하여 동일한 결과를 출력합니다. 함수 이름은 setDigits()
이며, 출력할 숫자를 인수로 받습니다. loop()
함수내에서 숫자 "0"을 출력하도록 함수를 호출한 상태이며, 함수내에서 For문을 이용하여 패턴을 출력합니다.
setDigits()
함수는 출력할 숫자를 정수형 데이터(int digit
)로 넘겨 받습니다. 하지만, 이 값을 계산에 사용할 것도 아니고, "9"가 넘어가는 두 자리 이상의 숫자를 표현하는 것도 아니기 때문에 반드시 정수형 데이터일 필요는 없습니다. 게다가, 다른 영문자와 같이 처리하기 위해선 오히려 문자형(char type)일 때가 더 편리할 수도 있습니다.
void loop() {
setDigits('0');
}
void setDigits(char digit) {
int i;
int d = digit - '0';
for (i = 0; i < 8; i++) {
lc.setRow(0, i, digits[d][i]);
lc.setRow(1, i, digits[d][i]);
lc.setRow(2, i, digits[d][i]);
}
}
위 코드에서 함수 호출 부분의 인수가 작은 따옴표(')로 묶여져 있습니다. 이는 숫자가 아니라 문자 '0'을 의미하며 이에 맞춰서 함수 정의 부분도 char type으로 변경하였습니다.
함수내에서는 문자로 들어온 "0"에 맞는 배열 값을 찾아서 출력하는 부분이 필요합니다. 이전 예제에선 인수로 들어온 digit를 배열 첨자로 바로 사용할 수 있었지만, 수정된 코드에선 digit가 char type이기 때문에 첨자로 이용할 수 없습니다. char type digit변수에서 해당하는 배열 첨자를 알아내야 하는데, 이를 해결하기 위해서 ASCII 코드값을 이용하였습니다. 숫자 "0"의 ASCII 문자 코드값은 48입니다. 숫자 "1"은 49이며 1씩 증가하여 숫자 "9"는 57의 코드값을 가집니다. 이 코드값을 이용하면 적절한 배열 첨자값을 도출할 수 있습니다. 위 예제에서 인수는 "0"이며 여기서 동일한 값인 "0"을 뺏기 때문에 숫자 0의 값이 변수 d에 할당됩니다. 마찬가지로 문자 "9"의 경우, ASCII 코드값 57에서 48을 뺀 값인 9가 변수 d에 저장됩니다. 이렇게 계산하면 변수 d를 바로 배열 첨자로 사용하여 원하는 숫자를 출력할 수 있습니다.
void loop() {
setDigits(0, '0');
setDigits(1, '1');
setDigits(2, '2');
}
void setDigits(int addr, char digit) {
int i;
int d = digit - '0';
for (i = 0; i < 8; i++) {
lc.setRow(addr, i, digits[d][i]);
}
}
이 글의 예제를 테스트하기 위해 아두이노 우노 보드에 LED 모듈 3개를 연결하였습니다. 이전 예제들은 3개의 모듈에 모두 동일한 패턴을 출력하였지만, 바로 위 코드는 원하는 모듈에 출력하도록 수정된 함수를 적용하였습니다. int addr
변수는 출력할 모듈을 지정하는 값을 인수로 받습니다. 이는 setRow()
함수와 동일하게 구성한 것입니다.
void loop() {
setDigits(0, '0');
setDigits(1, '1');
setDigits(3, '2');
}
void setDigits(int addr, char digit) {
int maxDevice = lc.getDeviceCount();
if (addr < 0 || addr >= maxDevice) {
return;
}
int i;
int d = digit - '0';
for (i = 0; i < 8; i++) {
lc.setRow(addr, i, digits[d][i]);
}
}
위 코드는 동작은 동일하나 좀더 안전하게 수행될 수 있도록 몇몇 코드를 추가하였습니다. 연결된 LED 모듈의 개수를 벗어나는 호출이 올 경우 그냥 리턴하고 이를 위해서 getDeviceCount()
함수를 이용합니다. 위에서 언급한 바와 같이 테스트를 위해 연결된 모듈은 모두 3개입니다. 이는 LedControl 객체 인스턴스를 생성하고 초기화할 때 마지막 인수(int numDevices
)로 제공합니다. 이 인수값은 maxDevices라는 클래스 변수에 저장되며 getDeviceCount()
함수를 이용해서 참조할 수 있습니다. 클래스변수 maxDevices는 private 변수이기 때문에 직접 참조할 수 없습니다.
연결된 모듈의 수는 "3"이지만, "0"번부터 시작하기 때문에 마지막 모듈은 어드레스값이 "2"입니다. 따라서 int addr
변수의 값이 "0"보다 작거나 "3" 이상이면 범위를 벗어난 경우이므로 아무런 수행없이 그냥 return합니다.
위 코드에서, loop()
함수의 세 번째 함수 호출문은 Device 범위를 벗어난 경우이므로 결과 없이 return 되는 경우이며, 세 번째 모듈은 관련된 함수가 없으므로 그냥 비어있게 됩니다.
void loop() {
setDigits(lc, 0, '0');
setDigits(lc, 1, '1');
setDigits(lc, 2, '2');
}
void setDigits(LedControl ledctrl, int addr, char digit) {
int maxDevice = ledctrl.getDeviceCount();
if (addr < 0 || addr >= maxDevice) {
return;
}
int i;
int d = digit - '0';
for (i = 0; i < 8; i++) {
ledctrl.setRow(addr, i, digits[d][i]);
}
}
숫자 출력 함수의 인수가 하나 더 늘었습니다. LED 컨트롤러를 지정하는 인수를 첫 번째 자리에 넣었으며, 컨트롤러 이름이 변경되거나 둘 이상의 컨트롤러를 생성하여 사용하더라도 수정 없이 사용할 수 있습니다. 역시 결과는 동일합니다.
이제 영문자를 출력하는 함수를 작성하겠습니다. 영문자는 대문자와 소문자 두 가지가 존재하기 때문에 이를 구별하는 조건 체크 코드가 필요합니다. 또 출력하려는 값이 영문자가 아닌 경우에는 출력 없이 리턴할 수 있어야 합니다.
void setChars(LedControl ledctrl, int addr, char value) {
if (value >= 'A' && value <= 'Z') {
} else if (value >= 'a' && value <= 'z') {
}
}
위와 같이 IF문을 이용하여 범위 체크가 가능합니다. 각각 대문자, 소문자일 경우에만 처리하기 때문에, 범위를 벗어난 값은 처리하지 않습니다.
배열에서 대문자는 1번부터 26번까지 저장되어 있고, 소문자는 27번부터 52번까지 저장되어 있습니다. 이를 위한 처리도 숫자와 마찬가지로 ASCII 코드값을 이용하면 됩니다. 숫자는 배열 0번부터 시작했지만, 대문자는 배열 1번부터 시작하므로, 인수로 받아온 값에서 'A'를 빼고 다시 "1"을 더하면 배열첨자를 구할 수 있습니다. 'A'에서 'A'를 빼면 "0"이고, 배열에서 대문자 'A'는 1번이므로 "더하기 1"을 해주는 것입니다. 소문자는 여기서 26개 항목 뒤에 있으므로 'a'를 빼고 "27"을 더해주면 됩니다.
마찬가지로, ASCII 코드값에 의해 문자간의 크기 비교가 가능하여 위와 같은 IF문의 조건식이 가능합니다.
void loop() {
setChars(lc, 0, 'a');
setChars(lc, 1, 'A');
setChars(lc, 2, '!');
}
void setChars(LedControl ledctrl, int addr, char value) {
int i;
int c = -1;
if (value >= 'A' && value <= 'Z') {
c = value - 'A' + 1;
} else if (value >= 'a' && value <= 'z') {
c = value - 'a' + 27;
}
if (c != -1) {
for (i = 0; i < 8; i++) {
ledctrl.setRow(addr, i, chars[c][i]);
}
}
}
loop()
함수내에 3개의 함수 호출이 있습니다. 첫 번째 LED 모듈에 소문자 'a'를, 두 번째 모듈에 대문자 'A'를 출력합니다. 세 번째 모듈은 영문자가 아니므로 아무것도 출력하지 않습니다.
영문자 출력 함수에서, int i
변수는 8개의 행을 출력하기 위한 For문용으로 숫자 출력 함수와 동일합니다. 변수 int c는 배열 첨자를 저장하기 위한 변수입니다. 초기값으로 "-1"을 주었습니다. 영문 소문자와 대문자일 경우 적당한 배열값으로 대체되지만, 범위를 벗어난 입력값일 경우 그대로 "-1"을 가지게 되며 이를 체크해서 출력 없이 건너 뛸 수 있도록 구성하였습니다. 이 함수에 setDigits()
함수와 마찬가지로, device 범위를 체크하는 부분만 추가하면 완성입니다.
#include "LedControl.h"
LedControl lc = LedControl(12,11,10,3);
byte chars[][8] = {
{
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000
},{
B00111000,
B01000100,
B01000100,
B01000100,
B01000100,
B01000100,
B01000100,
B00111000
},{
B00010000,
B00110000,
B00010000,
B00010000,
B00010000,
B00010000,
B00010000,
B00111000
},{
B00111000,
B01000100,
B00000100,
B00000100,
B00001000,
B00010000,
B00100000,
B01111100
},{
B00111000,
B01000100,
B00000100,
B00011000,
B00000100,
B00000100,
B01000100,
B00111000
},{
B00000100,
B00001100,
B00010100,
B00100100,
B01000100,
B01111100,
B00000100,
B00000100
},{
B01111100,
B01000000,
B01000000,
B01111000,
B00000100,
B00000100,
B01000100,
B00111000
},{
B00111000,
B01000100,
B01000000,
B01111000,
B01000100,
B01000100,
B01000100,
B00111000
},{
B01111100,
B00000100,
B00000100,
B00001000,
B00010000,
B00100000,
B00100000,
B00100000
},{
B00111000,
B01000100,
B01000100,
B00111000,
B01000100,
B01000100,
B01000100,
B00111000
},{
B00111000,
B01000100,
B01000100,
B01000100,
B00111100,
B00000100,
B01000100,
B00111000
},{
B00000000,
B00111100,
B01100110,
B01100110,
B01111110,
B01100110,
B01100110,
B01100110
},{
B00000000,
B01111100,
B01100110,
B01100110,
B01111100,
B01100110,
B01100110,
B01111100
},{
B00000000,
B00111100,
B01100110,
B01100000,
B01100000,
B01100000,
B01100110,
B00111100
},{
B00000000,
B01111100,
B01100110,
B01100110,
B01100110,
B01100110,
B01100110,
B01111100
},{
B00000000,
B01111110,
B01100000,
B01100000,
B01111100,
B01100000,
B01100000,
B01111110
},{
B00000000,
B01111110,
B01100000,
B01100000,
B01111100,
B01100000,
B01100000,
B01100000
},{
B00000000,
B00111100,
B01100110,
B01100000,
B01100000,
B01101110,
B01100110,
B00111100
},{
B00000000,
B01100110,
B01100110,
B01100110,
B01111110,
B01100110,
B01100110,
B01100110
},{
B00000000,
B00111100,
B00011000,
B00011000,
B00011000,
B00011000,
B00011000,
B00111100
},{
B00000000,
B00011110,
B00001100,
B00001100,
B00001100,
B01101100,
B01101100,
B00111000
},{
B00000000,
B01100110,
B01101100,
B01111000,
B01110000,
B01111000,
B01101100,
B01100110
},{
B00000000,
B01100000,
B01100000,
B01100000,
B01100000,
B01100000,
B01100000,
B01111110
},{
B00000000,
B01100011,
B01110111,
B01111111,
B01101011,
B01100011,
B01100011,
B01100011
},{
B00000000,
B01100011,
B01110011,
B01111011,
B01101111,
B01100111,
B01100011,
B01100011
},{
B00000000,
B00111100,
B01100110,
B01100110,
B01100110,
B01100110,
B01100110,
B00111100
},{
B00000000,
B01111100,
B01100110,
B01100110,
B01100110,
B01111100,
B01100000,
B01100000
},{
B00000000,
B00111100,
B01100110,
B01100110,
B01100110,
B01101110,
B00111100,
B00000110
},{
B00000000,
B01111100,
B01100110,
B01100110,
B01111100,
B01111000,
B01101100,
B01100110
},{
B00000000,
B00111100,
B01100110,
B01100000,
B00111100,
B00000110,
B01100110,
B00111100
},{
B00000000,
B01111110,
B01011010,
B00011000,
B00011000,
B00011000,
B00011000,
B00011000
},{
B00000000,
B01100110,
B01100110,
B01100110,
B01100110,
B01100110,
B01100110,
B00111110
},{
B00000000,
B01100110,
B01100110,
B01100110,
B01100110,
B01100110,
B00111100,
B00011000
},{
B00000000,
B01100011,
B01100011,
B01100011,
B01101011,
B01111111,
B01110111,
B01100011
},{
B00000000,
B01100011,
B01100011,
B00110110,
B00011100,
B00110110,
B01100011,
B01100011
},{
B00000000,
B01100110,
B01100110,
B01100110,
B00111100,
B00011000,
B00011000,
B00011000
},{
B00000000,
B01111110,
B00000110,
B00001100,
B00011000,
B00110000,
B01100000,
B01111110
},{
B00000000,
B00000000,
B00000000,
B00111100,
B00000110,
B00111110,
B01100110,
B00111110
},{
B00000000,
B01100000,
B01100000,
B01100000,
B01111100,
B01100110,
B01100110,
B01111100
},{
B00000000,
B00000000,
B00000000,
B00111100,
B01100110,
B01100000,
B01100110,
B00111100
},{
B00000000,
B00000110,
B00000110,
B00000110,
B00111110,
B01100110,
B01100110,
B00111110
},{
B00000000,
B00000000,
B00000000,
B00111100,
B01100110,
B01111110,
B01100000,
B00111100
},{
B00000000,
B00011100,
B00110110,
B00110000,
B00110000,
B01111100,
B00110000,
B00110000
},{
B00000000,
B00000000,
B00111110,
B01100110,
B01100110,
B00111110,
B00000110,
B00111100
},{
B00000000,
B01100000,
B01100000,
B01100000,
B01111100,
B01100110,
B01100110,
B01100110
},{
B00000000,
B00000000,
B00011000,
B00000000,
B00011000,
B00011000,
B00011000,
B00111100
},{
B00000000,
B00001100,
B00000000,
B00001100,
B00001100,
B01101100,
B01101100,
B00111000
},{
B00000000,
B01100000,
B01100000,
B01100110,
B01101100,
B01111000,
B01101100,
B01100110
},{
B00000000,
B00011000,
B00011000,
B00011000,
B00011000,
B00011000,
B00011000,
B00011000
},{
B00000000,
B00000000,
B00000000,
B01100011,
B01110111,
B01111111,
B01101011,
B01101011
},{
B00000000,
B00000000,
B00000000,
B01111100,
B01111110,
B01100110,
B01100110,
B01100110
},{
B00000000,
B00000000,
B00000000,
B00111100,
B01100110,
B01100110,
B01100110,
B00111100
},{
B00000000,
B00000000,
B01111100,
B01100110,
B01100110,
B01111100,
B01100000,
B01100000
},{
B00000000,
B00000000,
B00111100,
B01101100,
B01101100,
B00111100,
B00001101,
B00001111
},{
B00000000,
B00000000,
B00000000,
B01111100,
B01100110,
B01100110,
B01100000,
B01100000
},{
B00000000,
B00000000,
B00000000,
B00111110,
B01000000,
B00111100,
B00000010,
B01111100
},{
B00000000,
B00000000,
B00011000,
B00011000,
B01111110,
B00011000,
B00011000,
B00011000
},{
B00000000,
B00000000,
B00000000,
B01100110,
B01100110,
B01100110,
B01100110,
B00111110
},{
B00000000,
B00000000,
B00000000,
B00000000,
B01100110,
B01100110,
B00111100,
B00011000
},{
B00000000,
B00000000,
B00000000,
B01100011,
B01101011,
B01101011,
B01101011,
B00111110
},{
B00000000,
B00000000,
B00000000,
B01100110,
B00111100,
B00011000,
B00111100,
B01100110
},{
B00000000,
B00000000,
B00000000,
B01100110,
B01100110,
B00111110,
B00000110,
B00111100
},{
B00000000,
B00000000,
B00000000,
B00111100,
B00001100,
B00011000,
B00110000,
B00111100
}
};
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() {
setChars(lc, 0, 'a');
setChars(lc, 1, 'A');
setChars(lc, 2, '3');
}
void setChars(LedControl ledctrl, int addr, char value) {
int maxDevice = ledctrl.getDeviceCount();
if (addr < 0 || addr >= maxDevice) {
return;
}
int i;
int c = -1;
if (value >= 'A' && value <= 'Z') {
c = value - 'A' + 11;
} else if (value >= 'a' && value <= 'z') {
c = value - 'a' + 37;
} else if (value >= '0' && value <= '9') {
c = value - '0' + 1;
}
if (c != -1) {
for (i = 0; i < 8; i++) {
ledctrl.setRow(addr, i, chars[c][i]);
}
}
}
마지막으로, 숫자와 문자를 모두 하나의 함수에서 출력하도록 변경하였으며, 배열도 역시 하나로 구성하였습니다.
이상으로 숫자, 문자 출력과 관련된 내용을 마치고, 다음 글에선 문자열 스크롤 기능을 구현해 보겠습니다.