12
0

はじめに

Nerves Livebook で Raspberry Pi 用スターター電子工作キットを楽しんでいます

SunFounder Raspberry Pi 用のスターター電子工作キット

これまでの記事

この記事では 7 セグメントディスプレイに文字を表示します

実装したノートブックはこちら

7 セグメントディスプレイ

7本の棒で文字を表現するディスプレイです

IMG_1576.JPG

実は右下に「.」もあるので LED は 8 個ついています

GPIO のピンを単純に各 LED に繋げれば制御できますが、それだと GPIO のピンをどんどん消費してしまいます

そのため、今回はシフトレジスタとして 74HC595 を使って、3 つのピンだけで 8 つの LED を制御します

シフトレジスタ

シフトレジスタはシリアル伝送とパラレル伝送を変換します

今回の記事では、 74HC595 には順番に信号を送って(シリアル伝送)、そこから 7 セグメントディスプレイには並列に信号を送る(パラレル伝送)ように変換します

                    ┌----┐
 - 1 - 0 - 1 - 0 -> |    | - 0 ->
                    | 変 | - 1 ->
                    | 換 | - 0 ->
                    |    | - 1 ->
                    └----┘

回路の組み立て

オンライン説明書の通りに回路を組みます

ノートブックの実装

Nerves Livebook を開き、以降のコードを実行していきます

ピンを開く

まず、 GPIO の各ピンを出力用に開きます

{:ok, sdi} = Circuits.GPIO.open("GPIO17", :output)
{:ok, rclk} = Circuits.GPIO.open("GPIO18", :output)
{:ok, srclk} = Circuits.GPIO.open("GPIO27", :output)
  • sdi: シリアル伝送を受ける
  • rclk : 1 にしたタイミングで sdi の信号を並列伝送用に設定する
  • srclk : 1 にしたタイミングで設定されていた信号を並列伝送する

2進数をビットに分割する

今回実装する処理の流れは以下のようになっています

  • 入力として 00111111 というような2進数を与える
  • 入力を 0 0 1 1 1 1 1 1 というように各桁に分割する
  • 各桁(ビット)を 74HC595 に順次送る(sdi に各桁の値をセットした後で一瞬 rclk1 にする)
  • 全桁送り終わったら一瞬 srclk1 にする
  • 74HC595 から 7 セグメントディスプレイに各桁の値が並列に送られ、 1 が送られた LED だけ光る

そのため、まずは 2 進数を一桁ずつに分割します

もっと良い実装があるかもしれませんが、 Python 実装を翻訳したものになっています

シフト演算やビットの論理積を行うため、 Bitwise をインポートしておきます

import Bitwise

例えば以下のようなコードを実行します

0b10100001 |> inspect(base: :binary)

0b から始まる値は2進数として解釈されます

inspect(base: :binary) で2進数として表示します(何もしないと10進数に変換して表示されます)

すると、結果は以下のようになります

"0b10100001"

シフト演算子 <<< を使ってみます

0b10100001 <<< 1 |> inspect(base: :binary)

結果は以下のように右端に 0 が追加され、元のビット列は左にシフトしました

"0b101000010"

また、 0b10100001 <<< 2 |> inspect(base: :binary) とすれば "0b1010000100" となり、2桁左にシフトします

シフトしたあと 0b10000000 と論理積を取ってみます

(0b10100001 <<< 0 &&& 0b10000000) |> IO.inspect(base: :binary)
(0b10100001 <<< 1 &&& 0b10000000) |> IO.inspect(base: :binary)
(0b10100001 <<< 2 &&& 0b10000000) |> IO.inspect(base: :binary)
(0b10100001 <<< 3 &&& 0b10000000) |> IO.inspect(base: :binary)
(0b10100001 <<< 4 &&& 0b10000000) |> IO.inspect(base: :binary)
(0b10100001 <<< 5 &&& 0b10000000) |> IO.inspect(base: :binary)
(0b10100001 <<< 6 &&& 0b10000000) |> IO.inspect(base: :binary)
(0b10100001 <<< 7 &&& 0b10000000) |> IO.inspect(base: :binary)

各出力は以下のようになります

0b10000000
0b0
0b10000000
0b0
0b0
0b0
0b0
0b10000000

つまり、 0b10100001 の各桁を左から順に 1 であれば 0b100000000 であれば 0b0 になるように変換しています

この辺りは @kikuyuta さんの記事を参考にしました

分かりやすく 128 で割ると以下のようになります

data = 0b10100001

for bit <- 0..7 do
  div(data <<< bit &&& 0x80, 128)
end

実行結果

[1, 0, 1, 0, 0, 0, 0, 1]

つまり、これによって 0b10100001[1, 0, 1, 0, 0, 0, 0, 1] に分割できます

74HC595 に並列出力を設定する

以下のような関数を定義します

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

data の各ビットについて、 sdi に値をセットし、 srclk を一瞬 1 にして並列伝送用の信号として設定します

全ビット分設定してから rclk を一瞬 1 にして並列伝送を開始します

以下のコードを実行すると、 7 セグメントディスプレイに 0 が表示されます

shift_out.(0b00111111, sdi, rclk, srclk)

00111111 の各桁が「7セグメントディスプレイのどの LED を光らせるか」に対応しています

16 進数を表示する

16 進数(0〜9とA〜F)の各値を 7 セグメントディスプレイに表示します

0b00111111 の2進数を 0x3F のように16進数として表現し、それぞれを 0.5 秒間隔で切り替えます

seg_code = [
  0x3F,
  0x06,
  0x5B,
  0x4F,
  0x66,
  0x6D,
  0x7D,
  0x07,
  0x7F,
  0x6F,
  0x77,
  0x7C,
  0x39,
  0x5E,
  0x79,
  0x71
]

seg_code
|> Enum.map(fn code ->
  shift_out.(code, sdi, rclk, srclk)
  Process.sleep(500)
end)

hex.gif

HELLO. を表示する

HELLO. の各文字を表示してみます

L が連続するため、文字の切り替わりが分かるように「何も光らない時間」を 0.2 秒挟むようにしました

elixir_code = [
  0b01110110,
  0b01111001,
  0b00111000,
  0b00111000,
  0b00111111,
  0b10000000
]

elixir_code
|> Enum.map(fn code ->
  shift_out.(code, sdi, rclk, srclk)
  Process.sleep(500)
  shift_out.(0b00000000, sdi, rclk, srclk)
  Process.sleep(200)
end)

hello.gif

ピンを閉じる

遊び終わったらピンを閉じておきます

Circuits.GPIO.close(sdi)
Circuits.GPIO.close(rclk)
Circuits.GPIO.close(srclk)

まとめ

Nerves Livebook から 7 セグメントディスプレイに文字を表示できました

シフトレジスタの使い方も分かったので、色々応用ができそうです

12
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
0