Elixir Circuits I2CでLチカ

この記事は、「[#NervesJP Advent Calendar 2019](https://qiita.com/advent-calendar/2019/nervesjp)」 の21日目です。
昨日は @32hero さんの「[Why Nerves|>Nervesを使う理由探し](https://qiita.com/32hero/items/76df15f2a3dc6c52ef3e)」でした。

#はじめに

Elixirを使って、RaspberryPiのハードウェア制御の練習をしてみました。

![外観](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145581/858ab958-4652-319e-3b6c-34de02a06042.jpeg)

今回は、[Elixir Circuits](https://elixir-circuits.github.io/)の[I2C制御サンプル](https://github.com/elixir-circuits/circuits_i2c)を使って、IOエキスパンダICの[MCP23017](http://akizukidenshi.com/catalog/g/gI-09486/)を制御してみます。

※Nervesでないのは、Ubuntu環境が今、手元に無いため・・・ごめんなさい！！


##動作環境
ここでのハードウェア環境は、以下を想定しています。

 - Raspberry Pi 3+
 - Raspbian Buster （2019年9月版）
 - Elixir 1.9.4
 
```bash:コマンドライン
~ $ uname -a
Linux RaspberryPi 4.19.75-v7+ #1270 SMP Tue Sep 24 18:45:11 BST 2019 armv7l GNU/Linux

~ $ iex
Erlang/OTP 22 [erts-10.4] [source] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]

Interactive Elixir (1.9.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> 
``` 

#回路

##RaspberryPiとMCP23017の接続

![RaspberryPiとMCP23017の接続](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145581/fbd9c60c-af79-0ed0-d1c3-d6c31663a9a5.png)

##MCP23017とLEDの接続

![MCP23017とLEDの接続](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145581/f2e2f1a5-c075-778e-6096-a2249d47ca3b.png)

#プログラムの下準備

I2Cの制御に必要なパッケージをインストールします。

```bash:コマンドライン
pi@raspberrypi:~ $ sudo apt install i2c-tools -y
``` 

I2C経由でMCP23017と通信できているか確認します。

```bash:コマンドライン
pi@raspberrypi:~ $ sudo i2cdetect -r -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
```

回路図の通りに接続した場合（A0, A1, A2 = LOW となっている）MCP23017はアドレス0x20に割り当てされます。

#MCP23017の制御方法

コマンドの構成は`<<レジスタ名, 設定値>>`です。

1. 初期化コマンドを送る
 - MCP23017のPORTAを、出力に設定`<<0x00, 0x00>>`
 - （入力にする場合は`<<0x00, 0xff>>`） 

1. 出力のON/OFFの指令を送る
 - PORTAの0～7chをON`<<0x12, 0xff>>`
 - PORTAの0～7chをOFF`<<0x12, 0x00>>`

##MCP23017の主要コマンド

レジスタ名の
*Aは、MCP23017のGPA0～7。
*Bは、MCP23017のGPB0～7に対応します。

| レジスタ名 | 値 | 機能 |
|:---|:---|:---|
| IODIRA | 0x00 | 入出力方向 (0: 出力  1:入力) |
| IODIRB | 0x01 | 〃 |
| GPIOA | 0x12 | 出力レジスタ (GPIOの値) |
| GPIOB | 0x13 | 〃 |


#プログラム例

##ElixirでI2Cを制御する

```elixir:基本構文
I2C.write(ref, 0x20, <<0x12, 0xff>>)
```
|引数|役割|例文|
|:---|:---|:---|
|第2|送信先のI2Cアドレス|0x20（MCP23017のデフォルトアドレス）|
|第3|コマンド|0x12（GPIOAの出力レジスタ）、0xff（8ch全部出力とする）|


##準備

```bash:コマンドライン
~$ git clone https://github.com/elixir-circuits/circuits_i2c.git
~$ cd circuits_i2c/lib
~/circuits_i2c/lib $ touch circuits_i2c.ex
```

空のソースファイル`circuits_i2c.ex`を作っておきます。

##ソースコード

###出力・点滅動作

```elixir:circuit.ex
defmodule Circuits do

    # "L" Chika
    def loop1(start, count_up, sleep_msec) do
        Stream.iterate( start, &( &1 + count_up ) ) |>
        Enum.map( fn count ->
                        
            alias Circuits.I2C
            #I2Cを開く
            {:ok, ref} = I2C.open("i2c-1")

            # 初期化コマンドをI2C経由で送る
            # MCP23017のPORTAを、出力に設定
            I2C.write(ref, 0x20, <<0x00, 0x00>>)

            # PORTAの0～7chをHIGHに切替
            I2C.write(ref, 0x20, <<0x12, 0xff>>)
            :timer.sleep( sleep_msec )
            # PORTAの0～7chをLOWに切替
            I2C.write(ref, 0x20, <<0x12, 0x00>>)
            :timer.sleep( sleep_msec )

            end )
    end


    def main([]) do
        IO.puts "Hello I2C LED..."
        # 処理スタート
        loop1(0, 1, 500)
    end
end
```

###実行

LEDが500msおきに点滅します。

```bash:コマンドライン
~/circuits_i2c $  mix run -e "Circuits.main([])" 
Hello I2C LED...
```

#Grove規格の互換ボード

![Grove規格の互換ボード](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145581/0d002227-36a3-df8c-21ea-692416536826.png)

Grove規格（I2C）互換のボードを作ってみました。

※12/21時点、まだ公開できてないです、すみません！！
[GitHub](https://github.com/trihome/Grove_FA)


#参考資料

- カウンター付き無限ループの書き方
    - https://qiita.com/piacerex/items/aeb45bea6df415e7e1e8