Nerves Livebook から GPIO 拡張ボードの LED を点滅させる

## はじめに

ここまでの記事で Raspberry Pi 4 に最初からついている LED を光らせることができました

https://qiita.com/RyoWakabayashi/items/8119260ceeea462d6b7b

https://qiita.com/RyoWakabayashi/items/281afab89249dbf68cd5

ただし、センサーの値をクラウドに連携して何らかの処理、というようなことまでをやりたいので、以下の製品を購入しました

[SunFounder Raspberry pi 用のスターター電子工作キット](https://amzn.asia/d/0fb150kF)

![工作キット](https://m.media-amazon.com/images/I/817n6LBssyL._AC_SX679_.jpg)

Python のコードで動かせるようなので、「Python を Elixir に翻訳すればいけるのでは？」という甘い見積もりで早速発注

電子工作は学生の時以来なので、正直説明書なしで組むのは厳しいので、このようなキットは大変ありがたいです

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

https://github.com/RyoWakabayashi/elixir-learning/blob/main/livebooks/nerves_livebook/gpio_led.livemd

## 実行環境

以前の記事と同様、 Nerves Livebook の環境で実行します

https://qiita.com/RyoWakabayashi/items/8119260ceeea462d6b7b

もちろん購入した工作キットには Raspberry pi OS のインストール手順などが記載されているのですが、私はあくまで Elixir でやりたいので無視して進めます

## 回路の組み立て

### GPIO とは

General Purpose Input/Output の略で、汎用入出力のことです

https://www.dospara.co.jp/5info/cts_str_pc_gpio.html

Raspberry Pi 4 では画像の赤枠部分、40本のピンが GPIO になっており、ここからセンサーやボタンなどの外部装置に接続します

![IMG_1538.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/d88ee301-db2c-585f-58a9-b83641f42037.jpeg)


### GPIO 拡張ボード

世の中にはブレッドボードという便利なものがあります

私のような不器用かつおっちょこちょいな人にとって、ハンダ付けは恐ろしい作業です（1敗:火傷）

ブレッドボードでは、ハンダ付けなしで、穴に部品の線を差し込むだけで回路が組めるようになっています

https://shop.sunhayato.co.jp/blogs/problem-solving/breadboard

購入した工作キットには GPIO 拡張ボードがついていて、 Raspberry Pi のピンをブレッドボードから簡単に拡張できるようになっています

これなら子どもでも安心して回路を組むことができます

https://docs.sunfounder.com/projects/davinci-kit/ja/latest/gpio_extension_board.html

### LED点滅用回路

公開されているオンライン説明書を見ながら回路を組み立てます

https://docs.sunfounder.com/projects/davinci-kit/ja/latest/1.1.1_blinking_led.html

こんな感じになりました

![IMG_1537.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/48e0c6d4-6d4d-8255-a990-8a0983df8301.jpeg)

## Elixir で LED を光らせる

### Circuits - GPIO

Nerves から GPIO を操作するためのモジュールです

「Nerves GPIO」で検索したら出てきたのでこれを使います

https://github.com/elixir-circuits/circuits_gpio

### LED の点灯

Raspberry pi　上の Livebook で新しいノートブックを開き、以下のコードを実行します

```elixir
{:ok, gpio} = Circuits.GPIO.open("GPIO17", :output)
```

本来であればこの時点では初期値 0 が設定されるので光らないと思っていたのですが、光ってしまいました

![IMG_1534.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/625d90cb-1120-736f-20e4-036a33b6b72a.jpeg)

この状態で `Circuits.GPIO.write(gpio, 1)` を実行すると LED が消えます

0 で光って 1 で消えるのは直観に反しています

実はオンライン説明書で提示されているコードは電流の向きが逆になっていて、もちろんこれでも点滅させる分には何の問題もないのですが、やはり気持ち悪いので組み替えます

3V3 の線を GND に差し替えて、 LED の向きを逆にしました

![IMG_1536.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/f2690d11-9e1a-ea56-5995-fc903232ba37.jpeg)

この回路であれば 1 で光って 0 で消えるようになります

以下のコードを実行することで LED が光ります

```elixir
{:ok, gpio} = Circuits.GPIO.open("GPIO17", :output)

Circuits.GPIO.write(gpio, 1)

Circuits.GPIO.close(gpio)
```

また、毎回 open して処理実行して close というのが面倒な場合は `write_one` 関数で一回だけ処理することも可能です

以下のコードを実行すると LED が消えます

```elixir
Circuits.GPIO.write_one("GPIO17", 0)
```

### LED の点滅

これらを踏まえて、一定間隔で 0 1 を切り替えれば点滅できるということが分かります

以下のコードを実行すると、 LED を点滅させることができます

```elixir
{:ok, gpio} = Circuits.GPIO.open("GPIO17", :output)

Enum.each(1..10, fn index ->
  Circuits.GPIO.write(gpio, rem(index, 2))
  Process.sleep(500)
end)

Circuits.GPIO.close(gpio)
```

![led_gpio.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/8c1f817b-aacc-8260-58cd-124d93bed04e.gif)

## まとめ

Nerves Livebook で GPIO 拡張ボードの LED を点滅させることができました

ブレッドボードであれば私でもどんどん回路を組めるので、何だか色々できるような気がしてきました