第13回でmicrobit v2とv1.5のI2Cバスの差について調べました。しかしv2の内部I2Cバスについては触ってません。内部I2Cバスには3軸加速度センサと3軸電子コンパスが接続されてます。手元のmicro:bit v2ではLSM303AGRという1チップで両方できる優れもののデバイスが搭載されています。
※「GoにいればGoに従え」Go関連記事の総Index
micro:bit v2 内部I2Cバス
おさらいしておくと、micro:bit v1.5以前にはI2Cバスは一つしかなかったものが、micro:bit v2からは2つになっています。外部デバイス用にカードエッジの端子に接続している方がI2C1。そして内部デバイス用にボード内で閉じているのがI2C0です。以下の micro:bit のドキュメントに解説されてます。
LSM303AGR
STmicroelectronics製の6軸センサ、LSM303AGRは3軸の加速度センサと3軸の電子コンパスをワンパッケージに封入したデバイスです。冒頭のアイキャッチ画像に赤矢印つけておきましたが、老眼の目にはマーキングが読めない超小型のデバイスです。ST社の製品ページが以下に。
micro:bit はモーションセンサを搭載するという仕様は一貫しているみたいですが、搭載デバイスはバージョンにより異なるようです。手元のmicro:bit についてはv1.5でもv2でも同じ LSM303AGR を搭載してました。
お陰で過去回でv1.5の内外共用のI2CバスでLSM303AGRへアクセスしている例が参考にできました。その時の記事が以下に。ただし言語はMicroPythonですが。
MicroPython的午睡(5) LSM303AGRへアクセス、micro:bit
LSM303AGRの場合、パッケージは1個ですがI2Cのアドレスは2個割り当てられてます。バス的にはデバイスは2個ね。以降、加速度センサ側をACC、電子コンパス側をMAGと略記します。I2Cアドレス(7ビット)は以下のとおり。
-
- ACC 0x19
- MAG 0x1E
上記のI2Cアドレスにアクセスし、ちゃんと通信できていることを確かめたいです。勿論、副作用なく。そのときに使えるのがWHOAMIというレジスタです。そこを読むとデータシートに記載のデバイス固有の数字が読み出せます。このレジスタもACC側とMAG側にそれぞれあります。WHOAMIのレジスタアドレスが以下に。
-
- WHOAMI ACC REG ADR= 0x0F
- WHOAMI MAG REG ADR= 0x4F
そして上記レジスタを読み出すと以下の値が読み出せる筈
-
- WHOAMI ACC REG VALUE= 0x33
- WHOAMI MAG REG VALUE= 0x40
デバイスに向かってあなたは誰?と誰何するっと。上記の合言葉が返ってくればよし、返ってこなかったらどうしよう(まさかそんなことはあるまいが。)
今回実験に使用したGoソース
第13回で使用したソースを流用してます。ただし、内部I2Cバスなので、I2C0を使用し、接続するピンもSCL0_PIN、SCA0_PIN指定です。ボード内部で接続されているのでピンを変更すると動かない筈。
まずは、LSM303AGRへアクセスするためのソースです。今のところWHOAMIレジスタの読み出し機能のみ実装。
package main import ( "machine" "time" ) const LSM303AGR_ACC = 0x19 const LSM303AGR_MAG = 0x1E const WHOAMI_A_ADR = 0x0F const WHOAMI_M_ADR = 0x4F var i2c0 = machine.I2C0 // internal I2C bus func InitInternalI2C() { i2c0.Configure(machine.I2CConfig{ Frequency: machine.TWI_FREQ_100KHZ, SCL: machine.SCL0_PIN, SDA: machine.SDA0_PIN, }) time.Sleep(10 * time.Millisecond) } func ReadWhoAmI(opt bool) (bool, byte) { var tmpADR byte var tmpREG byte dat := []byte{0} if opt { tmpADR = LSM303AGR_ACC tmpREG = WHOAMI_A_ADR } else { tmpADR = LSM303AGR_MAG tmpREG = WHOAMI_M_ADR } err := i2c0.ReadRegister(tmpADR, tmpREG, dat) if err != nil { return false, 0 } return true, dat[0] }
上記ソースの隣においてある仮のmain()関数です。LSM303AGRのWHOAMIレジスタを読み出して、標準出力に16進で値を書き出すだけのもの。
package main import ( "fmt" "time" ) func main() { InitInternalI2C() opt := false for { opt = !opt success, dat := ReadWhoAmI(opt) if success { if opt { fmt.Printf("ACC WHO AM I: %02x\r\n", dat) } else { fmt.Printf("MAG WHO AM I: %02x\r\n", dat) } } else { fmt.Printf("ERROR: ReadWhoAmI\r\n") } time.Sleep(time.Second * 2) } }
実機動作確認
いつものように以下のようにしてビルド&フラッシュ書き込み(勿論micro:bit v2ボードをUSB接続してあります。)
$ tinygo flash -target=microbit-v2
書き込み完了後、USBシリアルで接続(115200ボー)すれば以下のごとし。
出力数字は16進です。予定どおりとな。