今回は74HC595という型番のシフトレジスタを使って、
7セグLEDを点灯させてみます。
シフトレジスタってちょっと「とっつきにくいイメージ」ありませんか??
わたしはあまりビットシフトがなんちゃらとか言われても、あまりピンときませんでした…
そんなわたしと同じような感覚でも理解できるようにまとめてみました。
最後までご覧いただければ、きっとあなたもすぐにシフトレジスタマスターです!
ちなみにYoutubeに上げていますが、完成形はこんな感じです。
Youtubeチャンネルにさまざまな動画を上げています。
↓↓↓こちらからYoutubeチャンネルにアクセス!! ↓↓↓
それでは早速以下の目次に沿って紹介していきます。
使用するもの
RaspberryPi
RaspberryPiはどのシリーズでも問題ありません。
わたしは今回RaspberryPi4B+でやってみました。
74HC595(シフトレジスタ)
何かの電子工作のキットの中に入っていたシフトレジスタです。
おそらく何かの電子工作キットを購入していたらもうすでに手元にあるかもしれません。
IC上に74CH595と印字されていたら同じものです。一度探してみましょう。
見つからなかった場合はamazonでも楽天でも購入可能です。1個当たりの単価も安いので、
なければ購入してしまうのが良いかもしれません。
7セグLED(ドット付きなので8LED)
アノードコモン、カソードコモンと実は見た目からはわかりませんが2種類あります。
コモン端子(共通端子)が、アノードか、カソードか?という違いです。
LEDの足がアノード、カソードとなっているのは知っていると思いますが、
そのアノード側が全ピン共通になっているのがアノードコモン。
カソード側が全ピン共通になっているのがカソードコモンです。
わたしの7セグはデータシートを見たところアノードコモンでした。
つまり、共通でアノードピンが一つに集約されています。
ですから、3.3Vはそのアノードコモンに挿してほかのピンにはさす必要がありません。
もしカソードコモンだったらGNDを挿す感じですね。
↓↓↓アノードコモンの7segLEDはこちら↓↓↓
↓↓↓カソードコモンの7segLEDはこちら↓↓↓
ブレッドボード
ブレッドボードは刺さればなんでも大丈夫です。
ただ、今回は配線がごちゃごちゃするので、ハーフサイズではなく、
フルサイズのブレッドボードを強くオススメします。
ちなみに、安物のブレッドボードはオススメできません。
↓↓↓以前わたしが大失敗した話↓↓↓
ジャンパーワイヤー
これがないと配線ができないので用意しましょう。
ちなみにジャンパーワイヤーは大量に安価で購入可能ですが、
以前ご紹介したように自作することもできます。
興味があればご覧くださいね。
↓↓↓ジャンパーワイヤーを自作したときの話↓↓↓
抵抗220Ω
7セグLEDはLEDが複数入ったボックスのようなものです。
ですからそれぞれに抵抗が必要になります。
RaspberryPiで制御・点灯させるならば220Ω程度で大丈夫です。
配線図
はじめに行っておきますが、
配線は結構大変です。
わたしは一度ミスってそのまま通電させてしまって、
RaspberryPi Picoを燃やしました笑
こんな感じで焦げてるのがわかりますかね??
おそらく短絡(ショート)かなにかさせて過電流が流れたようです。
配線って大事ですね….
Pythonのソースコード
import RPi.GPIO as GPIO
import time
LSBFIRST = 1
MSBFIRST = 2
# 74HC595(シフトレジスタ)のそれぞれのピンをRaspberryPiのGPIOと接続する。
dataPin = 17 #GPIO17にデータピンを設定
latchPin = 27 #GPIO27にラッチピンを設定
clockPin = 22 #GPIO22にクロックピンを設定
# この配列は左から順に0~Fまで7セグに表示させるための固有値。
num = [0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e]
def setup():
GPIO.setmode(GPIO.BCM) # GPIO番号で指定するためにBCMモードにする。
# シフトレジスタにつながっているピンをすべてOUTに設定する。
GPIO.setup(dataPin, GPIO.OUT)
GPIO.setup(latchPin, GPIO.OUT)
GPIO.setup(clockPin, GPIO.OUT)
def shiftOut(dPin,cPin,order,val):
# 7seg+1dotなので8個のLEDそれぞれのONOFFを制御する。
for i in range(0,8):
# いったんクロックピンをLOWにする。
GPIO.output(cPin,GPIO.LOW)
# 上記で決めた固有値はMSBFIRST用で決めたモノなのでMSBFIRSTしか使わない。
# LSBFIRSTだと、0と表示したいとき0xc0ではなくなる。
if(order == LSBFIRST):
GPIO.output(dPin,(0x01&(val>>i)==0x01) and GPIO.HIGH or GPIO.LOW)
elif(order == MSBFIRST):
GPIO.output(dPin,(0x80&(val<<i)==0x80) and GPIO.HIGH or GPIO.LOW)
# クロックピンをHIGHに戻す。
GPIO.output(cPin,GPIO.HIGH)
def loop():
while True:
# num(0~F)を順番に点灯させる。
for i in range(0,len(num)):
# いったんラッチピンをLOWにする。
GPIO.output(latchPin,GPIO.LOW)
# ここでshiftout関数でbyteに変換した文字列をデータピンに送る。
shiftOut(dataPin,clockPin,MSBFIRST,num[i])
# ラッチピンをHIGHに戻す。
GPIO.output(latchPin,GPIO.HIGH)
time.sleep(0.5)
# num(0~F)を点灯させ終わった後に、dotもつけた状態で再度(0~F)点灯させる。
for i in range(0,len(num)):
GPIO.output(latchPin,GPIO.LOW)
# 0x7fと論理積をとれば、かならずdotの番地が0になる→dotが光る。
shiftOut(dataPin,clockPin,MSBFIRST,num[i]&0x7f)
GPIO.output(latchPin,GPIO.HIGH)
time.sleep(0.5)
def destroy():
GPIO.cleanup()
if __name__ == '__main__': # Program starting from here
print ('Program is starting...' )
setup()
try:
loop()
except KeyboardInterrupt:
destroy()
シフトレジスタの解説
シフトレジスタを使う方法や、配線、制御方法については、
こちらの記事で解説しています。
この記事では、ビットシフトはしていません。単純にLED8個をON/OFFする実験です。
シフトレジスタの扱い方だけ理解したい人はこちらで十分かと思います。
ソースコードの解説
シフトレジスタの記事と、今回の7セグの違いはズバリ
光らせるLEDの場所の組み合わせがあらかじめ決まっている
というところです。
たとえば、0と表示させたい場合は、
GとDP以外を点灯させてあげればいいです。
ただ、わたしの7セグはアノードコモンというタイプで、
LOWにすることで点灯します。
ですから、cとd表示させるためには…
0=LOW,1=HIGHとしてあらわすと、
16進数 | DP | G | F | E | D | C | B | A | 点灯して浮かび上がる文字 |
---|---|---|---|---|---|---|---|---|---|
c6 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | c |
a1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | d |
となります。
ではここまでわかると、num配列の中身も何となくわかると思います。
このnumの配列の中身は、左から順に0~Fまで並んでいます。
あと引っかかりそうなのはここでしょうか?
elif(order == MSBFIRST):
GPIO.output(dPin,(0x80&(val<<i)==0x80) and GPIO.HIGH or GPIO.LOW)
ここではMSBFIRSTということで、
一番左のけたから順に見ていくという指定をしています。
ですから、DPのけたから見ていくということですね。
まずDPの桁が0か1かの判定を論理積&で確認しています。
ちなみに0x80は2進数で10000000なので、一番左の桁が1の場合のみ論理積は1となります。
判定をして1だった場合はHIGH=LEDOFF
0だった場合はLOW=LEDONになります。
左へビットシフトしていき、順々にAまでのON/OFFを指定していきます。
【<<】は左へビットシフトという論理演算子です。
ビットシフトについてはこちらで紹介していますのでご覧下さい。
まとめ
今回シフトレジスタを使用して7セグLEDを点灯させてみました。
LED8個ですから、別にシフトレジスタを使用する必要はないのですが、
シフトレジスタで8個制御できるということでちょうどいい数だったので挑戦してみました。
IOピンを増やす方法はシフトレジスタ以外にI2C接続でもできるので、
そちらのほうが配線もソースコードもスッキリすると予想しています。
IOエキスパンダなんて名前なのですが、一応すでに入手済みなので
ちょっといじって記事にする予定です。
コメント