今日のゴール
・RaspberryPiにシフトレジスタ【74HC595】 を使ってLEDライトを8個つなげる
・PythonでLEDを制御してチカチカさせてみる
ダウンロードは🎥こちら
必要な道具たち
・シフトレジスタ【74HC595】
・LEDライト×8個
・抵抗×8個(一般的なLEDなら、120 〜 330オームぐらいの範囲)(私は、220オームを使用)
・ブレッドボード (2個あると、やりやすい)
・ジャンパーピン
シフトレジスタとは
ざっくりと言うと、シフトレジスタにまとまったデータ(命令)を記憶させ、一気に実行する、ようなイメージです。
今回でいうと、まとまったデータ(命令)=各LEDライトを点ける/付けない となります。
今回は、74HC595を使います。1個100円ほどで購入可能です。
下記のようなセットにも、入っています。
配線する
下記は、74HC595の各ピンの名前です。向きは、丸い窪みで判断します。
下記のようにRaspberryPiとつないでください。
74HC595の向きを間違えないようにしてください。丸い窪みが左側に来るようにしています。
クリックで大きくなります。
【74HC595】
1 QB <- - - - - - - - > + LED7 - <- - - 抵抗 - - - > GND
2 QC <- - - - - - - - > + LED6 - <- - - 抵抗 - - - > GND
3 QD <- - - - - - - - > + LED5 - <- - - 抵抗 - - - > GND
4 QE <- - - - - - - - > + LED4 - <- - - 抵抗 - - - > GND
5 QF <- - - - - - - - > + LED3 - <- - - 抵抗 - - - > GND
6 QG <- - - - - - - - > + LED2 - <- - - 抵抗 - - - > GND
7 QH <- - - - - - - - > + LED1 - <- - - 抵抗 - - - > GND
8 GND <- - - - - - - - > GND
9 QH' なし
10 SCLR <- - - - - - - - > 3.3V
11 SCK <- - - - - - - - > GPIO19 (オレンジ)
12 RCK <- - - - - - - - > GPIO20 (紫)
13 G <- - - - - - - - > GND
14 SI <- - - - - - - - > GPIO21(茶色)
15 QA <- - - - - - - - > + LED8 - <- - - 抵抗 - - - > GND
16 Vcc <- - - - - - - - > 3.3V
GPIOの番号は適宜変更しても構いません。その場合はソースコードも変更してください。
各ピンの解説
SI : シリアルデータを入れる
SCK : シフトレジスタクロック
RCK : ラッチクロック
QA〜QH : 出力先(8個)
Vcc : 電源(+)今回は3.3Vに接続
GND : グラウンド(−)
G : Hiにすると、QA〜QHがハイインピーダンス状態(切断状態)になる。今回は未使用なので、GNDに接続
SCLR : リセットクロック(Loにするとシフトレジスタをリセットする) 。今回は未使用なので、VCCに接続
QH' : 別の74HC595につなげて拡張できる
LEDをチカらせる
今回は、1番目から順番に一個づつ光らせて、パーリナイッ感を演出します。
gpioモジュールがインストールされていない場合はインストールしてください。
$ sudo apt-get install python-rpi.gpio「led.py」という名前で新しくファイルを作ります。
$ sudo vi led.py「led.py」という名前で新しくファイルを作ったら、下記のとおり、編集しましょう。
#!/usr/local/bin/python # -*- coding: utf-8 -*- import RPi.GPIO as GPIO import time interval_time = 0.5 loop_num = 3 # 各GPIOの番号 SCK = 19 RCK = 20 SI = 21 GPIO.setmode(GPIO.BCM) # 初期化 GPIO.setup(SCK, GPIO.OUT) GPIO.setup(RCK, GPIO.OUT) GPIO.setup(SI, GPIO.OUT) def reset(): GPIO.output(SCK, GPIO.LOW) GPIO.output(RCK, GPIO.LOW) GPIO.output(SI, GPIO.LOW) def shift(PIN_NUM): GPIO.output(PIN_NUM, GPIO.HIGH) GPIO.output(PIN_NUM, GPIO.LOW) def send_bits(data): for i in range(8): if ((1 << i ) & data) == 0: GPIO.output(SI, GPIO.LOW) else: GPIO.output(SI, GPIO.HIGH) shift(SCK) shift(RCK) def lighting(): reset() num = 1 for i in range(9): send_bits(num) num = num << 1 time.sleep(interval_time) send_bits(0) try: print("start") for num in range(loop_num): lighting() finally: print("finish") reset() GPIO.cleanup()
下記コマンドで実行すると、1番目のLEDから順番に光っていくのを、3回繰り返します。
interval_time を短くすると、動きが早くなります。
ダウンロードは🎥こちら
$ sudo python led.py
上記の例だと、シフト演算とか使ってて意味不明な感じです。
解説がてら、シフト演算やループ処理を使わず、ステップ実行させてみます。
#!/usr/local/bin/python # -*- coding: utf-8 -*- import RPi.GPIO as GPIO import time interval_time = 0.5 loop_num = 3 # 各GPIOの番号 SCK = 19 RCK = 20 SI = 21 GPIO.setmode(GPIO.BCM) # 初期化 GPIO.setup(SCK, GPIO.OUT) GPIO.setup(RCK, GPIO.OUT) GPIO.setup(SI, GPIO.OUT) def reset(): GPIO.output(SCK, GPIO.LOW) GPIO.output(RCK, GPIO.LOW) GPIO.output(SI, GPIO.LOW) # 次のLEDに移動 def shift_SCK(): print "SCK" GPIO.output(SCK, GPIO.HIGH) GPIO.output(SCK, GPIO.LOW) # 命令を実行 def shift_RCK(): print "RCK" GPIO.output(RCK, GPIO.HIGH) GPIO.output(RCK, GPIO.LOW) # 1番目のLEDを光らせる def send_bits_1(): print "LED1" # --- 命令をレジスタに格納(この時点ではまだ光らない) GPIO.output(SI, GPIO.HIGH) # 1番目のLED(QH)「点灯」 shift_SCK() # 次のLEDの設定に移動 GPIO.output(SI, GPIO.LOW) # 2番目のLED(QG)「消」 shift_SCK() # 次のLEDの設定に移動 GPIO.output(SI, GPIO.LOW) # 3番目のLED(QF)「消」 shift_SCK() # 次のLEDの設定に移動 GPIO.output(SI, GPIO.LOW) # 4番目のLED(QE)「消」 shift_SCK() # 次のLEDの設定に移動 GPIO.output(SI, GPIO.LOW) # 5番目のLED(QD)「消」 shift_SCK() # 次のLEDの設定に移動 GPIO.output(SI, GPIO.LOW) # 6番目のLED(QC)「消」 shift_SCK() # 次のLEDの設定に移動 GPIO.output(SI, GPIO.LOW) # 7番目のLED(QB)「消」 shift_SCK() # 次のLEDの設定に移動 GPIO.output(SI, GPIO.LOW) # 8番目のLED(QA)「消」 shift_SCK() # 次のLEDの設定に移動 # --- 命令を実行。1番目のLEDが点灯する shift_RCK() # 2番目のLEDを光らせる def send_bits_2(): print "LED2" # --- 命令をレジスタに格納(この時点ではまだ光らない) GPIO.output(SI, GPIO.LOW) # 1番目のLED「消」 shift_SCK() # 次のLEDの設定に移動 GPIO.output(SI, GPIO.HIGH) # 2番目のLED「点灯」 shift_SCK() # 次のLEDの設定に移動 GPIO.output(SI, GPIO.LOW) # 3番目のLED「消」 shift_SCK() # 次のLEDの設定に移動 GPIO.output(SI, GPIO.LOW) # 4番目のLED「消」 shift_SCK() # 次のLEDの設定に移動 GPIO.output(SI, GPIO.LOW) # 5番目のLED「消」 shift_SCK() # 次のLEDの設定に移動 GPIO.output(SI, GPIO.LOW) # 6番目のLED「消」 shift_SCK() # 次のLEDの設定に移動 GPIO.output(SI, GPIO.LOW) # 7番目のLED「消」 shift_SCK() # 次のLEDの設定に移動 GPIO.output(SI, GPIO.LOW) # 8番目のLED「消」 shift_SCK() # 次のLEDの設定に移動 # --- 命令を実行。2番目のLEDが点灯する shift_RCK() # 3番目のLEDを光らせる def send_bits_3(): print "LED3" # --- 命令をレジスタに格納(この時点ではまだ光らない) GPIO.output(SI, GPIO.LOW) # 1番目のLED「消」 shift_SCK() # 次のLEDの設定に移動 GPIO.output(SI, GPIO.LOW) # 2番目のLED「消」 shift_SCK() # 次のLEDの設定に移動 GPIO.output(SI, GPIO.HIGH) # 3番目のLED「点灯」 shift_SCK() # 次のLEDの設定に移動 GPIO.output(SI, GPIO.LOW) # 4番目のLED「消」 shift_SCK() # 次のLEDの設定に移動 GPIO.output(SI, GPIO.LOW) # 5番目のLED「消」 shift_SCK() # 次のLEDの設定に移動 GPIO.output(SI, GPIO.LOW) # 6番目のLED「消」 shift_SCK() # 次のLEDの設定に移動 GPIO.output(SI, GPIO.LOW) # 7番目のLED「消」 shift_SCK() # 次のLEDの設定に移動 GPIO.output(SI, GPIO.LOW) # 8番目のLED「消」 shift_SCK() # 次のLEDの設定に移動 # --- 命令を実行。3番目のLEDが点灯する shift_RCK() # ---- 4番目以降は省略 ---- # # 全て消灯 def all_off(): for i in range(8): GPIO.output(SI, GPIO.LOW) shift_SCK() shift_RCK() # メインの処理 def lighting(): reset() send_bits_1() # 1番目のLED点灯 time.sleep(interval_time) send_bits_2() # 2番目のLED点灯 time.sleep(interval_time) send_bits_3() # 3番目のLED点灯 time.sleep(interval_time) # ---- 4番目以降は省略 ---- # all_off() try: print("start") for num in range(loop_num): lighting() finally: print("finish") reset() GPIO.cleanup()
簡単に使い方を解説します。
・まず、出力先QHの値(HIGH or LOWいずれか)をセットします。
・セットするときはシリアルデータ(SI)に値を入れます。
・次は、QGに入れたいです。
・SCKにHIGHを入れると次のアドレス(QG)に移動します。
・移動したら次回の処理のために、SCKをLOWに戻しておきます。
・出力先QGにデータを入れます。SIにHIGH or LOWいずれかをセットします。
・SCKにHIGHを入れ、次のアドレス(QF)に移動し、データを入れます・・・
・これを繰り返し、QAまで8個全ての値を指定したら、RCKをHIGHにします。
・RCKがLOWからHIGHに変わると、QA〜QHのデータが一括して出力されます。
・実行したら次回の処理のために、RCLをLOWに戻しておきます。
いろいろな点灯パターンをプログラミングして、パーリー感を出すと面白いです。