gobot I2CでLチカ

#1.はじめに

goと[gobot](https://gobot.io/)を使って、RaspberryPiのI2Cに接続したIOエキスパンダ(MCP23017)を操作してみます。

[公式にMCP23017がサポート](https://gobot.io/documentation/drivers/mcp23017/)されてるので、チュートリアルチャレンジで終わるかと思ったら、なんと、サンプルコードが書かれてなかったので、覚え書きを兼ねて簡単にまとめてみました。

**実行環境**

| | |
|:--|:--|
|ハードウェア|Raspberry Pi 4 |
|OS|Raspbian Buster|
|go|Ver.1.14.3|
|||
|IOエキスパンダ|[MCP23017](http://akizukidenshi.com/catalog/g/gI-09486/)|
||→これを、RaspberryPiのI2C端子に接続済|

```bash
$ uname -a
Linux raspi4 4.19.97-v7l+ #1294 SMP Thu Jan 30 13:21:14 GMT 2020 armv7l GNU/Linux
$ go version
go version go1.14.3 linux/arm
$ 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: -- -- -- -- -- -- -- --    
```


#2.準備

インストールは別記事で解説しているので、詳細はそちらをご覧下さい。

- [golang](https://hotch-potch.hatenadiary.jp/entry/2020/01/05/213840)
- [gobot](https://hotch-potch.hatenadiary.jp/entry/2020/05/31/205957)

#3.LEDの点滅例

MCP23017のポートAのピン0～7につないだLEDを、流れるように点灯する例です。
こちらのドキュメントを参考[^a][^b]に書いてみました。

[^a]: https://godoc.org/gobot.io/x/gobot/drivers/i2c#MCP23017Driver
[^b]: https://github.com/hybridgroup/gobot/blob/master/drivers/i2c/mcp23017_driver.go

重要な関数は以下の通りです。

- `i2c.NewMCP23017Driver`

|||
|:--|:--|
|i2c.WithBus(1)|ラズパイのi2cは`1`です。（1を指定している例：`$ sudo i2cdetect -r -y 1`）|
|i2c.WithAddress(0x20)|MCP23017の設定にあわせます。（ここでは0x20）|

- `WriteGPIO(ピン番号, 値, ポート名)`
  - 値は`0`：消灯、`1`：点灯
  - ポート名は文字列で指定、`"A"`あるいは`"B"`

```golang:raspi_blink_i2c.go
package main

import (
	"time"

	"gobot.io/x/gobot"
	"gobot.io/x/gobot/drivers/i2c"
	"gobot.io/x/gobot/platforms/raspi"
)

func main() {
	//初期化
	raspiAdaptor := raspi.NewAdaptor()
	//MCP23017の初期化
	//I2Cバス1番、アドレス0x20
	i2cexp := i2c.NewMCP23017Driver(raspiAdaptor,
		i2c.WithBus(1),
		i2c.WithAddress(0x20))

	//LEDを流れるように点灯するための制御変数
	//pin: ピン番号0から開始
	//val: 点灯1状態から開始
	var pin, val uint8
	pin, val = 0, 1

	//定期実行
	work := func() {
		//100ms毎にループ
		gobot.Every(100*time.Millisecond, func() {

			//ポートAのピンを点灯/消灯
			i2cexp.WriteGPIO(pin, val, "A")

			//ピン番号を次に移動
			pin++
			if pin > 7 {
				//ピン番号7になったら、ピン番号を0に戻す
				pin = 0
				if val == 1 {
					//現在が点灯1状態なら、次は消灯0状態に
					val = 0
				} else {
					//次は点灯1状態に
					val = 1
				}
			}
		})
	}

	robot := gobot.NewRobot("bot",
		[]gobot.Connection{raspiAdaptor},
		//デバイスに追加
		[]gobot.Device{i2cexp},
		work,
	)

	robot.Start()
}
```

###実行

```bash:コマンドライン
$ go run raspi_blink_i2c.go 
2020/05/31 20:56:29 Initializing connections...
2020/05/31 20:56:29 Initializing connection RaspberryPi-308BFB50 ...
2020/05/31 20:56:29 Initializing devices...
2020/05/31 20:56:29 Initializing device MCP23017-6301D4B5 ...
2020/05/31 20:56:29 Robot bot initialized.
2020/05/31 20:56:29 Starting Robot bot ...
2020/05/31 20:56:29 Starting connections...
2020/05/31 20:56:29 Starting connection RaspberryPi-308BFB50...
2020/05/31 20:56:29 Starting devices...
2020/05/31 20:56:29 Starting device MCP23017-6301D4B5...
2020/05/31 20:56:29 Starting work...
2020/05/31 20:58:30 Stopping Robot bot ...
[Ctrl-C]
$
```

下記の動画、下の方の8つのLEDが、左から右へ流れています。

![VID_20200531_205746_144x256_fps25.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145581/9cb83458-c6f3-9e56-cb23-6adf913b16e7.gif)

#4.おわりに

残課題としては、[Ctrl-C]で止めたときに、IOエキスパンダを全て消灯することです。

現状のままだと、制御が止まった時点の点灯が残ってしまいます。
こちら[^aa]を参考に、SIGINT捕捉後にIOエキスパンダのピン番号全てにLを送って消灯するプログラムを試しましたが、どうやら`work := func() {`の実行が生きている間に消灯処理を入れないとダメなようです。（今の所、解決できてません）

[^aa]: https://oohira.github.io/gobyexample-jp/signals.html

#参考資料