ラズパイで SPI 7セグLED Module 8 Digital を使ってみた

じょるブログ

現役理系大学生による大学生に向けた情報サイト

ラズベリーパイ 電子工作

ラズパイで SPI 7セグLED Module 8 Digital を使ってみた

投稿日:2020年5月6日 更新日:

半年ほど就活に専念するため、ブログの更新をしていませんでしたが、なんとか就活の方が落ち着いてきたのでまたブログを再開しようと思います。

就活中はブログは一時中断していましたが、電子工作の方は続けていたので、ここ半年間で行ってきた電子工作(主にスマートホーム関連)を今後少しづつ紹介していこうと思います!

   

今回は電子工作に関する記事です。

SPI通信により8つの7セグLEDを 制御できるモジュールを購入したので、この使い方について紹介します。


8桁 LED 表示管7セグメント74HC595 モジュール

    


Raspberry Pi4 ModelB 4GB ラズベリーパイ4 技適対応品

    

もともと7セグLEDの制御を行ってみようと思ていたのですが、 ロジックIC を使用せず直で扱おうとすると1個の7セグLEDに対して7つ配線を引かなければならず、複数の7セグLEDを扱おうとすると配線が複雑になり、とても面倒くさそうだったので避けていました。

そんな時にこのロジックIC( 74HC595 ) 付きの7セグLEDを見つけました。
こちらはSPI通信により、電源とグランドの2線 + 信号線3線の合計5本の線で8個の7セグLEDを制御することができます。

また、このモジュールは複数連結することもできるので、16個、24個、32個・・・と、5本の線で好きなだけ制御することができるんです!

今のところ使用する予定はないのですが衝動買いしてしまいました(笑)

購入していざ実装してみようと思ったのですが、ArduinoやC言語を使用したサンプルコードなどは見つかったのですが、ラズベリーパイを使用した例が見つからなかったので、備忘録として、ラズベリーパイとの接続方法とpythonのサンプルコードをこの記事に記載します。

  

回路図(接続方法)

回路はこんな感じです。

電源とGNDを含めた合計5つの線をつなぐだけです。

SPI通信をするにはラズベリーパイ上の専用のピンを使用しなければならないので、間違えずに配線してください。

    

プログラム・動作

まず、ラズベリーパイの設定からSPI通信を有効にします。

下図のように、「MENU(ラズベリーのマーク)」 -> 「設定」-> 「Raspberry Pi の設定」へと進みます。

  

すると、以下のような設定画面が表示されるので、「インターフェイス」のタブをクリックし、SPIの欄を有効にします。

  

以上で設定は完了です。続いてプログラムを実行します。

今回サンプルプログラムとして、以下の3つのプログラムを作成しました。

  • サンプルプログラム(0~9、A~Zを順に表示していくプログラム)
  • 時計プログラム( 現在の時刻を表示するプログラム )
  • 3分タイマープログラム(指定時間カウントダウンを行うプログラム)

各プログラムについて記載していきます。

   

・サンプルプログラム

これは、動作確認用のプログラムです。

1から9の数字が左から右へ順に表示され、一秒暗転した後、AからZのアルファベットが同様に表示されるプログラムです。

ソースコードを以下に記載します。

# coding: UTF-8

import spidev
import time


#///// SPI設定 /////
spi = spidev.SpiDev()
spi.open(0,0)
spi.max_speed_hz = 1000000


#///// 出力データ配列 /////
#数字          0     1    2    3    4    5    6    7    8    9
number_data   = [0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90]
#アルファベット   a    b    c    d    e    f    g    h    i    j    k    l    m    n    o    p    q    r    s    t    u    v    w    x    y    z
alphabet_data = [0xA0,0x83,0xa7,0xa1,0x86,0x8e,0xc2,0x8b,0xe6,0xe1,0x89,0xc7,0xaa,0xc8,0xa3,0x8c,0x98,0xce,0x9b,0x87,0xc1,0xe3,0xd5,0xb6,0x91,0xb8]
#記号等       .  ハイフン space 全埋め
symbol_data   = [0x7f,0xbf,0xff,0x00]


#///// 出力 /////
#表示リセット
for index in range(8):
    spi.xfer([0xff])
time.sleep(1)

#1-9を順に表示
for data in number_data:
    spi.xfer([data])
    time.sleep(1)

#表示リセット
for index in range(8):
    spi.xfer([0xff])
time.sleep(1)

#A-Zを順に表示
for data in alphabet_data:
    spi.xfer([data])
    time.sleep(1)

   

・時計プログラム

これは、現在の時間が表示されるプログラムです。

プログラム中の now_date の部分のコメントアウトを外し、出力データの部分を変えるとカレンダーとしても使用できます。

ソースコードを以下に記載します。

# coding: UTF-8

import spidev
import time
import datetime


#///// SPI設定 /////
spi = spidev.SpiDev()
spi.open(0,0)
spi.max_speed_hz = 1000000


#///// 文字を7セグLED用の16進数に変換する関数 /////
def chr_to_7segData(chr):
    return_data = ""
    if   chr == "0":
        return_data = 0xc0
    elif chr == "1":
        return_data = 0xf9
    elif chr == "2":
        return_data = 0xa4
    elif chr == "3":
        return_data = 0xb0
    elif chr == "4":
        return_data = 0x99
    elif chr == "5":
        return_data = 0x92
    elif chr == "6":
        return_data = 0x82
    elif chr == "7":
        return_data = 0xf8
    elif chr == "8":
        return_data = 0x80
    elif chr == "9":
        return_data = 0x90
    elif chr == "a":
        return_data = 0xA0
    elif chr == "b":
        return_data = 0x83
    elif chr == "c":
        return_data = 0xa7
    elif chr == "d":
        return_data = 0xa1
    elif chr == "e":
        return_data = 0x86
    elif chr == "f":
        return_data = 0x8e
    elif chr == "g":
        return_data = 0xc2
    elif chr == "h":
        return_data = 0x8b
    elif chr == "i":
        return_data = 0xe6
    elif chr == "j":
        return_data = 0xe1
    elif chr == "k":
        return_data = 0x89
    elif chr == "l":
        return_data = 0xc7
    elif chr == "m":
        return_data = 0xaa
    elif chr == "n":
        return_data = 0xc8
    elif chr == "o":
        return_data = 0xa3
    elif chr == "p":
        return_data = 0x8c
    elif chr == "q":
        return_data = 0x98
    elif chr == "r":
        return_data = 0xce
    elif chr == "s":
        return_data = 0x9b
    elif chr == "t":
        return_data = 0x87
    elif chr == "u":
        return_data = 0xc1
    elif chr == "v":
        return_data = 0xe3
    elif chr == "w":
        return_data = 0xd5
    elif chr == "x":
        return_data = 0xb6
    elif chr == "y":
        return_data = 0x91
    elif chr == "z":
        return_data = 0xb8
    elif chr == ".":
        return_data = 0x7f
    elif chr == "-":
        return_data = 0xbf
    elif chr == " ":
        return_data = 0xff
    else:
        return_data = 0xff
        print("error")

    return return_data


#データ出力
def send_data(data_chr):
    #表示する8文字のデータが入った配列の用意
    output_data = []
    for x in data_chr:
        Converted_data = chr_to_7segData(x)
        output_data.append(Converted_data)

    #配列を逆順にセット
    output_data.reverse() 

    #出力(SPI通信)
    for data in output_data:
        spi.xfer([data])


while True:
    output_data = []

    now = datetime.datetime.today()
    #時刻取得
    now_time = '{0:%H.%M.%S}'.format(now)
    #日付取得
    # now_date = '{0:%Y%m%d}'.format(now)

    #表示
    send_data(now_time)

    time.sleep(1)

   

・3分タイマープログラム

これは指定した時間カウントダウンを行い、最後にENDの文字を表示するプログラムです。

このプログラムでは秒を分や時に単位変換するモジュールを使用したので、実行する前に以下のコマンドで dateutil ライブラリーをインストールする必要があります。

pip install dateutils

ソースコードを以下に記載します。

# coding: UTF-8

import spidev
import time
import datetime
from dateutil.relativedelta import relativedelta


#///// SPI設定 /////
spi = spidev.SpiDev()
spi.open(0,0)
spi.max_speed_hz = 1000000


#///// 文字を7セグLED用の16進数に変換する関数 /////
def chr_to_7segData(chr):
    return_data = ""
    if   chr == "0":
        return_data = 0xc0
    elif chr == "1":
        return_data = 0xf9
    elif chr == "2":
        return_data = 0xa4
    elif chr == "3":
        return_data = 0xb0
    elif chr == "4":
        return_data = 0x99
    elif chr == "5":
        return_data = 0x92
    elif chr == "6":
        return_data = 0x82
    elif chr == "7":
        return_data = 0xf8
    elif chr == "8":
        return_data = 0x80
    elif chr == "9":
        return_data = 0x90
    elif chr == "a":
        return_data = 0xA0
    elif chr == "b":
        return_data = 0x83
    elif chr == "c":
        return_data = 0xa7
    elif chr == "d":
        return_data = 0xa1
    elif chr == "e":
        return_data = 0x86
    elif chr == "f":
        return_data = 0x8e
    elif chr == "g":
        return_data = 0xc2
    elif chr == "h":
        return_data = 0x8b
    elif chr == "i":
        return_data = 0xe6
    elif chr == "j":
        return_data = 0xe1
    elif chr == "k":
        return_data = 0x89
    elif chr == "l":
        return_data = 0xc7
    elif chr == "m":
        return_data = 0xaa
    elif chr == "n":
        return_data = 0xc8
    elif chr == "o":
        return_data = 0xa3
    elif chr == "p":
        return_data = 0x8c
    elif chr == "q":
        return_data = 0x98
    elif chr == "r":
        return_data = 0xce
    elif chr == "s":
        return_data = 0x9b
    elif chr == "t":
        return_data = 0x87
    elif chr == "u":
        return_data = 0xc1
    elif chr == "v":
        return_data = 0xe3
    elif chr == "w":
        return_data = 0xd5
    elif chr == "x":
        return_data = 0xb6
    elif chr == "y":
        return_data = 0x91
    elif chr == "z":
        return_data = 0xb8
    elif chr == ".":
        return_data = 0x7f
    elif chr == "-":
        return_data = 0xbf
    elif chr == " ":
        return_data = 0xff
    else:
        return_data = 0xff
        print("error")

    return return_data


#データ出力
def send_data(data_chr):
    #表示する8文字のデータが入った配列の用意
    output_data = []
    for x in data_chr:
        Converted_data = chr_to_7segData(x)
        output_data.append(Converted_data)

    #配列を逆順にセット
    output_data.reverse() 

    #出力(SPI通信)
    for data in output_data:
        spi.xfer([data])


set_time = 60 #秒

now_time = set_time
while True:
    
    time_str = "{0.hours:02}.{0.minutes:02}.{0.seconds:02}".format(relativedelta(seconds=now_time))
    send_data(time_str)
    time.sleep(1)
    now_time -= 1

    if now_time<=0:
        send_data("---end--")
        break

    

解説

まず、サンプルプログラムの 出力データ配列 について解説します。

このモジュールは一文字ずつしかデータを送ることはできず、その送るデータは16進数に変換して送ります。

16進数への変換方法ですが、まず光らせたいセグメントを0とし、光らせたくないセグメントを1として2進数を作ります。

例えば下図のABCDEFだけを光らせて0という文字を作りたい場合は

(HGFEDCBA)
 11000000

というようにします。

次にこれを16進数に変換します。これは10進数だと192、16進数だとc0となります。

プログラム上では16進数を表す場合は先頭に0xを付けることになっているので、0xc0 を送れば0が出力されるということになります。

このようにして、16進数を送信することで任意の文字を表示させることができます。

データの送信は

spi.xfer()

により、行うことができます。

    

次に、時計プログラムとタイマープログラムについてです。

サンプルプログラムでは一文字ずつ送信していましたが、時計やタイマーのように同じフォーマットで表示を行うには、8文字を1セットとして送信することを繰り返すことにより行います。(紛らわしい表現ですが、8文字を同時に送信するということではなく、 8文字を1文字ずつ高速で送信するという意味です。)

送信する際に配列データを反転させている理由についてですが、

このモジュールは、データを送ると下図のように一番左に新しいデータが入り、既に入っていたデータは右隣のLEDへと移動していく、という仕様になっているからです。

よって、例えば12345678というデータを順に送るとすると、全てのデータを送信した後には87654321というようにデータが逆になって表示されてしまいます。

このようにそのまま送信すると反転して表示されてしまうため、データを送信する前にデータ配列をいったん反転させてから送信しています。

  

まとめ

今回は基礎的な部分の紹介でした。冒頭でも書きましたが、このモジュールは複数連携することができるので、色々と応用できそうです!

せっかくなので、このモジュールと何かしらのAPIを使用して何かしらのデータを表示するプログラムを作ってみようかなと思っているのですが、なかなかアイデアが思い浮かばないため、何か思いついたらまた紹介します(笑)

    

参考サイト

-ラズベリーパイ, 電子工作

執筆者:


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

Alexa, Google HomeをRasberryPiと連携する

この記事ではスマートリモコンを作ってみたで作成した、スマートリモコンをAlexaやGoogle Assistantと連携するために利用した外部サービスについて記載します。     Amazon Ech …

簡単!ラズパイでスマホ広告をブロック – youtube広告も削除可能!

    ラズパイでスマホを含む家中の端末に表示されるWEB広告をブロックする方法を紹介します。 動画の最初や途中に表示されるyoutube広告を削除することも可能です! 最近ラズパイを使って何かしたい …

大学生の電子工作 スマートリモコン(プログラム)

この記事ではスマートリモコンを作ってみたで紹介したスマートリモコンのプログラムを記載していきます。回路はスマートリモコン(回路)に記載してあります。今回作成するプログラムは以下の4つです。 (LED点 …

AmazonDushボタンを改造してできること- ラズパイやIoT製品との連携方法

AmazonDushボタンはひと手間加えるだけで、IoT製品等の遠隔ボタンとして使用することができます。これにより、スマートロックと連携させダッシュボタンで鍵を開閉したり、スマートリモコンのボタンとし …

ラズパイでスマートロック作ってみた③ – AmazonDushボタンでラズパイのスマートロックを操作する

大学生の電子工作 ラズパイでスマートロック作ってみたの記事でスマートロックを作成し、現在も使用しているのですが、一つだけ問題点があります。 それは… スマホの充電が切れたら鍵が開けられなくなってしまう …