HT16K33をRaspberry Piで使う

この記事は、MIDI&Audioをは無関係です。

Adafruit 8x8 Bi-Color LED MatrixをRaspberry Pi Zeroに接続し、 WiringPiライブラリを使って動作させます。Bi-Colorは、2色(赤と緑)を意味しています。 HT16K33 はLEDのドライバのチップの名前です。



HT16K33の使い方

HT16K33は緑を点灯させるレジスターと、赤を点灯させるレジスターがあります。 それぞれのレジスタは、8x8bit、すなわち8byteです。 1行が1byteに相当します。 点灯させたい時は、そのビットを1に設定し、消灯はゼロとします。 オレンジを点灯させたい時は、緑と赤を両方とも1に設定します。 例えばGndDotとRndDotをそれぞれ8x8bitのメモリとします。

uint8_t GndDot[8];  //緑の設定レジスタ
uint8_t RedDot[8];  //赤の設定レジスタ

HT16K33のレジスタ(0x00 - 0x10)に対して、緑と赤のレジスタの値を1行づつを交互に書き込んています。

void Wiringpi_HT16K33::DisplayOutput(uint8_t *GndDot, uint8_t *RndDot)
{
  uint8_t i,j;
  for(i=0,j=0; i<16; i+=2,j++){
    write8(i,   GndDot[j]);
    write8(i+1, RndDot[j]);
  }
}

下のように点灯させたいとします。これを図1とします。

図1:目的の点灯図

この場合、図1を見ながらGndDotとRedDotを次のように設定するとします。

uint8_t GrnON[8]={
  0b00000000,
  0b01111110,
  0b01000000,
  0b01000000,
  0b01000000,
  0b01000000,
  0b01111110,
  0b00000000
};

uint8_t RedON[8]={
  0b00000000,
  0b01000000,
  0b00100000,
  0b00010000,
  0b00001000,
  0b00000100,
  0b00000010,
  0b00000000
};

GrnON、RedONを上の関数で書き込むと以下のように目的の絵を180度回転させた絵になってしまいます。

図2:実際の点灯

目的の図1のように点灯させるには、図1の絵を180度回転してGndDotとRedDotを設定します。 (180度回しておけば、レジスタに書き込んだ時180度まわしてれるので元に戻ります。)


図3:図1を180度回転

uint8_t GrnON2[8]={
  0b00000000,
  0b01000010,
  0b01000010,
  0b01000010,
  0b01000010,
  0b01000010,
  0b01111110,
  0b00000000
};

uint8_t RedON2[8]={
  0b00000000,
  0b01000000,
  0b00100000,
  0b00010000,
  0b00001000,
  0b00000100,
  0b00000010,
  0b00000000
};

GrnON2、RedON2を上の関数で書き込むと以下のように図1を得ることができます。


図4:GrnON2、RedON2を表示した結果

ソフトウェア

// main.cpp
// 赤 → 緑 → オレンジ → 消灯
// の順に点灯します。
  #include <stdio.h>
  #include <stdint.h>
  #include <wiringPi.h>
  #include <wiringPiI2C.h>
  #include "Wiringpi_HT16K33.h"
  
  int main()
  {
    Wiringpi_HT16K33 ht16k33(5);
  
    while(1){
      ht16k33.allRed();
      delay(2000);
      ht16k33.allGreen();
      delay(2000);
      ht16k33.allOrange();
      delay(2000);
      ht16k33.allClear();
      delay(2000);
    }
  }
  /* 
  * Wiringpi_HT16K33.h
  * HT16k33 for using WiringPi
  * by MikataHara 
  * 2024.10.26
  */
                 
  #ifndef _WIRINGPI_HT16K33_H
  #define _WIRINGPI_HT16K33_H
  
  #include <wiringPiI2C.h>
                 
  #define HT16K33_I2CADDR_DEFAULT 0x70    ///< I2C address
                 
  /*  Class for Adafruit HT16K33 bi-Color */
                 
  class Wiringpi_HT16K33 {
    public:
      Wiringpi_HT16K33(uint8_t val);
                 
      void write(uint8_t val);
      void write8(uint8_t reg, uint8_t val);
      uint8_t read8(uint8_t reg);
                 
      void allClear();
      void allGreen();
      void allRed();
      void allOrange();
                 
    private:
      uint8_t _i2caddr;
  };
  /*
  * Wiringpi_HT16K33.cpp
  * Modified for Trinket 0by MikataHara
  * 2024.10.26
  */

  #include <stdint.h>
  #include <stdio.h>
  #include "Wiringpi_HT16K33.h"

  /* val : 輝度(0x0〜0xF) */
  Wiringpi_HT16K33::Wiringpi_HT16K33(uint8_t val)
  {
    _i2caddr = wiringPiI2CSetup(HT16K33_I2CADDR_DEFAULT);

    // オシレータを有効化
    wiringPiI2CWrite(_i2caddr, 0x21);       // 0x21: システムオシレータON

    // 表示点灯
    wiringPiI2CWrite(_i2caddr, 0x81);       // 0x81: 表示ON、ブリンクなし

    // 輝度設定
    wiringPiI2CWrite(_i2caddr, 0xE0 | val); // 0xE0 + 輝度(0x0〜0xF)
  }

  void Wiringpi_HT16K33::write(uint8_t val)
  {
    wiringPiI2CWrite(_i2caddr, val);
  }

  void Wiringpi_HT16K33::write8(uint8_t reg, uint8_t val)
  {
    wiringPiI2CWriteReg8(_i2caddr, reg, val);
  }

  uint8_t Wiringpi_HT16K33::read8(uint8_t reg)
  {
    uint16_t result = wiringPiI2CReadReg8(_i2caddr, reg);
    return result;
  }

  void Wiringpi_HT16K33::allClear()
  {
	  for(uint8_t i=0; i<16; i+=2){
		  write8(i,   0x00);
		  write8(i+1, 0x00);
	  }
  }

  void Wiringpi_HT16K33::allRed()
  {
	  for(uint8_t i=0; i<16; i+=2){
		  write8(i,   0x00);
		  write8(i+1, 0xFF);
	  }
  }

  void Wiringpi_HT16K33::allGreen()
  {
	  for(uint8_t i=0; i<16; i+=2){
  		write8(i,   0xFF);
	  	write8(i+1, 0x00);
	  }
  }

  void Wiringpi_HT16K33::allOrange()
  {
	  for(uint8_t i=0; i<16; i+=2){
		  write8(i,   0xFF);
		  write8(i+1, 0xFF);
	  }
  }