아두이노로 LED matrix 제어하기 #2 : LedControl Library 1

2017. 9. 19. 07:25

Arduino/Display

Arduino LedControl Library #1

이번 글부터 아두이노를 이용하여 LED matrix를 다루는 방법에 대한 연재를 시작합니다. 이전 글에서 소개한 RobotDyn의 8x8 Led matrix driver 모듈 3개를 연결하여 24x8 matrix로 실습하며, 개별 LED의 on/off에서 시작해서 숫자, 알파벳 구현 등 여러 가지로 활용해 볼 계획입니다.

Max7221 chip을 사용한 LED matrix driver module이기에 쉽게 접근이 가능하고, 케이블 연결 외엔 더 해줄 일이 없으며, arduino.cc에서 라이브러리가 제공되어 소스 코드 작성도 어렵지 않습니다.

먼저 기본 라이브러리인 LedControl에 대해서 살펴보며 연재를 시작하겠습니다.

  • Arduino UNO
  • Robotdyn LED 8x8 matrix driver module x3
  • Breadboard
  • LedControl library

보드는 아두이노 우노를 사용했고, Led module driver 3개를 브레드보드를 이용해서 연결하였습니다. 사용된 LED module에 대한 정보와 연결 구성에 대해선 이전 글(아래 링크)를 통하여 확인할 수 있습니다.

아두이노로 LED matrix 제어하기 #1

작동 확인을 위한 간단한 예제 실행

이전 글에서 연결이 완료되었으므로 테스트를 위해 라이브러리에서 제공하는 기본 예제를 하나 실행해 보겠습니다. 우선, LedControl이라는 라이브러리를 설치해야 합니다. LedControl Library는 MAX7219, 7221칩을 사용한 LED 드라이버를 구동하여 LED matrix, segment LED를 제어할 수 있습니다. 다른 유저가 만든 Custom Library라서 기본으로 설치되진 않지만, Library Manager를 통해 쉽게 설치할 수 있습니다.

아두이노 스케치를 실행한 후, 메뉴에서 Sketch, Include Library, Manage Libraries... 를 차례로 선택하면 그림과 같이 Library Manager가 나타납니다. 오른쪽 상단의 검색창에 ledcontrol을 타이핑하다 보면 LedControl 라이브러리를 쉽게 찾을 수 있습니다.

검색된 라이브러를 클릭하면 Install 버튼이 보입니다. 설치하면 라이브러리 타이틀 오른쪽으로 'INSTALLED'라고 표시됩니다.

이제 File메뉴의 Examples 항목으로 가면 예제 리스트의 아래쪽 'Examples from Custom Libraries' 섹션에 LedControl이라는 이름을 확인할 수 있습니다. 세 번째 예제 'LCDemoMatrix'를 불러옵니다.

불러온 예제입니다. 위 캡처 화면에서 보듯이, 위에서 연결한대로 D12, D11, D10번으로 핀 설정이 기본으로 돼 있기 때문에, 수정 없이 바로 실행하면 결과를 확인할 수 있습니다.

그림에서 확대한 부분의 코드를 보면, LedControl 객체 타입의 'lc' 변수를 선언하고 적절한 핀 번호로 초기화하고 있습니다. 이 때, 마지막 인수는 "1"입니다. 이 숫자는 연결된 LED 드라이버 모듈의 개수를 의미합니다. 연결에 사용한 모듈이 3개이므로 숫자 "3"으로 변경해야 하지만 그냥 수정없이 실행하였습니다.

실행한 화면입니다. 테스트를 위한 예제라서 여러 가지 패턴을 반복해서 보여주는데, 모듈 3개가 같은 결과를 보이고 있습니다. 예제 내용을 보면 첫 번째 모듈에 출력하는 코드만 있지만, 정확한 모듈의 수를 제공하지 않았을 때 나오는 현상인 듯 하고, 모듈의 숫자를 맞게 수정해주면 코드대로 첫 번째 모듈에서만 실행되는 것을 확인했습니다.

정상적으로 작동되는 것을 확인했으므로, 이제 라이브러리를 이용하여 하나씩 코드를 작성해 보겠습니다.

LedControl 라이브러리를 통한 모듈 Setup

LedControl 라이브러리는 LED module을 다루기 위한 기능들을 함수들로 제공하고 이를 이용하여 소스 코드를 구성하면 되기 때문에, 이들 함수들을 예제를 통해 하나씩 소개하며 라이브러리를 살펴 보겠습니다.

#include "LedControl.h"
LedControl lc;

아두이노 스케치를 실행하고 우선 위의 두 줄을 입력합니다. 첫 째줄은 LedControl 라이브러리를 포함시키는 include문입니다. LedControl.h는 헤더 파일이라 하며 라이브러리에서 제공하는 함수들이 미리 정의되어 있기 때문에 include시킨 후에 내가 만든 함수처럼 편하게 사용할 수 있습니다. 라이브러리가 저장되어 있는 폴더에 가보면 LedControl.h, LedControl.cpp 이렇게 두 개의 파일이 있습니다. 실제로 함수의 정의 및 구현은 .cpp 소스 파일에 기술되어 있지만, 사용자는 .h 헤더파일만 포함시키면 됩니다.

두 번째 줄은 LedControl type의 변수 lc를 선언하는 명령입니다. LedControl은 객체형(class type)으로 역시 LedControl.cpp에 정의되어 있습니다. LedControl 라이브러리내에서 Led matrix module을 다루기 위한 변수와 함수들을 묶어서 객체(class)를 만들고 LedControl이라 이름을 붙였습니다. 그리고, 이 객체 타입으로 선언하기만 하면 해당 변수와 함수들에 쉽게 접근할 수 있게 됩니다.

위 코드에서 lc는 LedControl 객체 타입의 변수로 선언되었으며, 이를 Instance라 합니다. 좀더 쉽에 생각하면, 아두이노와 물리적으로 연결된 LED matrix 모듈을 아두이노 소스상에서 가리키고 부를 수 있는 이름을 지어주는 것과 비슷합니다.

#include "LedControl.h"
LedControl lc = LedControl(12,11,10,3);

LedControl 객체를 선언하는 부분이 더 길어졌습니다. lc 변수를 선언하면서 초기화까지 같이 해주도록 변경했고 이는 라이브러리의 기본 예제 코드와 동일합니다. 초기화는 아두이노와 모듈이 어느 핀을 통해 연결되었는지, 또 직렬로 연결된 모듈의 개수가 몇 개인지 알려주는 일을 합니다.

위쪽에 링크된 모듈 리뷰글에서 이미 아두이노와의 연결에 관련해서 소개했고, 이를 변수 선언문에서 위와 같이 표현합니다. 여기서 사용하는 Robotdyn Led driver module의 기판에 표시된 라벨대로 하면 차례로 SDI, SCL, CS입니다.

마지막 인수인 숫자 "3"은 직렬로 연결된(cascaded, daisy chain) Led 드라이버 모듈의 개수입니다. 총 8개까지 연결할 수 있으며 따라서 1부터 8까지의 숫자를 입력할 수 있습니다. 1보다 작거나 8보다 큰 정수가 들어오면 최대값인 8로 세팅됩니다. 여기서는 3개의 모듈이 직렬로 연결되었다는 뜻입니다.

이제, 변수 "lc"는 아두이노 핀 D12, D11, D10에 직렬로 연결된 Led 모듈 3개를 가리키게 됩니다. 만약, 8개가 넘는 모듈을 제어하고 싶다면 아두이노와 다른 라인으로 연결하면 됩니다. 예를 들어, D8, D7, D6 번에 LED 드라이버 모듈을 연결한 후, lc2 라는 이름으로 위와 같이 선언하면 또 다른 8개의 모듈을 제어할 수 있습니다.

#include "LedControl.h"
LedControl lc = LedControl(12,11,10,3);
void setup() {
  lc.shutdown(0, false);
}

setup() 함수 이전에 처리할 내용이 더 없기 때문에 바로 setup() 함수에 대한 정의를 시작했습니다. shutdown() 함수는 power-saving mode를 제어하는 함수입니다. 사용하지 않을 때는 모듈을 off시켜 전력 소모를 줄여주는 것인데, 인수로 true를 주면 power-saving mode로 들어가서 모듈이 off되고, 다시 false를 주면 power-saving mode가 끝나고 모듈이 on이 됩니다. max7221 칩은 시작할 때(startup) 디폴트로 power-saving mode로 들어갑니다. 따라서, 위 코드와 같이 사용하기 전에 먼저 false를 주어 wake-up시켜야 합니다.

첫 번째 인수인 숫자 "0"은 모듈의 인덱스값입니다. 위에서 언급했듯이 최대 8개까지 모듈을 연결할 수 있고, "1"부터 "8"까지의 숫자로 지정할 수 있습니다. 하지만, 이를 코드상에서 지칭할 때는 "0"부터 "7"까지의 숫자로 구별합니다. 즉, 아두이노 D12, D11, D10번 핀을 통하여 연결한 8개의 모듈 중 첫 번째 모듈을 사용할 때는 숫자 "0"을, 마지막 8번째 모듈을 지칭할 때는 숫자 "7"을 지정하면 됩니다. 배열의 인덱스값과 같은 방식이라 보면 되고, 이 예제에선 3개의 모듈이기 때문에 "0, 1, 2" 세 개의 숫자로 구별하게 됩니다. 따라서, 위 코드는 연결된 첫 번째 모듈을 power-saving mode에서 해제하라는 뜻입니다.

#include "LedControl.h"
LedControl lc = LedControl(12,11,10,3);
void setup() {
  lc.shutdown(0, false);
  lc.shutdown(1, false);
  lc.shutdown(2, false);
}

연결된 모듈이 3개 이므로, 각각 숫자 0, 1, 2로 지칭하여 power-saving mode를 해제하였습니다. 객체 변수 lc가 함수 앞쪽에 기술되어 있기 때문에, 해당 모듈들만 제어할 수 있게 됩니다.

#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,8);
  lc.setIntensity(1,8);
  lc.setIntensity(2,8);
  lc.clearDisplay(0);
  lc.clearDisplay(1);
  lc.clearDisplay(2);
}

그 다음, setIntensity(), clearDisplay() 함수를 실행합니다. setIntensity()는 밝기를 지정하는 함수입니다. 0부터 15까지의 숫자를 사용하여 16단계로 지정할 수 있습니다. 숫자가 클 수록 밝아지며, 예제에선 숫자 "8"이 밝기 값입니다. 역시 첫 번째 인수는 모듈의 인덱스 번호입니다.

clearDisplay() 함수는 이름 그대로 해당 모듈의 화면을 지워줍니다. setup() 함수에서 한번 클리어 하고 시작하는 게 좋겠죠!

LED module On/Off by setLed()

위와 같이 코드 몇 줄로 setup() 함수의 내용은 다 채웠고, 이제 loop() 함수내에 실제로 Led를 켜고 끄는 코드들을 채울 차례입니다. setLed()함수는 LedControl 라이브러리에서 제공하는 함수로 개별 LED 즉, 하나의 LED를 on/off 시킬 수 있습니다.

void setLed(int addr, int row, int col, boolean state);

setLed() 함수의 호출 형식입니다. 우선, 마지막 인수 state는 LED의 on/off 상태를 지정하는 인수입니다. boolean type이기 때문에 true, false만을 값으로 가질 수 있고, true일 경우 LED on, false일 경우 반대로 LED off 명령을 내립니다.

나머지 인수는 위 그림과 같습니다. 첫 번째 인수인 addr은 int type으로 모듈의 인덱스 값을 정수형으로 제공합니다. 이미 위에서 살펴 본 내용대로, 0 ~ 7의 숫자를 이용하여 지정하고 이 예제에선 모듈이 3개이므로 0, 1, 2 세 개의 숫자중 하나를 가질 수 있습니다.

두 번째, 세 번째 인수는 모듈이 아닌 개별 LED의 주소를 행과 열로 지정합니다. 사용된 LED matrix 모듈이 8x8 즉, 8행 8열이기 때문에, 각각 "0"에서 "7"까지의 숫자값을 가질 수 있습니다. 역시 배열과 같이 "0"번부터 시작합니다.

lc.setLed(0, 0, 0, true);

위와 같이 함수를 호출한다면, 변수 lc와 연결된 첫 번째 모듈의 첫 번째 줄, 첫 번째 LED를 On 시킨다는 의미가 됩니다.

#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,8);
  lc.setIntensity(1,8);
  lc.setIntensity(2,8);
  lc.clearDisplay(0);
  lc.clearDisplay(1);
  lc.clearDisplay(2);
}
void loop() {
  lc.setLed(0, 0, 0, true);
  lc.setLed(1, 0, 0, true);
  lc.setLed(2, 0, 0, true);
}

setLed() 함수를 loop() 함수에 적용한 소스입니다. 15 ~ 17 라인과 같이 세 번 호출하도록 하였고, 모듈을 구분하는 첫 번째 인수만 다르게 입력하였습니다.

결과 화면입니다. 각  모듈의 첫 번째 LED만  On 되었습니다.

여기까지 LedControl 라이브러리에 대한 소개 및 사용 방법에 대해 소개했고, 다음 글에서는 반복문을 이용해서 움직임을 주는 소스를 작성하겠습니다. 이상입니다.

Comments