YOGYUI

Adafruit HT16K33 Backpack + LED Display (14-segment) 본문

Hardware/Arduino

Adafruit HT16K33 Backpack + LED Display (14-segment)

요겨 2021. 1. 28. 15:48
반응형

1. Hardware

Adafruit HT16K33 14-Segment LED Backpack + LED

HOLTEK사의 LED Controller Driver IC인 HT16K33을 탑재한 개발용 보드

HT16K33 Datasheet

HT16K33 Features

IC 내부에 128bit 메모리를 갖고 있으며, I2C 인터페이스로 MCU 등과 통신할 수 있다 (LED 밝기 제어도 가능)

단순한 7-segment LED 뿐만 아니라, 14-segment LED, LED Matrix 등 다양한 종류의 LED 디스플레이 모듈을 제어할 수 있다

내가 구매한 LED 모듈은 "Quad Alphanumeric, Pure Green" 제품이다 (녹색, 4 Character)
backpack pcb와 함께 구매, under $14

구매 페이지

동작 예시

2. Arduino Practice

Adafruit은 거의 모든 제품군에 대한 아두이노용 라이브러리 및 예제파일들을 제공한다

아두이노 IDE 라이브러리 매니저에서 "Adafruit LED Backpack Library" 설치
(함께 설치해야 하는 Library들도 모두 설치)

Arduino - Adafruit LED Backpack Library

LED Backpack Library Source Code (Git)

 

Arduino Micro를 사용해 간단한 실습을 진행해보자

실습을 위한 배선

Arduino의 기본 I2C 라이브러리 Wire를 사용하기 때문에 데이터 라인(SDA)는 2번 핀에, 클럭 라인(SCL)은 3번 핀에 연결해주면 준비는 끝난다 (5V 전원 사용에, I2C 전압 레벨도 5V기 때문에 VI2C, VCC 모두 5V에 연결)

Wire 라이브러리 사용 시 I2C 핀아웃, Arduino Micro는 Leonardo 핀맵을 따르면 된다

 

14-Segment 한개의 bit-mask은 다음과 같음을 알아두면 segment별로 on/off하는 코드를 짤 수 있다

(우측 하단 점=DP까지 포함해서 총 15bit 제어 가능)

segment bit mask, 출처: adafruit

4글자이기 때문에 Adafruit_AlphaNum4 객체를 사용한다

Raw Bit로 On/Off 여부는 writeDigitRaw 메서드를 사용하면 된다 (HT16K33 내부 메모리에 값 업로드)

// Adafruit_LEDBackpack.cpp
void Adafruit_AlphaNum4::writeDigitRaw(uint8_t n, uint16_t bitmask) {
    displaybuffer[n] = bitmask;
}

첫번째 인자는 LED 인덱스 (몇번째 글자인지, 범위 = 0 ~ 3), 두번째 인자는 16비트 bitmask로 on/off할 segment에 대한 값을 써주면 된다

writeDigitRaw 후 writeDisplay를 하면 HT16K33가 실제로 LED에 Display하게 된다

다음과 같이 숫자 1, 2, 3, 4를 디스플레이해보자

// test1.ino
#include "Adafruit_LEDBackpack.h"

Adafruit_AlphaNum4 led = Adafruit_AlphaNum4();

void setup() {
  led.begin(0x70);
  led.writeDigitRaw(0, 0x0006);
  led.writeDigitRaw(1, 0x00DB);
  led.writeDigitRaw(2, 0x00CF);
  led.writeDigitRaw(3, 0x00E6);
  led.writeDisplay();
}

void loop() {

}

begin 메서드를 반드시 호출해줘야 한다 (Wire I2C Initialize + HT16K33 내부 오실레이터 시작)

writeDigitRaw 실습 결과

원하는 글자를 디스플레이하기 위해 매번 bit-mask를 계산해서 넣어주거나 LUT를 사용자가 직접 구현하는건 번거롭기 때문에 라이브러리는 아스키코드들에 대한 bit-mask 매핑을 내부적으로 갖고 있으며 사용자는 writeDigitAscii 메서드를 호출해서 편하게 글자를 변경할 수 있다

// Adafruit_LEDBackpack.cpp
void Adafruit_AlphaNum4::writeDigitAscii(uint8_t n, uint8_t a, bool d) {
    uint16_t font = pgm_read_word(alphafonttable + a);

    displaybuffer[n] = font;

    /*
    Serial.print(a, DEC);
    Serial.print(" / '"); Serial.write(a);
    Serial.print("' = 0x"); Serial.println(font, HEX);
    */

    if (d)
        displaybuffer[n] |= (1 << 14);
}

(세번째 boolean 인자인 d는 DP (소수점 표시용)를 켤지 여부)

alphafonttable 일부 예시는 다음과 같다 (모든 ascii code에 대한 bit-mask LUT)

// Adafruit_LEDBackpack.cpp
static const uint16_t alphafonttable[] PROGMEM = {
  /* 중략 */
  0b0000110000111111, // 0
  0b0000000000000110, // 1
  0b0000000011011011, // 2
  0b0000000010001111, // 3
  0b0000000011100110, // 4
  /* 중략 */
  0b0000000011110111, // A
  0b0001001010001111, // B
  0b0000000000111001, // C
  0b0001001000001111, // D
}

시리얼 통신으로 입력받은 글자를 디스플레이하도록 코드를 변경해보자

// test2.ino
#include "Adafruit_LEDBackpack.h"

Adafruit_AlphaNum4 led = Adafruit_AlphaNum4();
char led_buffer[4] = {' ', ' ', ' ', ' '};

void setup() {
  Serial.begin(115200);
    
  led.begin(0x70);
  led.clear();
  led.writeDisplay();
}

void loop() {
  while (true) {
    if (Serial.available()) {
      int cnt = Serial.available();       
      for (int i = 0; i < cnt; i++) {
        led_buffer[i] = Serial.read();    
      }
      for (int i = cnt; i < 4; i++) {
        led_buffer[i] = ' ';
      }

      led.clear();
      for (int i = 0; i < 4; i++) {
        led.writeDigitAscii(i, led_buffer[i]);
      }
      led.writeDisplay();
    }
  }
}

동작 예시

시리얼 통신 LED Display 예시

7-segment LED와 달리, 조약하게나마 영문 소문자도 나름 알아볼 수 있게 표현됨을 알 수 있다

writeDigitRaw 메서드를 사용해 본인만의 디스플레이 형식을 커스터마이징할 수도 있다

 

setBrightness 메서드를 사용해 LED의 밝기를 조절할 수 있다 (최대 16단계)

(begin메서드로 초기화 후 밝기는 최대(15)로 설정되기 때문에 눈이 부실 수 있다)

// test3.ino
#include "Adafruit_LEDBackpack.h"

Adafruit_AlphaNum4 led = Adafruit_AlphaNum4();

void setup() {
    led.begin(0x70);
    led.writeDigitAscii(0, '1');
    led.writeDigitAscii(1, '2');
    led.writeDigitAscii(2, '3');
    led.writeDigitAscii(3, '4');
    led.writeDisplay();
}

void loop() {
  int brightness = 0;
  while (true) {
    led.setBrightness(brightness);
    brightness += 1;
    if (brightness > 15) 
      brightness = 0;
    delay(500);
  }
}

동작 예시

LED 밝기 변경 예시

7-Segment, 14-Segment, Dot Matrix LED 등 다양한 종류의 디스플레이를 지원하며 내부 메모리를 갖고 있고 밝기 변경도 가능한 여러 특징들을 갖고 있으니깐 HT16K33 IC는 ARM, DSP, FPGA 등 다양한 임베디드 아키텍쳐에 무난히 적용할 수 있을 것으로 생각된다 (chip 단가가 $1 수준이라 약간 비싸다는게 흠...이랄까, 물론 MOQ 1000 단위에서는 $0.5 언더로 떨어지는 거 같긴 하지만~)

ARM 계열 프로젝트에 우선 사용할 것 같긴 한데, 관련 프로젝트 진행하면서 해당 IC 다루는 코드는 따로 업로드하도록 하자

끝~

반응형

'Hardware > Arduino' 카테고리의 다른 글

(CJMCU-2812-16) WS2812 RGB LED Array (x16 Ring)  (0) 2021.03.01
ArduinoJson Document - Key 존재 여부 확인  (0) 2021.02.15
ESP8266에서 MQTT 구동하기  (0) 2021.02.01
Keyes ESP8266 WiFi Module  (0) 2021.01.31
Comments