今日のゴール
・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に戻しておきます。
いろいろな点灯パターンをプログラミングして、パーリー感を出すと面白いです。