#1.はじめに
goとgobotを使って、RaspberryPiのI2Cに接続したIOエキスパンダ(MCP23017)を操作してみます。
公式にMCP23017がサポートされてるので、チュートリアルチャレンジで終わるかと思ったら、なんと、サンプルコードが書かれてなかったので、覚え書きを兼ねて簡単にまとめてみました。
実行環境
ハードウェア | Raspberry Pi 4 |
OS | Raspbian Buster |
go | Ver.1.14.3 |
IOエキスパンダ | MCP23017 |
→これを、RaspberryPiのI2C端子に接続済 |
$ 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.準備
インストールは別記事で解説しているので、詳細はそちらをご覧下さい。
#3.LEDの点滅例
MCP23017のポートAのピン0~7につないだLEDを、流れるように点灯する例です。
こちらのドキュメントを参考12に書いてみました。
重要な関数は以下の通りです。
i2c.NewMCP23017Driver
i2c.WithBus(1) | ラズパイのi2cは1 です。(1を指定している例:$ sudo i2cdetect -r -y 1 ) |
i2c.WithAddress(0x20) | MCP23017の設定にあわせます。(ここでは0x20) |
-
WriteGPIO(ピン番号, 値, ポート名)
- 値は
0
:消灯、1
:点灯 - ポート名は文字列で指定、
"A"
あるいは"B"
- 値は
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()
}
###実行
コマンドライン
$ 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が、左から右へ流れています。
#4.おわりに
残課題としては、[Ctrl-C]で止めたときに、IOエキスパンダを全て消灯することです。
現状のままだと、制御が止まった時点の点灯が残ってしまいます。
こちら3を参考に、SIGINT捕捉後にIOエキスパンダのピン番号全てにLを送って消灯するプログラムを試しましたが、どうやらwork := func() {
の実行が生きている間に消灯処理を入れないとダメなようです。(今の所、解決できてません)
#参考資料