Raspberry Piで秋月の7セグLEDシリアルドライバを使用する

IT

今回は秋月さんで販売されているSPI通信で操作可能な7セグをRaspberryPiで使ったみたいと思います。ちなみに、自分はプログラムは得意という感じでもないので、コードが汚かったり、良い書き方があると思いますがご了承ください。

7セグが手軽に扱えるモジュール

一般的な7セグを使用するときは、回路が複雑になりがちですが、秋月電子で販売されている、7セグメントLEDシリアルドライバキット(DIP化キット LED別売)を使うと、桁数を増やしても回路が比較的簡単に組めます。

今回使用した7セグ

今回は、最初からLEDが実装されている、
赤色7セグメントLEDシリアルドライバモジュール 完成品
を使いました。はんだ付けをする手間が省けますし、シリアルドライバモジュール+LED単体と比べると、1つ15円の差です。(これを安いと捉えるか高いと捉えるかは人次第)

1桁 0から9までのカウントアップ

回路図

RaspberryPiと7セグの接続を以下に示します。
SPI通信させますが、7セグからRaspberry Piにはデータを送らないので、MISOピンは使用しません。
電源は5Vでもいけますが、3.3Vでも問題なく動作したので、3.3Vにしました。

SPI有効化

まだRaspberry PiのSPI通信を有効化していない場合は有効化します。
以下のコマンドを入力します。

sudo raspi-config

次に、以下のように、Interfacing Optionsを矢印キーで選んでEnterします。

SPIを選びます。

Yesを選択します。

OKを選択します。

メニュー画面に戻るので、ESCキーで終了させます。

プログラム

実行方法:例えばファイル名が7seg.pyなら以下のようにして実行します。

python 7seg.py

以下のようにPythonでコードを書きました。実行すると、7セグがインクリメント(0.5秒毎)し、ループします。0,1,2・・・9→0,1,2,・・のような感じです。

import spidev
import time

dot = 0b10000000
data = [0b00111111,#0
        0b00000110,#1
        0b01011011,#2
        0b01001111,#3
        0b01100110,#4
        0b01101101,#5
        0b01111101,#6
        0b00000111,#7
        0b01111111,#8
        0b01101111]#9

spi = spidev.SpiDev()
spi.open(0,0)
spi.max_speed_hz = 1000000

while True:
    for i in range(10):
        spi.xfer([data[i]])
        time.sleep(0.5)

SPI通信させるとき、WiringPiを使おうと思ったのですが、ループ文で動きがおかしくなってしまい、時間かかったのですが、spidevを使ったことによりうまく動くようになりました。

動作ついてですが、以下のように7セグの各LEDにはアルファベットが割当てられています。秋月電子のArduinoのサンプルプログラムを見る限り、この7セグシリアルドライバに SPI 通信を用いてDP,G,F,E,D,C,B,Aの順で 0 or 1を送信すれば良さそうです。(合計8bit)
例えば、7を表示したいときは、AとBとCだけ光らせれば良いので、00000111を送信すれば良いです。

ちなみに、秋月電子のサンプルプログラムでは7のとき11100000を送っていますが、設定で最下位ビット(LSB)から送信しているので、順番的には00000111を送っていることになります。

2桁 0から99までのカウントアップ

回路図

今度は7セグを2つに増やして0から99をカウントしていくものを作ります。

前回と違う点はSDOを使う点です。SDOはデータをアウトプットするピンで、SDIはデータをインプットするピンです。(図中の注意と書いてある部分です。)
つまり、7セグ(1の位)のSDOから7セグ(10の位)のSDIに配線します。

プログラム

以下を実行すると、0.2秒ごとに0から99までのインクリメントをループします。

import spidev
import time

dot = 0b10000000
data = [0b00111111,#0
        0b00000110,#1
        0b01011011,#2
        0b01001111,#3
        0b01100110,#4
        0b01101101,#5
        0b01111101,#6
        0b00000111,#7
        0b01111111,#8
        0b01101111]#9

spi = spidev.SpiDev()
spi.open(0,0)
spi.max_speed_hz = 1000000

while True:
    for i in range(10):
        for j in range(10):
            spi.xfer([data[i]])#10
            spi.xfer([data[j]])#1
            time.sleep(0.2)

動作としては、以下のようになります。うまく説明できないので例なのですが・・

  • 現在19を表示している状態とします。ここから20に変えようとします。
  • まず、ラズパイは7セグ(1の位)に2を表示させるデータを送信します。
  • 7セグ(1の位)7セグ(10の位)に9を表示させるデータを送信し、2を表示します。
  • 7セグ(10の位)は9を表示します。
    この時点で92となります。(これは目に見えない速さ変わっているのでわからない)

  • 次に、ラズパイは7セグ(1の位)に0を表示させるデータを送信します。
  • 7セグ(1の位)7セグ(10の位)に2を表示させるデータを送信し、0を表示します。
  • 7セグ(10の位)は2を表示します。これで20となります。
    最初からここまで一瞬で処理します。
  • 0.2秒待ちます。つまり、20という状態を0.2秒間維持することによって、やっと目に20が見えます。

こんな感じで、SDOからは7セグが持っていた数字を出力しています。試しに、time.sleep文を間に噛ませると、この動作がわかりやすいと思います。

5桁にして遊ぶ

回路図

最後に5桁に挑戦してみます。回路は2桁と同じようにSDO→SDIというのだけ注意すれば組めます。

プログラム1

以下を実行すると、00000から99999までのインクリメントをループします。

import spidev
import time

dot = 0b10000000
data = [0b00111111,#0
        0b00000110,#1
        0b01011011,#2
        0b01001111,#3
        0b01100110,#4
        0b01101101,#5
        0b01111101,#6
        0b00000111,#7
        0b01111111,#8
        0b01101111]#9

spi = spidev.SpiDev()
spi.open(0,0)
spi.max_speed_hz = 1000000

while True:
    for num in range(99999):
        num=(str(num)).zfill(5)
        spi.xfer([data[int(num[-5])]])
        spi.xfer([data[int(num[-4])]])
        spi.xfer([data[int(num[-3])]])
        spi.xfer([data[int(num[-2])]])
        spi.xfer([data[int(num[-1])]])
        time.sleep(0.005)

プログラム2

以下を実行すると000.00から999.99までのインクリメントをループします。

import spidev
import time

dot = 0b10000000
data = [0b00111111,#0
        0b00000110,#1
        0b01011011,#2
        0b01001111,#3
        0b01100110,#4
        0b01101101,#5
        0b01111101,#6
        0b00000111,#7
        0b01111111,#8
        0b01101111]#9

spi = spidev.SpiDev()
spi.open(0,0)
spi.max_speed_hz = 1000000

while True:
    for num in range(99999):
        num=(str(num)).zfill(5)
        spi.xfer([data[int(num[-5])]])
        spi.xfer([data[int(num[-4])]])
        spi.xfer([data[int(num[-3])]|dot])
        spi.xfer([data[int(num[-2])]])
        spi.xfer([data[int(num[-1])]])
        time.sleep(0.005)

このプログラムで何をしたいかと言うと、

spi.xfer([data[int(num[-3])]|dot])

の部分で|dotとすれば、ドットを表示できるということを示したかっただけです。

プログラム3

以下のプログラムはユーザーから入力された値を表示します。
0~99999までなら表示します。
入力した値に対する表示例

  • 0→00000.
  • 0.00000001→0.0000
  • 1→00001.
  • 1.23456789→1.2345
  • 12.3456789→12.345
  • 0.12→000.12
  • 1234→01234.
  • 12345.6→12345.

ちなみに、自分はプログラムは得意という感じでもないので、コードが汚かったり、もう少しスマートなアルゴリズムや良い書き方があると思いますが、とりあえずこれで動いたのでご報告です。

日本語でコメント文ついていますが、実行してエラーになった場合は
「python3 ○○.py」
のようにpython3で実行してみてください。

import spidev

dot = 0b10000000
data = [0b00111111,#0
        0b00000110,#1
        0b01011011,#2
        0b01001111,#3
        0b01100110,#4
        0b01101101,#5
        0b01111101,#6
        0b00000111,#7
        0b01111111,#8
        0b01101111]#9

spi = spidev.SpiDev()
spi.open(0,0)
spi.max_speed_hz = 1000000

while True:
    number=input("input here-->")#ユーザから入力を待つ
    if  not 0 <= float(number) <= 99999:#不正な値をチェック
        print("Please enter 0~99999")
        continue
    number=number.zfill(6)#6桁に調整。例0.123456789→0.1234 例123→00123
    digit=[number[0],number[1],number[2],number[3],number[4],number[5]]#一桁ずつに分解
    for i in range(6):#dot+5桁分で6回ループ。小数点のいちを探してdot_placeに格納。
        dot_place=6#初期値は1の位の7セグに小数点が来るようにしている。整数12345の場合12345.と表示するため。
        if digit[i]==".":
            dot_place=i
            break
    for i in range(6):#表示する部分。万の位から順番に処理。
        if i==dot_place-1:#例123.45のとき、小数点の位置は左から4番目だが、3桁目のときに3と小数点を同時に送るためdot_place-1になっている。
            spi.xfer([data[int(digit[i])]|dot])#小数点付きで送信
        elif i==dot_place:#小数点は上で送信済みなので、ここは通過。
            continue
        else:
            spi.xfer([data[int(digit[i])]])#普通に送信

動作についてはコメント文を参照してください。

まとめ

秋月電子通商さんで販売されている、SPI通信で扱える7セグは配線量も少なく、プログラムもわかってしまえば、使いやすいのでおすすめです!

コメント

タイトルとURLをコピーしました