아두이노로 7 segment LED 제어하기 #2 TM1637 라이브러리 1

2018. 3. 15. 14:03

Arduino/Display

Using 7 segments LED with Arduino : 라이브러리를 활용한 예제

이전 글에서, TM1637 칩을 사용한 7 세그먼트 모듈을 소개하고 이를 아두이노에서 사용하기 위해 TM1637Display 라는 라이브러리까지 찾아 설치하였습니다. 이번 시간에는 이 라이브러리를 활용하여 실제로 구동하는 예제들을 작성해 보겠습니다.

이 라이브러리에서 제공하는 사용자 함수는 총 5개입니다. 앞으로 두 번의 연재에 걸쳐 이 함수들의 사용법에 대해 알아보겠습니다.

라이브러리의 딜레이값은 수정했나요?
void TM1637Display::bitDelay()
{
	delayMicroseconds(100);
}

이전 글에서, 이 라이브러리를 사용하기 위해 사전에 약간의 수정을 해주었습니다. 저가형 모듈과의 호환성을 위한 것이고, 예제를 진행하기 전에 꼭 처리되어야 합니다. 라이브러리 소스(TM1637Display.cpp) 파일을 열어 위와 같이 해당 코드를 찾아 수정해주세요! 원래 값 "50"을 "100"으로 고쳐주시면 됩니다.

이 라이브러리에서 제공하는 함수는 총 다섯 가지입니다.

  • setSegments() - Set the raw value of the segments of each digit
  • showNumberDec() - Display a decimal number
  • showNumberDecEx - Display a decimal number with decimal points of colon
  • setBrightness - Sets the brightness of the display
  • encodeDigit - Translate a single digit into 7 segment code

필요한 인수 등 좀 더 자세한 사항은 헤더 파일(tm1637Display.h)을 열어 보시면됩니다. 이번 글에서는 이 중 3개의 함수에 대해 알아보겠습니다.

#include <TM1637Display.h> // 헤더 파일 포함
void setup() {
  // put your setup code here, to run once:
}
void loop() {
  // put your main code here, to run repeatedly:
}

새로운 예제를 작성하기 위해, 우선 이 라이브러리를 사용하도록 헤더파일을 포함시킵니다.

#include <TM1637Display.h>
//
// Module connection pins (Digital Pins)
#define CLK 2
#define DIO 3

하드웨어 핀은 두 개이며 디지털 포트에 연결하고 선언하여 사용합니다. 여기서는 기본 예제와 동일하게 CLK(클럭)는 D2, DIO(디지털 입출력)는 D3에 연결하였습니다.

// Module connection pins (Digital Pins)
#define CLK 2
#define DIO 3
//
// 오브젝트 생성하고 초기화
TM1637Display dsp(CLK, DIO);

연결된 핀번호 정보를 가지고 해당 라이브러리의 객체를 생성합니다.

출력 밝기를 조절하는 setBrightness 함수

먼저 출력 밝기를 세팅하는 setBrightness 함수에 대해 알아 보겠습니다.

  • void setBrightness(uint8_t brightness, bool on = true);
  • 디스플레이의 밝기를 조절합니다.
  • 세팅된 값은 다음 번 출력시에 적용됩니다.
  • 첫 번째 인수는 "밝기"이며, 0부터 7까지의 숫자로 지정합니다.
  • 두 번째 인수를 이용하여 디스플레이를 켜고 끌 수 있습니다. 생략 가능합니다.
데이터를 출력하기 전에, 꼭 밝기를 먼저 세팅해야 합니다.
#include <TM1637Display.h>
// Module connection pins (Digital Pins)
#define CLK 2
#define DIO 3
// 오브젝트 생성하고 초기화
TM1637Display dsp(CLK, DIO);
//
void setup() {
}
//
void loop() {
  dsp.showNumberDec(1234);
}

우선 숫자 "1234"를 showNumberDec(1234) 함수를 이용해 출력하도록 하는 코드입니다. 하지만, 결과적으로 아무 것도 출력되지 않습니다.

사실, 출력은 되었지만 보이지 않는 상태입니다. 아래와 같이 데이터 출력 전에 먼저 세팅해주면 됩니다.

void loop() {
  dsp.setBrightness(7);
  dsp.showNumberDec(1234);
}

위와 같이 해주면 출력된 데이터를 확인할 수 있습니다.

밝기 세팅은 다음 번 출력시에 적용됩니다.
void loop() {
  dsp.setBrightness(7);
  dsp.showNumberDec(1234);
  dsp.setBrightness(0);
}

loop() 함수는 아두이노 보드를 끄기 전까지는 계속 반복합니다. 그런데, 위 코드에는 setBrightness() 함수가 두 번이나 나오지만, 밝기 변화를 볼 수 없을 겁니다. 밝기 조절은 다음 번 출력시에 적용되고, 두 번째 setBrightness() 함수 이후에 출력되는 데이터는 없기 때문입니다.

void loop() {
  dsp.setBrightness(7);
  dsp.showNumberDec(1234);
  delay(1000);
  dsp.setBrightness(0);
  dsp.showNumberDec(1234);
  delay(1000);
}

위와 같이 각각의 setBrightness() 함수 호출후에 디스플레이에 출력하도록 수정하면 프로그램이 반복되는 동안, 1초마다 깜박이듯이 밝기가 변화되는 것을 볼 수 있습니다.

밝기가 "0"이어도 꺼진 것은 아닙니다.

밝기 인수값은 "0"부터 "7"까지이며, "7"은 가장 밝고 "0"은 가장 어둡지만, "0"값이 꺼진 것을 의미하진 않습니다.

void loop() {
  for (int i = 0; i < 8; i++) {
    dsp.setBrightness(i);
    dsp.showNumberDec(1234);
    delay(1000);
  }
}

"0"부터 "7"까지 1초마다 밝기를 변화시키는 코드입니다. 총 8 단계인데, 한 단계 정도는 별 차이가 안 나네요!

두 번째 인수를 통한 디스플레이 on / off
void loop() {
  dsp.setBrightness(7, true);
  dsp.showNumberDec(1234);
  delay(1000);
  dsp.setBrightness(7, false);
  dsp.showNumberDec(1234);
  delay(1000);
}

위 코드와 같이 두 번째 인수값을 "false"로 주면, 디스플레이를 끄게 됩니다. 따라서, 위 코드는 1초마다 블링크(깜박임)하는 효과를 보여줍니다.

숫자를 출력하는 showNumberDec 함수

아래쪽 도트나 가운데 콜론은 제외하고 숫자만 출력하는 함수입니다. 출력할 데이터를 정수값으로 받기 때문에 사용하기가 쉽습니다.

  • void showNumberDec(int num, bool leading_zero = false, uint8_t length = 4, uint8_t pos = 0);
  • 첫 번째 인수(int num)로 주어지는 정수값을 숫자 그대로 출력합니다.
  • 두 번째 인수 leading_zero는 선행 숫자 "0"을 표시하는 방법입니다.
  • 세 번째 인수 length는 수정할 범위를 지정합니다.
  • 네 번째 인수 pos는 표시될 위치입니다.

예제를 통하여 하나씩 확인해 보겠습니다.

첫 번째 인수는 생략할 수 없습니다.

반대로, 첫 번째 인수만 제공해도 출력이 가능합니다. 밝기 조절을 위한 예제들에서 이미 사용했었구요!

void loop() {
  dsp.setBrightness(7);
  //
  dsp.showNumberDec(1234);
  delay(1000);
  dsp.showNumberDec(123);
  delay(1000);
  dsp.showNumberDec(12);
  delay(1000);
  dsp.showNumberDec(1);
  delay(1000);
}

1초마다 한 자리씩 줄이며 출력하는데, 다른 인수 없어도 제대로 출력됨을 확인할 수 있습니다. 여기서 사용하는 디스플레이는 총 4자리를 출력할 수 있습니다. 그보다 적은 자리를 출력할 경우 기본적으로 오른쪽 정렬을 하여 출력합니다. 즉, 일반적인 숫자 표기 방식처럼 오른쪽 마지막 숫자가 오른쪽 마지막 자리에 표시됩니다.

위 코드는 출력 데이터가 "1234"에서 "1"까지 한 자리씩 줄어듭니다. 예제에서 처음 "1234"를 출력한 후 "123"을 출력할 때, 출력하는 데이터가 네 자리에서 세 자리로 줄었으므로, 줄어든 한 자리(여기서는 왼쪽 첫 째자리)는 그대로 남아있을 것같지만 지워져서 공백 상태가 됩니다.

위 예제를 실행해보면 showNumberDec() 함수가 호출될 때마다 이전 데이터가 지워지는 것을 확인할 수 있는데, 이 현상은 세 번째 인수 length와 관련이 있습니다. length 인수는 수정할 범위를 지정하는데 생략할 경우 디폴트로 "4"를 값으로 받고, 이는 총 4자리를 수정 범위로 삼겠다는 의미입니다. 이 모듈의 총 자릿수가 4자리이므로 결국 매번 함수가 호출될 때마다 전체 화면이 새로 쓰여지는 결과가 됩니다. 만약, 세 번째 인수를 "3", "2", "1"중 하나로 제공하면 해당 숫자만큼만 새로 쓰여지고 남은 자리는 기존에 출력된 데이터가 지워지지 않고 그대로 남아있게 됩니다.

void loop() {
  dsp.setBrightness(7);
  //
  dsp.showNumberDec(77777);
  delay(1000);
}

첫 번째 인수가 정수형 데이터이지만 계산 등을 위한 일반적인 용도는 아닙니다. 단순히, 해당 자리에 어떤 숫자가 찍힐지를 알려주기 위함이죠. 예를 들어 "4321"의 숫자 "4"는 왼쪽 첫 째자리에 "4"를 출력하라는 뜻이지 4000이라는 값을 표현하는 것은 아닙니다. 따라서, 출력할 범위에 맞게 데이터의 자릿수도 맞춰주어야 합니다.  위 예제의 "77777" 처럼 범위를 넘어서는 값을 제공하면 의도치 않은 결과를 보게 됩니다. 따라서, showNumberDec(), showNumberDecEx() 함수를 사용할 경우 첫 번째 인수가 표현 범위를 넘어서지 않도록 해야 합니다. 그리고, 이 표현 범위는 세 번째 인수 length와 관련이 있구요!

두 번째 인수를 통하여 선행 숫자 "0"의 출력 방법을 구분합니다.
void loop() {
  dsp.setBrightness(7);
  //
  dsp.showNumberDec(1234);
  delay(1000);
  dsp.showNumberDec(123, true);
  delay(1000);
  dsp.showNumberDec(12, true);
  delay(1000);
  dsp.showNumberDec(1, true);
  delay(1000);
}

"leading zero"는 자릿수를 맞추기 위해 숫자 앞에 붙이는 "0"을 의미합니다. 위 코드를 실행하면 "1234", "0123", "0012", "0001" 이렇게 숫자가 오른쪽에 맞춰지면서 앞 쪽 빈 자리는 숫자 "0"으로 채웁니다. 디폴트는 "false"이므로 생략할 경우, "0"은 출력하지 않고 공백으로 남습니다. 이전에 실행해본 예제가 여기에 해당됩니다.

세 번째 인수(length)를 통하여 출력할 범위를 지정할 수 있습니다.

디폴트 값은 "4"입니다. 모듈이 총 4자리이므로 기본적으로 모든 자리가 변경됩니다. 만약, 세 번째 인수를 통하여 출력될 자릿수를 지정했다면, 그에 맞게 출력할 데이터의 자릿수도 범위내로 제공하시기 바랍니다.

void loop() {
  dsp.setBrightness(7);
  //
  dsp.showNumberDec(7777);
  delay(1000);
  dsp.showNumberDec(234, false, 3);
  delay(1000);
  dsp.showNumberDec(23, false, 3);
  delay(1000);
  dsp.showNumberDec(2, false, 3);
  delay(1000);
}

위 코드와 같이 세 번째 인수 "length"를 3으로 지정하면 처음부터 3자리까지만 출력합니다. 마지막 네 번째 자리는 수정하지 않기 때문에 이전 출력된 데이터가 그대로 있게 됩니다. 위 소스를 실행하면, 처음에 숫자 "7"로 모두 채웁니다. 그런 후에, 앞 쪽 3자리만 차례로 "234", "23", "2"가 출력되고, 마지막 자리는 수정하지 않아서 그대로 "7"이 출력된 상태로 남아있습니다. 여기서 두 번째 인수를 "true"로 주면 앞쪽 빈 자리는 "0"으로 채워집니다.

void loop() {
  dsp.setBrightness(7);
  //
  dsp.showNumberDec(7777);
  delay(1000);
  dsp.showNumberDec(23, false, 2);
  delay(1000);
  dsp.showNumberDec(2, false, 2);
  delay(1000);
}

위 코드는 출력 범위를 2자리로 지정했기 때문에, 오른 쪽(끝 쪽) 두 자리는 처음 출력한 "77"이 그대로 남고 앞 쪽 부분만 변경됩니다. 만약, 다시 인수를 "1"로 변경하여 실행한다면 첫째 자리만 변경되고 나머지는 "777"로 되겠지요!

네 번째 인수 "pos"는 출력을 시작할 위치를 지정합니다.

네 번째 인수를 통하여, "0"에서 "3"까지의 숫자로 출력을 시작할 위치를 지정할 수 있습니다. "0"은 첫 번째 자리이며 순서대로 할당하여 "3"은 마지막 네 번째 자리입니다.

void loop() {
  dsp.setBrightness(7);
  //
  dsp.showNumberDec(4, false, 1, 3);
  delay(1000);
  dsp.showNumberDec(3, false, 1, 2);
  delay(1000);
  dsp.showNumberDec(2, false, 1, 1);
  delay(1000);
  dsp.showNumberDec(1, false, 1, 0);
  delay(1000);
  while(1); // 무한 루프
}

위 코드의 showNumberDec() 함수는 세 번째 인수가 모두 숫자 "1"로 동일합니다. 따라서, 한 자리만 출력합니다.

첫 번째 출력 함수의 마지막 인수는 "3"이고, 따라서 오른쪽 끝자리에 "4"를 출력합니다. 두 번째 출력 함수는 숫자 "3"을 출력하는데, 역시 한 자리만이고, 시작 위치는 "2"이므로 앞에서 세 번째 위치입니다. 여기까지 출력된 내용은 "34"가 오른쪽에 정렬되어 출력되었을 겁니다.

결국, "1234"를 "4"부터 시작해서 앞 쪽으로 차례로 한 자리씩 출력하는 소스입니다. 위 코드에서 세 번째 인수를 "1"로 준 것은 한 자리씩만 출력한다는 뜻입니다. "한 자리"를 출력하면 나머지 다른 세 자리는 건들지 않게 되고, 이미 출력되어있는 값이 그대로 유지됩니다. 그래서, 위 코드의 마지막 행(무한루프를 위한 while문)을 생략한다면 화면에 "1234"가 출력된 후 아무런 변화가 없는 듯 보이게 됩니다. 다른 자리는 건드리지 않고 계속 같은 자리에 같은 숫자만 출력하기 때문입니다.

void loop() {
  dsp.setBrightness(7);
  //
  dsp.showNumberDec(7777, false, 4, 0);
  delay(1000);
  dsp.showNumberDec(22, false, 2, 1);
  delay(1000);
  while(1); // 무한 루프
}

위 코드는 우선 "7777"을 4자리에 걸쳐서 첫 번째부터 찍고, "22"를 두 자리에 걸쳐서 두 번째 자리부터 찍습니다. 즉, 가운데 두 자리만 "22"로 바꾼다는 의미입니다.

#include <TM1637Display.h>
// Module connection pins (Digital Pins)
#define CLK 2
#define DIO 3
// 오브젝트 생성하고 초기화
TM1637Display dsp(CLK, DIO);
//
void setup() {
  dsp.setBrightness(7);
}
//
void loop() {
  dsp.showNumberDec(1);
  delay(1000);
  dsp.showNumberDec(2, false, 1, 2);
  delay(1000);
  dsp.showNumberDec(3, false, 1, 1);
  delay(1000);
  dsp.showNumberDec(4, false, 1, 0);
  delay(1000);
  dsp.showNumberDec(1, false, 1, 0);
  delay(1000);
  dsp.showNumberDec(2, false, 1, 1);
  delay(1000);
  dsp.showNumberDec(3, false, 1, 2);
  delay(1000);
  dsp.showNumberDec(4, false, 1, 3);
  delay(1000);
  dsp.showNumberDec(1111);
  delay(1000);
  dsp.showNumberDec(22, false, 2, 0);
  delay(1000);
  dsp.showNumberDec(33, false, 2, 1);
  delay(1000);
  dsp.showNumberDec(44, false, 2, 2);
  delay(1000);
  dsp.showNumberDec(55, false, 2, 3);
  delay(1000);
  dsp.showNumberDec(1111);
  delay(1000);
  dsp.showNumberDec(222, false, 3, 0);
  delay(1000);
  dsp.showNumberDec(333, false, 3, 1);
  delay(1000);
  dsp.showNumberDec(444, false, 3, 2);
  delay(1000);
  dsp.showNumberDec(555, false, 3, 3);
  delay(1000);
}

세 번째, 네 번째 인수를 여러가지로 변형하여 출력하는 예제입니다. 어떻게 사용되는지 아래 동영상과 같이 확인할 수 있습니다.

예제 : 카운팅 프로그램
#include <TM1637Display.h>
// Module connection pins (Digital Pins)
#define CLK 2
#define DIO 3
// 오브젝트 생성하고 초기화
TM1637Display dsp(CLK, DIO);
void setup() {
}
//
void loop() {
  dsp.setBrightness(7);
  //
  int cnt3 = 1;
  int cnt2 = 0;
  int cnt1 = 0;
  int cnt0 = 0;
  //
  unsigned long cTime = millis();
  unsigned long rTime = 0;
  //
  while(1) {
    cTime = millis();
    if (cTime - rTime >= 100) {
      dsp.showNumberDec(cnt3, false, 1, 3);
      cnt3++;
      rTime = cTime;
    }
    if (cnt3 >= 10) {
      cnt2++;
      dsp.showNumberDec(cnt2, false, 1, 2);
      cnt3 = 0;
    }
    if (cnt2 >= 10) {
      cnt1++;
      dsp.showNumberDec(cnt1, false, 1, 1);
      cnt2 = 0;
    }
    if (cnt1 >= 10) {
      cnt0++;
      dsp.showNumberDec(cnt0, false, 1, 0);
      cnt1 = 0;
    }
  }
}

"1"부터 시작해서 10분의 1초 단위로 카운트를 증가시키고, 이 값을 디스플레이에 출력하는 소스입니다. 간단한 테스트를 위해 999초(화면 상 9999) 넘어가는 부분은 따로 처리하지 않았습니다.

위 예제에 대한 결과 화면이고, 중간 부분은 빠르게 돌렸습니다.

나머지 함수들에 대해선 다음 글에서 다루도록 하겠습니다. 이상입니다.

0 Comments