使ったもの
- Raspberry Pi TypeB
- 外部接続用のPC(Mac)
- シフトレジスタ(74HC595)
- LED5本(5個しか無かった...)
- 抵抗8本
- ブレッドボード
シフトレジスタって何?
- シリアル → パラレル変換や、その逆を行う回路
- 例えば、RaspberryPi で、8個のLEDを個別にチカらせたい場合、何も考えないと、GPIOのピンを8個使うことになる
- けど、シフトレジスタ(シリアル → パラレル変換)を使えば、1つの出力からのデータ(シリアル)を複数の出力(パラレル)に変換できる
- パラレル → シリアル変換ならば、複数の入力を1つの入力に変換できる
シフトレジスタ(74HC595)の使い方
以下のPin Assignment について解説
各ピンの意味
- SI : シリアルデータを入れる所
- SCK : シフトレジスタクロック
- RCK : ラッチクロック
- QA〜QH : 出力先(8個)
- Vcc : 電源接続(5V)
- GND : グラウンドに接続
- G : Hiにすると、QA〜QHがハイインピーダンス状態(切断状態)になる
今回は未使用なので、GNDに接続 - SCLR : リセットクロック(Loにするとシフトレジスタをリセットする)
今回は未使用なので、Vccに接続 - QH' : 別の74HC595につなげることで、16ビット、24ビットと、拡張できる
使い方
- SI に1ビットのデータを入れる(Lo or Hi)
- SCK を Hi にすると、データの入力先が次のアドレスに移動する
- SI に次のアドレスのデータを入れる
- 8ビット分データを入れたら、RCK を Hi にする
- 各出力先から、SIに入力した8ビット分のデータが出力される
配線
- SI(17)、SCK(27)、RCK(22) を GPIO に接続
- QA〜QHに、発光ダイオードと、抵抗を接続
- Vcc、SCLR を Vcc に接続
- GND、G を GND に接続
こんなかんじ
Raspberry Pi 側の実装
gem pi_piper のインストール
pi_piper は、ruby から GPIO へのアクセスを楽にしてくれる gem
$ sudo apt-get install ruby-dev
$ sudo gem install pi_piper
$ gem list --local
*** LOCAL GEMS ***
ffi (1.9.3)
pi_piper (1.3.2)
ruby の実装
1個ずつLEDを光らせてみる
require 'pi_piper'
$pins = {
:ser => PiPiper::Pin.new(:pin => 17, :direction => :out), # シリアルデータ
:sck => PiPiper::Pin.new(:pin => 27, :direction => :out), # シフトレジスタクロック
:rck => PiPiper::Pin.new(:pin => 22, :direction => :out) # ラッチクロック
}
def shift(key)
$pins[key.to_sym].on
$pins[key.to_sym].off
end
def reset
$pins.values.each{|pin| pin.off }
end
def send_bits(data)
# シリアルデータを送信
0.upto(7) do |byte|
if ((1 << byte) & data) == 0
$pins[:ser].off
else
$pins[:ser].on
end
shift(:sck) # シフトレジスタクロックを送信
end
shift(:rck) # ラッチクロックを送信
end
reset
num = 1
0.upto(8) do |byte|
send_bits(num)
num = num << 1
sleep(0.5)
end
send_bits(0)
# close
reset
$pins.values.each do |pin|
File.write("/sys/class/gpio/unexport", pin.pin)
end
こんな感じに光る(地味)
バーサライトを作ってみる
LEDの残像で文字とかを表示する装置のこと
実装してみたけど、回路を振り回せないので正しく動作しているかどうかよくわからない
require 'pi_piper'
$pins = {
:ser => PiPiper::Pin.new(:pin => 17, :direction => :out), # シリアルデータ
:sck => PiPiper::Pin.new(:pin => 27, :direction => :out), # シフトレジスタクロック
:rck => PiPiper::Pin.new(:pin => 22, :direction => :out) # ラッチクロック
}
def shift(key)
$pins[key.to_sym].on
$pins[key.to_sym].off
end
def reset
$pins.values.each{|pin| pin.off }
end
def send_bits(data)
# シリアルデータを送信
0.upto(7) do |byte|
if ((1 << byte) & data) == 0
$pins[:ser].off
else
$pins[:ser].on
end
shift(:sck) # シフトレジスタクロックを送信
end
shift(:rck) # ラッチクロックを送信
end
begin
reset
data_str = <<EOS
1111111100011111100011111100011111111000
0001100000011000000011000000000011000000
0001100000011111100011111100000011000000
0001100000011000000000001100000011000000
0001100000011111100011111100000011000000
EOS
datas = data_str.split("\n").map do |str|
str.split(//).map(&:to_i)
end.transpose.map do |data|
(data.join('')+'000').to_i(2)
end
while true do
datas.each do |num|
citme = Time.now
send_bits(num)
# sleep(0.01)
end
end
catch Exception => e
p e.message
puts e.join("\n")
ensure
send_bits(0)
# close
reset
$pins.values.each do |pin|
File.write("/sys/class/gpio/unexport", pin.pin)
end
end
そんなかんじ