ラズパイ2023年10月更新 bookworm ⑤ 4桁7segment LED
AdafruitのStemma QT/Qwiicボードの中に、I2Cバス接続の4桁7セグメントLED表示器があります。コントローラはHT16K33です。白色をスイッチサイエンスから入手しました。Adafruitには、白色以外の色も用意されています。Stemma QT/Qwiicコネクタがついていないモデルは、アマゾンでも入手できます。
裏面のA0をショートして、スレーブ・アドレスを0x77に変更して使っています。変更前のデフォルトは0x76です。
●pythonのプログラム<step1>
I2Cバスをアクセスするsmbus2ライブラリを利用します。
1 2 3 4
5 6 7 8
9 0 - .
を7セグメントLEDに繰り返して表示します。
System Setup Registerに'0'を書き込んで、クロックを有効にします。
i2c.write_byte_data(i2c_address, HT16K33_GENERIC_SYSTEM_ON, 0)
この記述と、
i2c.write_byte(i2c_address,HT16K33_GENERIC_SYSTEM_ON)
は、同じ結果になるようです。
HT16K33のデータシートはこれですが、プログラムを記述するには足りないように思えます。検索して見つかったプログラムを参考にします。
i2c.write_byte_data(i2c_address, HT16K33_GENERIC_DISPLAY_ON, 0)
は、
i2c.write_byte(i2c_address,HT16K33_GENERIC_DISPLAY_ON)
でも、同様に動作します。
i2c.write_byte_data(i2c_address, HT16K33_GENERIC_CMD_BRIGHTNESS, 8)
は、輝度の設定です。0~15が指定でき、15が最大の明るさになります。
i2c.write_i2c_block_data(i2c_address, 0, [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00])
は、4桁のLEDを消灯します。この記述ではなく、もっと別の方法で消灯できるかもしれません。
import time i2c_address = 0x71 HT16K33_GENERIC_SYSTEM_ON = 0x21 HT16K33_GENERIC_CMD_BRIGHTNESS = 0xe0 while 1: i2c.write_byte_data(i2c_address, 0, 0x06) #1 i2c.write_byte_data(i2c_address, 0, 0x6d) #5 i2c.write_byte_data(i2c_address, 0, 0x67) #9 |
●pythonのプログラム<step2>
pythonの辞書機能を使って、
- 左からseg1、seg2、seg3、seg4と表示LEDの位置を指定でき
- 0~9はnum[x]で表示
できるプログラムです。
今、7セグメントLEDには、'5678'が表示されています。
import time i2c_address=0x71 HT16K33_GENERIC_SYSTEM_ON=0x21 HT16K33_GENERIC_CMD_BRIGHTNESS=0xe0 i2c.write_i2c_block_data(i2c_address,0,[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]) num={0:0x3f,1:0x06,2:0x5b,3:0x4f,4:0x66,5:0x6d,6:0x7d,7:0x07,8:0x7f,9:0x67} # -;0x40,dot;0x80 i2c.write_byte_data(i2c_address, seg1, num[5]) |
関数化を図ります。
作ったのは、LEDを消灯するLEDclear()、7セグメントLEDの表示桁位置と、数字を引数とするdispLED(segment,number)です。
import time i2c_address=0x71 HT16K33_GENERIC_SYSTEM_ON=0x21 HT16K33_GENERIC_CMD_BRIGHTNESS=0xe0 def LEDclear(): num={0:0x3f,1:0x06,2:0x5b,3:0x4f,4:0x66,5:0x6d,6:0x7d,7:0x07,8:0x7f,9:0x67} # -;0x40,dot;0x80 def dispLED(segment,number): #main |
実数dataを受けて表示をできるようにします。
実数を引数とするdisp7seg(data)関数です。最初に、負の数かを判断しています。負の数であれば、neg=Trueとします。
次に、小数点があるかどうかを見て、その位置dotNumPlaceを知ります。
segmentPlace=1
if neg==True:
i2c.write_byte_data(i2c_address, seg[1], 0x40)
segmentPlace=2
表示は、左詰めにしています。segmentPlace=1は一番左の桁の位置用の変数です。負の数であれば、その位置にマイナス0x40を表示します。segmentPlace=2と表示位置を進めます。
正の数であれば、segmentPlace=1のままです。
lenString= len(dataString)
実数の長さlenStringを知ります。負の数の時は、マイナスを省きます。
while lenString>0:
dispNum=dataString[mojiichi-1:mojiichi]
...
lenString=lenString-1
長さlenStringをカウンタとして利用したループです。lenStringは一つの桁を表示するとだんだん減少していきますが、最初の桁位置位置を知るためのカウンタmojiichiを用意しています。最初は'1'でループに入り、表示すると増加します。
実数を文字列とした文字列dataStringから1文字取り出して変数dispNumを得ます。
もし小数点であれば、小数点の前の文字にドットを追加して表示dispLED(segmentPlace,int(dispNum),True)します。小数点と関係ないなら、そのまま表示dispLED(segmentPlace,int(dispNum),False)します。
dispNum=dataString[mojiichi-1:mojiichi]
if dispNum==".":
mojiichi=mojiichi-1
segmentPlace=segmentPlace-1
dispNum=dataString[mojiichi-1:mojiichi]
dispLED(segmentPlace,int(dispNum),True)
mojiichi=mojiichi+1
else:
dispLED(segmentPlace,int(dispNum),False)
表示関数dispLED(segment,number,dot)の引数は、表示LEDの桁位置segment、表示する数字number、ドットの有無を示すbool変数dotです。dotがTrueであれば、表示する数字の最上位ビットを'1'にして、ドットが点灯します。
def dispLED(segment,number,dot):
if dot:
i2c.write_byte_data(i2c_address, seg[segment], num[number] +128) # |= 0x80
else:
i2c.write_byte_data(i2c_address, seg[segment], num[number])
23.4、-23.0、0、105.6を表示します。表示できる実数の範囲は制限を設けていないので、あくまでも、半導体センサが測定する温度ぐらいの表示用です。
import time i2c_address=0x71 HT16K33_GENERIC_SYSTEM_ON=0x21 HT16K33_GENERIC_CMD_BRIGHTNESS=0xe0 def clearLED(): num={0:0x3f,1:0x06,2:0x5b,3:0x4f,4:0x66,5:0x6d,6:0x7d,7:0x07,8:0x7f,9:0x67} # -;0x40,dot;0x80 def dispLED(segment,number,dot):
dataString=str(abs(data)) segmentPlace=1 while lenString>0: print("test start") clearLED() clearLED() clearLED() |
●pythonのプログラム<step3>
第4回を参照して、I2Cバスに気圧センサBME280をつなぎ、測定値の中の温度を4桁7セグメントLED表示器に表示します。
上記<step2>で作ったdisp7seg(data)関数は室温付近だと桁がオーバフローすることはありません。
第4回を参照してデバイス・ドライバを組み込んでリブートします。
組み込まれたことを確認します。0x77がUUになってます。
プログラムです。
import time i2c_address=0x71 HT16K33_GENERIC_SYSTEM_ON=0x21 HT16K33_GENERIC_CMD_BRIGHTNESS=0xe0 def clearLED(): num={0:0x3f,1:0x06,2:0x5b,3:0x4f,4:0x66,5:0x6d,6:0x7d,7:0x07,8:0x7f,9:0x67} # -;0x40,dot;0x80 def dispLED(segment,number,dot): def disp7seg(data): dataString=str(abs(data)) segmentPlace=1 while lenString>0: # main |
実行中の様子です。