ラズパイで 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を使用して何かしらのデータを表示するプログラムを作ってみようかなと思っているのですが、なかなかアイデアが思い浮かばないため、何か思いついたらまた紹介します(笑)

    

参考サイト

google ads




google ads




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

執筆者:


  1. はるき より:

    こうする他ないのでしょうか❓?(笑)

はるき へ返信する コメントをキャンセル

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

CAPTCHA


関連記事

RaspberryPiのセットアップ ② – SSH,VNC(遠隔操作)の設定とファイルサーバーの設定

 この記事では、前回の記事(RaspberryPiのセットアップ ① – 2種類のOSインストール方法と基本設定)に引き続き、ラズパイを遠隔操作するためのSSH・VNCの設定方法と、パソコ …

ラズパイでスマートロック作ってみた② - 扉の開閉状況をGoogleスプレッドシートに記録

以前作成したスマートロックに、扉の開閉状況をGoogleスプレッドシートに記録する、という機能をつけたので、そのやり方について紹介します。   搭載した機能 スイッチで鍵の開閉外部サービス(Googl …

壊れたイヤホンを半田ごてを使って直してみた – 修理方法解説

   長年使用していたイヤホンが壊れてしまったので、半田ごてを使用して直してみました。この記事ではイヤホンの直し方について解説します。 (イヤホンの構造によって多少直し方は異なる場合があります。) 今 …

ラズパイに4TBの外付けHDDを接続しNAS(ファイルサーバー)を構築してみた

私は256GBのSSDが搭載されているWindowsパソコンを使用しているのですが、最近空き容量が30GBくらいになってきてしまいました。空き容量がギリギリになると色々と不具合が発生してくるとどこかで …

大学生の電子工作 ラズパイでスマートロックを自作してみた

前回、前々回に続き、3回目の電子工作です。玄関の鍵が面倒だと感じたことは誰しも一度はありますよね。鍵をかばんやポケットから取り出すのが地味にめんどくさかったり、鍵をなくしてしまって困ってしまったという …




関連記事