昨晩、アイキャッチ画像の御本「基礎から学ぶ TinyGoの組込み開発」を購入させていただきました(AmazonのKindle形式電子書籍版ですけど。)これを読めば立派にTinyGo書ける人になること必定?しかし、すみません、まだ読んでません。今回はダメダメなまま前回心に引っかかっていた問題に再突入。
※「GoにいればGoに従え」Go関連記事の総Index
前回心に引っかかっていた問題
前回吉例LチカをBBC micro:bit 上でやってみました。TinyGoから呼び出せる micro:bit用のmachineパッケージには、LED_ROW群3本とLED_COL群9本というボード上の5x5のLEDマトリックスを駆動するための端子が定義されてます。ROW群の最小番号の1番とCOL群の最小番号の1番を組み合わせたら、当然のように5x5の左上のLEDが点灯しました。
BBC micro:bit でもv2になると、ROW5本、COL5本で綺麗に5×5マトリックスを構成してますが、v1系の配列は非対称であることは知ってます。回路図が以下に。
https://github.com/bbcmicrobit/hardware/blob/master/V1.5/SCH_BBC-Microbit_V1.5.PDF
以前 Arduino環境で BBC micro:bit したときにはピン番号の読み方でハマりました(そのときの記事がこちら。)その時と違い上記の回路図相当のROW、COL信号で駆動しているのだもの間違いないハズ。しかし、まだありましたな。
回路図上でのLEDの順番と実際の5x5マトリックス上での順番は関係なかったという件に愕然。左上から順番と思い込んでプログラム書いたらサッパリでした。
ROW、COLとLEDの物理配置
結局、LEDの物理配置を探るためのプログラムを書く羽目になり、調査した結果が以下です。Cxがmachine.LED_COL_xに対応し、Rxがmachine.LED_COL_yに対応してます。以下の5x5の配列は、USBソケットの方向を上、カードエッジを下とした場合の物理配置です。
C1-R1 C4-R2 C2-R1 C5-R2 C3-R1 C4-R3 C5-R3 C6-R3 C7-R3 C8-R3 C2-R2 C9-R1 C3-R2 C9-R3 C1-R2 C8-R1 C7-R1 C6-R1 C5-R1 C4-R1 C3-R3 C7-R2 C1-R3 C6-R2 C2-R3
なんじゃらほいの、COL、ROWバラバラ、あちゃこっちゃに飛んでるのでありました。いやな予感がしたのは、以前遭遇していたのに老人の忘却力で忘れかけていたからか?
今回作成のTinyGoプログラム
ともあれCOL、ROWの組み合わせが判明したので、任意の複数のLEDをパターン点灯させるための関数を自前で書いてみました。多分TinyGoの既存のモジュールの中には同様なことができるモジュールありそうですが、今回は自前主義(まだモジュール化もしておらず。)
uint32型の整数値を1個渡すだけで、いかなるLED点灯パターンにでもなる
関数であります。整数型へのエンコードは、
-
- 点灯を1、消灯を0とする
- 5x5マトリックスの左上をビット0,右下をビット24としてビット列を作成し、uint32型整数に格納する
という方式。整数値を1個渡すだけで〇でも×でもハート型でもお好みのパターンが表示できると。
ともあれ、今回はテストなので「左上から右下に向かって1秒ごとに1ビットが動いていくようなパターン」で動作させてみました。ダラダラなソースコードが以下に。
package main import ( "fmt" "machine" "time" ) func initLED() { machine.LED_ROW_1.Configure(machine.PinConfig{Mode: machine.PinOutput}) machine.LED_ROW_2.Configure(machine.PinConfig{Mode: machine.PinOutput}) machine.LED_ROW_3.Configure(machine.PinConfig{Mode: machine.PinOutput}) machine.LED_COL_1.Configure(machine.PinConfig{Mode: machine.PinOutput}) machine.LED_COL_2.Configure(machine.PinConfig{Mode: machine.PinOutput}) machine.LED_COL_3.Configure(machine.PinConfig{Mode: machine.PinOutput}) machine.LED_COL_4.Configure(machine.PinConfig{Mode: machine.PinOutput}) machine.LED_COL_5.Configure(machine.PinConfig{Mode: machine.PinOutput}) machine.LED_COL_6.Configure(machine.PinConfig{Mode: machine.PinOutput}) machine.LED_COL_7.Configure(machine.PinConfig{Mode: machine.PinOutput}) machine.LED_COL_8.Configure(machine.PinConfig{Mode: machine.PinOutput}) machine.LED_COL_9.Configure(machine.PinConfig{Mode: machine.PinOutput}) machine.LED_ROW_1.Low() machine.LED_ROW_2.Low() machine.LED_ROW_3.Low() } func dispLED(arg uint32) { machine.LED_ROW_1.Low() machine.LED_ROW_2.Low() machine.LED_ROW_3.Low() if (arg & 0x0404001) != 0 { machine.LED_COL_1.Low() } else { machine.LED_COL_1.High() } if (arg & 0x1000404) != 0 { machine.LED_COL_2.Low() } else { machine.LED_COL_2.High() } if (arg & 0x0101010) != 0 { machine.LED_COL_3.Low() } else { machine.LED_COL_3.High() } if (arg & 0x0080022) != 0 { machine.LED_COL_4.Low() } else { machine.LED_COL_4.High() } if (arg & 0x0040048) != 0 { machine.LED_COL_5.Low() } else { machine.LED_COL_5.High() } if (arg & 0x0820080) != 0 { machine.LED_COL_6.Low() } else { machine.LED_COL_6.High() } if (arg & 0x0210100) != 0 { machine.LED_COL_7.Low() } else { machine.LED_COL_7.High() } if (arg & 0x0008200) != 0 { machine.LED_COL_8.Low() } else { machine.LED_COL_8.High() } if (arg & 0x0002800) != 0 { machine.LED_COL_9.Low() } else { machine.LED_COL_9.High() } if (arg & 0x00F8815) != 0 { machine.LED_ROW_1.High() } if (arg & 0x0A0540A) != 0 { machine.LED_ROW_2.High() } if (arg & 0x15023E0) != 0 { machine.LED_ROW_3.High() } } func main() { initLED() var idx = 0 var dpx = 0x1 for { fmt.Println(idx) dispLED(uint32(dpx)) dpx = dpx << 1 time.Sleep(time.Millisecond * 1000) idx++ if idx > 24 { idx = 0 dpx = 0x1 } } }
いやあ、たった25個とは言え、物理配置のデバッグは辛かったっす。どこかにボードレイアウトと信号の対応書いてある資料があるのではないか?ないハズはないだろうに。