ESP32で7セグメントLEDを制御するには?
シフトレジスタ
ESP32で7セグメントLEDを制御する方法はいくつかあります。単純に各LEDにGPIO端子を接続して制御することもできます。ただその場合、LEDの数だけGPIO端子が必要となり、実用的ではありません。そこで今回は、「シフトレジスタ」と呼ばれるICを使ってみます。シフトレジスタを利用すれば、少ないGPIO端子で、複数のLEDの制御が可能になります。
シフトレジスタとは、0と1の信号を一定の方向に順番に移動(シフト)させることができる電子回路の一種です。シフトレジスタは、シリアルデータをパラレルデータに変換する用途でよく使われます。たとえば、8ビットに対応したシフトレジスタであれば、8ビットのデータを1ビットずつ(シリアル)設定し、その後にすべてのデータを一度に(パラレルで)出力することができます。この仕組みを7セグメントLEDに適用すると、1ビットずつのシリアルデータで、7セグメントLEDの8つのLEDを制御できるというわけです。
SN74HC595N
SN74HC595Nという型番の8ビットのシフトレジスタを使います。このICについての詳細は、データシートを参照してください。
ピン配置は次のようになっています。
| ピン番号 | 端子名 | 入出力 | 機能 |
|---|---|---|---|
| 1~7、15 | QA~QH | O | データ出力 |
| 8 | GND | - | GND |
| 9 | QH’ | O | カスケード接続用 |
| 10 | SRCLR | I | シフトレジスタクリア |
| 11 | SRCLK | I | クロック信号 |
| 12 | RCLK | I | ラッチ信号 |
| 13 | OE | I | 出力の有効化 |
| 14 | SER | I | シリアルデータ入力 |
| 16 | VCC | - | 電源(5V) |
端子には、表のような名前がついています。QA~QHがデータ出力なので、これらのピンに、7セグメントLEDと電流制限用の抵抗を接続します。QH'は、複数のシフトレジスタをカスケード接続(数珠つなぎ)する際に使用します。ここでは、1つのICしか使わないので接続は不要です。
SER(14番ピン)がシリアルデータ入力です。このピンを使って、1ビットずつデータを入力します。
SRCLK(11番ピン)は、1ビットのデータを内部的にセットする信号です。LOWからHIGHにすると、1ビットのデータ(SERピンの状態)がセットされます。
RCLK(12番ピン)は、いわゆるラッチ信号の入力です。8ビット分のセット後に、LOWからHIGHにすると、すべてのデータがQA~QHに出力されます。
OE(13番ピン)は、LOWのときに出力が有効になります。ここでは有効のままにしますのでGNDに接続しておきます。SRCLR(10番)は、LOWにすると出力がクリアされますので、今回は、電源に接続して常にHIGHにします。
配線
今回使用した7セグメントLEDは、LN5160Aという型番のアノード・コモンのものです。
前述のピン配置図のとおり、ピンの3番または8番ピンが共通のアノード端子になっているので、このピンを電源の+5Vに接続します。残りのピンに、抵抗を介して、74HC595のQA~QHを接続します。わかりやすいように、7セグメントLEDの1番ピン(カソード e)を、74HC595のQE(5番ピン)というように、a~hを合わせて接続します。
電流制限用の抵抗は、ここでは330Ωとしました。SN74HC595Nのデータシートには、出力ピン1つあたり35mA以下、かつ全体で70mA以下の電流にするように書かれています。LN5160Aの順方向電圧降下Vfは、2.1Vなので、次のような計算になります(8つのLEDを同時に点灯した場合)。
(5V - 2.1V)/(70mA / 8本)= 331Ω
※(電源電圧 – 順方向電圧降下)/ 順方向電流 = 制限抵抗値
SN74HC595NのSER、SRCLK、RCLKは、それぞれ、ESP32のGPIO21、22、23に接続しました。
数字を表示する
次に、プログラムを作成しましょう。じつは.NET nanoFrameworkには、SN74HC595N用のクラスが提供されており、シフトレジスタ内部の動作を知らなくても、かんたんに利用できるようになっています。.NET nanoFrameworkのブランクプロジェクトを新規作成後、NuGetパッケージマネージャで、nanoFramework.Iot.Device.Sn74hc595パッケージをあらかじめインストールしておきます。
数字の0~9を順番に表示するプログラムは、次のようになります。
public static void Main()
{
// dp g f e d c b a(4)
byte[] bitp = {
0b_1100_0000, // 0
0b_1111_1001, // 1
0b_1010_0100, // 2
0b_1011_0000, // 3
0b_1001_1001, // 4
0b_1001_0010, // 5
0b_1000_0010, // 6
0b_1111_1000, // 7
0b_1000_0000, // 8
0b_1001_0000, // 9
};
// SER、SRCLK、RCLKを指定してSn74hc595オブジェクトを生成する(1)
using Sn74hc595 sr = new(new Sn74hc595PinMapping(21, 22, 23));
// すべて消灯(2)
sr.ShiftByte(0b_11111111);
while (true)
{
// 1秒ごとに0~9の順に表示する(3)
foreach (byte b in bitp)
{
sr.ShiftByte(b);
Thread.Sleep(1000);
}
}
}
Sn74hc595PinMappingは、SER、SRCLK、RCLKを、それぞれESP32のどのピンに設定するかを指定するオブジェクトです。前述のとおり、GPIO21、22、23を指定します(1)。
Sn74hc595クラスのShiftByte()メソッドが、SN74HC595Nに8ビット(1バイト)のデータを送るメソッドです。まず、すべてのLEDを消灯します(2)。一見すると、反対のビットを指定していると思うかもしれません。ここでの7セグメントLEDは、アノードコモンなので、ビットが1、つまり出力がHIGHのときに、LEDが消えている状態で、出力がLOWのときに点灯します。したがって、0b_11111111を設定すると、各LEDすべてが消灯になります。
次に数字の出力です(3)。これは、数字の表示となるようなビットパターン(4)をShiftByte()メソッドで送信します。
ShiftByte()メソッドに指定する値は、上位ビットから、7セグメントLEDのdp、g、f、e、d、c、b、aに対応します。たとえば、0b_1100_0000なら、dp、gが消灯、a~fが点灯となり、数字の0となります。
