ラズパイで 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. はるき より:

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

comment

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

CAPTCHA


関連記事

ESP-WROOM-32の基本的な使い方 初期設定や書込み方法、Lチカについて画像付きで徹底解説

  この記事ではESP-WROOM-32の基本的な使い方について解説します。 ESP-WROOM-32は低価格(1000円以下)で買うことができるWiFi/Bluetoothモジュールです。 上の画像 …

RaspberryPiのセットアップ ① – 2種類のOSインストール方法と基本設定

 この記事では、私がラズパイにOSをインストールするたびに行っているRaspberryPiのセットアップについて記載します。ここでは、NOOBSとイメージファイルによる2種類のOSのインストール方法と …

1200円でカメラ、wi-fi、Bluetooth付きの激安マイコンで遊んでみた

    最近、研究室の3Dプリンターの稼働状況を監視するためにカメラを設置しようと思いたち、激安のカメラを探していました。 最初は以前こちらの記事で紹介したようにWebカメラとラズパイを用いてストリー …

Alexa,GoogleHomeでPS4を操作する

         前の記事で人生初の電子工作をしてスマートリモコンを作成し、AlexaやGoogle Assistantでテレビやエアコンなどを操作できるようになったのですが、スマートリモコンを利用し …

Google Apps Scriptを使用してスプレッドシート上の図形を押した際に、プログラムを実行させる

    大学生の電子工作 ラズパイでスマートロック作ってみた⑤の記事に関連して、スプレッドシート上に設置したボタンを押した際に Google Apps Scriptを用いたプログラムを実行することで、 …




関連記事