はじめに
Nerves Livebook で Raspberry Pi 用スターター電子工作キットを楽しんでいます
SunFounder Raspberry Pi 用のスターター電子工作キット
これまでの記事
- Nerves Livebook で Raspberry Pi 4 のLチカ
- Nerves Livebook + Delux で簡単Lチカ
- MacBook 上の Livebook から Raspberry Pi 上の Livebook に接続してLチカする
- Nerves Livebook から GPIO 拡張ボードの LED を点滅させる
- Nerves Livebook から RGB LED を制御する(ソフトPWMもやってみる)
- Nerves Livebook から LED 棒グラフを制御する
- Nerves Livebook でボタンとLEDを連動させる
- Nerves Livebook で 7 セグメントディスプレイに文字を表示する
この記事では 4 桁 7 セグメントディスプレイに文字を表示します
実装したノートブックはこちら
4 桁 7 セグメントディスプレイ
前回の記事で使った 7 セグメントディスプレイが 4 桁分繋がっています
前回の 7 セグメントディスプレイはカソードコモン(CC)でしたが、今回はアノードコモン(CA)になっています
逆方向になっているため、 0 で光って 1 で消えます
つまり前回は 0
の文字を 0b00111111
で表していましたが、今回は 0b11000000
で表します
また、 4 桁ありますが、実は同時に 4 桁全て光らせることはできません
一桁ずつ光らせるのを高速に切り替えることで、人の目には 4 桁同時に光っているかのように見せます
例えば 1234
と表示される場合、以下のように順に光らせています
4
3
2
1
回路の組み立て
オンライン説明書の通りに回路を組みます
ノートブックの実装
Nerves Livebook を開き、以降のコードを実行していきます
準備
ビット演算のために Bitwise
を読み込みます
import Bitwise
ピンを開く
GPIO の各ピンを出力用に開きます
まずは前回と同じシフトレジスタ 74HC595 に信号を送るためのピンを開きます
{:ok, sdi} = Circuits.GPIO.open("GPIO24", :output)
{:ok, rclk} = Circuits.GPIO.open("GPIO23", :output)
{:ok, srclk} = Circuits.GPIO.open("GPIO18", :output)
次に、光らせる桁を制御するための 4 つのピンを開きます
place_pins =
[
"SPI_MOSI",
"GPIO22",
"GPIO27",
"GPIO17"
]
|> Enum.map(fn label ->
label
|> Circuits.GPIO.open(:output)
|> elem(1)
end)
4 つのうち 1 つだけに 1
を送ることで、指定の桁を光らせます
関数の定義
使用する関数を諸々定義します
clear_display
では全ての LED に 1
を書き込むことで何も光っていない状態にします
clear_display = fn sdi, rclk, srclk ->
Enum.each(1..8, fn _ ->
Circuits.GPIO.write(sdi, 1)
Circuits.GPIO.write(srclk, 1)
Circuits.GPIO.write(srclk, 0)
end)
Circuits.GPIO.write(rclk, 1)
Circuits.GPIO.write(rclk, 0)
end
shift_out
は前回と同じで、シフトレジスタに指定した信号を順次送ってから並列伝送する関数です
shift_out = fn data, sdi, rclk, srclk ->
for bit <- 0..7 do
bit = data <<< bit &&& 0x80
Circuits.GPIO.write(sdi, bit)
Circuits.GPIO.write(srclk, 1)
Process.sleep(1)
Circuits.GPIO.write(srclk, 0)
end
Circuits.GPIO.write(rclk, 1)
Process.sleep(1)
Circuits.GPIO.write(rclk, 0)
end
pick_digit
関数で光らせる桁を指定します
一旦全て 0
にしておいてから光らせたい桁のピンだけ 1
にしています
pick_digit = fn place_pins, digit ->
Enum.each(place_pins, fn pin ->
Circuits.GPIO.write(pin, 0)
end)
place_pins
|> Enum.at(digit)
|> Circuits.GPIO.write(1)
end
これらを組み合わせて、指定した文字を指定した桁に表示する関数 display
を作ります
display = fn char, place, place_pins, sdi, rclk, srclk ->
clear_display.(sdi, rclk, srclk)
pick_digit.(place_pins, place)
shift_out.(char, sdi, rclk, srclk)
end
COOL を表示する
COOL
の文字を表示させてみます
反転だと考えにくかったので、前回と同じカソード用の 2 進数でコードを指定しておいて、 ~~~
演算子で反転させます
cool_code = [
0b00111001,
0b00111111,
0b00111111,
0b00111000
]
0..100
|> Enum.map(fn _ ->
~~~Enum.at(cool_code, 3)
|> display.(0, place_pins, sdi, rclk, srclk)
~~~Enum.at(cool_code, 2)
|> display.(1, place_pins, sdi, rclk, srclk)
~~~Enum.at(cool_code, 1)
|> display.(2, place_pins, sdi, rclk, srclk)
~~~Enum.at(cool_code, 0)
|> display.(3, place_pins, sdi, rclk, srclk)
end)
画質を 720p60
以上にすれば COOL の文字が見えます
それより低いとバラバラに光っているように見えます
GIF だとこんな感じで、全く同時に光っているようには見えません
スクリーンショットだと各文字が個別に光っているのが分かります
4桁カウンターを表示する
数字をどんどんカウントアップしていくカウンターを表示します
seg_code = [0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90]
0..1000
|> Enum.map(fn counter ->
seg_code
|> Enum.at(rem(counter, 10))
|> display.(0, place_pins, sdi, rclk, srclk)
seg_code
|> Enum.at(div(rem(counter, 100), 10))
|> display.(1, place_pins, sdi, rclk, srclk)
seg_code
|> Enum.at(div(rem(counter, 1000), 100))
|> display.(2, place_pins, sdi, rclk, srclk)
seg_code
|> Enum.at(div(rem(counter, 10000), 1000))
|> display.(3, place_pins, sdi, rclk, srclk)
end)
ピンを閉じる
遊び終わったらピンを閉じておきます
Circuits.GPIO.close(sdi)
Circuits.GPIO.close(rclk)
Circuits.GPIO.close(srclk)
place_pins
|> Enum.map(fn pin ->
Circuits.GPIO.close(pin)
end)
まとめ
Nerves Livebook から 4 桁 7 セグメントディスプレイに文字を表示できました
高速に切り替える技も色々応用ができそうですね