2015年04月20日

RaspberryPiにシフトレジスタ【74HC595】 を使って、複数のLEDをチカチカさせてパーリィーナイしてみた【Python使用】


今日のゴール

・RaspberryPiにシフトレジスタ【74HC595】 を使ってLEDライトを8個つなげる
・PythonでLEDを制御してチカチカさせてみる



必要な道具たち

 ・シフトレジスタ【74HC595】
 ・LEDライト×8個
 ・抵抗×8個(一般的なLEDなら、120 〜 330オームぐらいの範囲)(私は、220オームを使用)
 ・ブレッドボード (2個あると、やりやすい)
 ・ジャンパーピン

シフトレジスタとは

ざっくりと言うと、シフトレジスタにまとまったデータ(命令)を記憶させ、一気に実行する、ようなイメージです。
今回でいうと、まとまったデータ(命令)=各LEDライトを点ける/付けない となります。

今回は、74HC595を使います。1個100円ほどで購入可能です。
下記のようなセットにも、入っています。


配線する

下記は、74HC595の各ピンの名前です。向きは、丸い窪みで判断します。
スクリーンショット 2015-04-20 10.53.57.png
下記のようにRaspberryPiとつないでください。
74HC595の向きを間違えないようにしてください。丸い窪みが左側に来るようにしています。 スクリーンショット 2015-04-17 11.38.44.png
クリックで大きくなります。

【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に戻しておきます。


いろいろな点灯パターンをプログラミングして、パーリー感を出すと面白いです。




posted by Raspberry Pi at 18:44 | Raspberry Pi | このブログの読者になる | 更新情報をチェックする