Arduino

16×8マトリクスLEDドライバモジュール(HT16K33)を使って7セグを表示する

以前には7セグメントドライバIC(TC4511BP)を使って7セグを表示する方法についてご紹介しました。これは、7セグ表示に特化した部品であるため、プログラムに予め表示する数字を用意する必要がなかったり、必要な端子数を抑えられる、7セグLEDの電流について考慮する必要がないなどのメリットがありました。

しかし、Arduino側で異常終了するとArduinoからの通信がなくなり、LEDに表示することができなくなります。これはArduinoからICが通信を受けてそのまま7セグへ渡しているからです。

そこで、今回は 16×8マトリクスLEDドライバモジュール(HT16K33) を使って7セグを表示する回路を作成します。このモジュールについては次節をご参照ください。

16×8マトリクスLEDドライバモジュール(HT16K33)

16×8マトリクスLEDドライバモジュール(HT16K33) とは、I2C通信を使ってLEDを点灯制御するドライバモジュールです。モジュール自体にレジスタを持っているため、データの保管ができます。そのため、Arduinoが異常終了して通信が来なくてもレジストリ内にデータがあるので7セグを表示し続けることが可能となります。

Aから始まる端子がA0~A15、Cから始まる端子がC0~C7、ArduinoとI2C通信するためのSCLとSDA、VDDとGNDの計28ピンあります。Aから始まる端子は7セグのアノード側と接続し、Cから始める端子はカソード側と接続します。

必要電源電圧は4.5~5.5Vですので、Arduinoの5Vで足ります。アドレスは、0x70です。(※HT16K33自体は表面実装部品のため、予め基盤に取り付けられた HT16K33 breakoutを使います。)

I2C通信方式

I2C通信(Inter Integrated Circuit)とは、センサーとデバイス間通信を簡略化する通信方法です。データを送受信する「SDA(Serial Data)」とセンサーとデバイスの通信タイミングを取る「SCL(Serial Clock)」を相互接続することで通信が可能となります。

制御する側(今回だとArduino)のことをI2Cマスタと呼び、制御される側(今回だとモジュール)をI2Cスレーブと呼びます。I2C通信は複数のデバイスと通信が可能となっています。そのため、それぞれのI2Cスレーブには識別するためにI2Cアドレスが用意されています。さらにデータを一時的に保管できるようにI2C通信ができるセンサにはレジスタが予め用意されています。

ArduinoでI2C通信を使う

ArduinoにはI2C通信を簡単に使うために「Wire」ライブラリが用意されています。書き方は以下を見てください。

初期設定
Wire.begin();
レジスタに書き込む
Wire.beginTransmission(I2Cアドレス);
Wire.write(書き込み先アドレス);
Wire.write(送信する値);
Wire.endTransmission();
レジスタから読み込む
Wire.beginTransmission(I2Cアドレス);
Wire.write(読み込み先アドレス);
Wire.endTransmission();
Wire.requestFrom(I2Cアドレス,バイト数);
変数 = Wire.read();

HT16K33を使って4桁の7セグを表示する

16×8マトリクスLEDドライバモジュール(HT16K33) を使って時間を表示する回路を作成しました。ただし、時間は予めプログラム上で指定した固定の時間です。

作成した回路

作成した回路は以下の図になります。

回路を作成する際に使用した装置及び部品は下表をご覧ください。

Arduino小型コンピュータ搭載のマイコン
ブレッドボード抵抗・ジャンパー線などを使って回路を作る基板
7セグLED0~9の数字を表示できるディスプレイ
16×8マトリクスLEDドライバモジュール LEDを点灯制御するドライバモジュール
ジャンパー線電気を中継する線
抵抗220Ω×8電圧を下げる端子

プログラムコード

プログラムコードは以下の通りです。

#include <Wire.h>

const int HT16K33_ADDR = 0x70;
const char seg[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
const int DIG = 5;//桁数
const int disp[] = {1,7,4,5,2};//表示する数字

void setup() {
  // put your setup code here, to run once:
  Wire.begin();
  Wire.beginTransmission(HT16K33_ADDR);
  Wire.write(0x21);
  Wire.write(0x01);
  Wire.endTransmission();
  delay(10);
  Wire.beginTransmission(HT16K33_ADDR);
  Wire.write(0x81);
  Wire.write(0x01);
  Wire.endTransmission();
  delay(10);

}

void loop() {
  // put your main code here, to run repeatedly:

  for(int i = 0;i < DIG;i++)
  {
    Wire.beginTransmission(HT16K33_ADDR);
    Wire.write(i*2);
    Wire.write(seg[disp[i]]);
    Wire.endTransmission();
    delay(10);
  }

}

setup関数内の Wire.write(0x21)は、HT16K33のクロック開始、 Wire.write(0x81)は通信開始をしていますので、おまじないみたいなものと考えてください。

宣言部分のconst int disp[] = {1,7,4,5,2};は「17時45分」を表示するために使っています。2は、「:」を表示するため指定しています。これは2を7セグ表示する際にはaとbを点灯するが、cを点灯しないため採用しています。

というのも、「:」を点灯するには上図のD1とD2だけ通電させればよいからです。D3は「°」ですので今回は不要です。

実行結果

実行結果は以下の動画をご覧ください。

まとめ

今回はI2C通信の 16×8マトリクスLEDドライバモジュール を使って7セグLEDを表示する回路を作成しました。なんといってもArduinoとの接続線がSDAとSCLの2本で済むため、使用端子を節約できて他に多くのセンサなども併用して使うことができます。

またArduino側が止まってもHT16K33側はデータを保持しているので7セグ側に影響がない点も場面によっては大きなメリットになるかと思います。

とても便利な電子部品ですので、今後も活躍する場が多くなるでしょう。

参考書籍

Arduino電子工作