
第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進です。予定どおりとな。

