前回は、BBC micro:bit v2 搭載のSTmicroelectronics社製LSM303AGRのうち磁気センサ(電子コンパス)の読み取りを確認。今回は加速度センサについて読み取りを実行です。読み取りそのものは難しくないけれども、いろいろ出来るので設定すべきレジスタが多いです。最初に一度やるだけだけれども。
※「GoにいればGoに従え」Go関連記事の総Index
前回は LSM303AGRのデータシートにあわせ、ST社の下記のアプリケーションノートを参照させていただきながらプログラムを作成いたしました。書いてある通りにプログラムを書けば動くと。お楽。
LSM303AGRの制御用のTinyGoソース
前回、mb20lsm303.goというファイル名で全文かかげたファイルに追加した部分を以下に掲げました。
まず const定義が大量に。先頭の const OUTZ_H_REG_Mは磁気センサの定義の末尾で、それ以降が追加した加速度センサのレジスタです。以下はアプリケーションノートを見て、最低限必要なレジスタのみ列挙しているのですが、それでもレジスタ数が多いです。
途中略以降が、追加した2関数です。InitAccNormal1Hz()は、加速度センサ部分を初期化する関数で、最初に1度呼び出す必要があります。初期化成功すれば真を返します。なお、設定はNormalモード(10bit レゾリューション)で、±2Gがフルスケール、一番遅いデータレート1Hz、3軸動作です。フィルタ、FIFO、割り込み等まったく使わずポーリング用の設定です(ほぼほぼデフォルト設定。)
ReadACCData()は、加速度センサの読み取り結果を返してきます。戻り値は4要素で最初に読み取りの成功、不成功を真偽値で、つづいて読み取った値を16ビットの整数3個で返してきます。X、Y、Zの順番です。
上記の初期化関数で±2Gをフルスケールとしているので、16ビット整数の-32768が-2G、+32767が+2Gにマップされるのだと思います。細かい誤差とか知らんけど。
//~冒頭略 const OUTZ_H_REG_M = 0x6D const CTRL_REG1_A = 0x20 const CTRL_REG2_A = 0x21 const CTRL_REG3_A = 0x22 const CTRL_REG4_A = 0x23 const CTRL_REG5_A = 0x24 const CTRL_REG6_A = 0x25 const REF_DATAC_A = 0x26 const STATUS_REG_A = 0x27 const OUTX_L_REG_A = 0x28 const OUTX_H_REG_A = 0x29 const OUTY_L_REG_A = 0x2A const OUTY_H_REG_A = 0x2B const OUTZ_L_REG_A = 0x2C const OUTZ_H_REG_A = 0x2D const INT1_THS_A = 0x32 const INT1_DUR_A = 0x33 const INT1_CFG_A = 0x34 // 途中略 func InitAccNormal1Hz() bool { ok := write1Byte(LSM303AGR_ACC, CTRL_REG1_A, 0x17) //ODR=1Hz, Normal, All axis enabled if !ok { return false } ok = write1Byte(LSM303AGR_ACC, CTRL_REG2_A, 0x00) //HPF=Normal, bypass if !ok { return false } ok = write1Byte(LSM303AGR_ACC, CTRL_REG3_A, 0x00) //all interrupts are disabled. if !ok { return false } ok = write1Byte(LSM303AGR_ACC, CTRL_REG4_A, 0x00) //continuous, little endian, +-2g, Normal mode. if !ok { return false } ok = write1Byte(LSM303AGR_ACC, CTRL_REG5_A, 0x00) //Normal mode, FIFO disabled if !ok { return false } ok = write1Byte(LSM303AGR_ACC, CTRL_REG6_A, 0x00) //INT2 disabled if !ok { return false } ok = write1Byte(LSM303AGR_ACC, REF_DATAC_A, 0x00) //REFERENCE/DATACAPTURE_A = 0x00 if !ok { return false } ok = write1Byte(LSM303AGR_ACC, INT1_THS_A, 0x00) //INT1 Threshold is 0x00 if !ok { return false } ok = write1Byte(LSM303AGR_ACC, INT1_DUR_A, 0x00) //INT1 DURATION is 0x00 if !ok { return false } ok = write1Byte(LSM303AGR_ACC, INT1_CFG_A, 0x00) //INT1 All functions are disabled if !ok { return false } // After interrupt setting // ok = write1Byte(LSM303AGR_ACC, CTRL_REG5_A, 0x00) //Normal mode, FIFO disabled // if !ok { // return false // } return true } func ReadACCData() (bool, int16, int16, int16) { ok, reg := read1Byte(LSM303AGR_ACC, STATUS_REG_A) if !ok { fmt.Printf("ERROR ACC 0\r\n") return false, 0, 0, 0 } cnt := 3 if (reg & 0x08) == 0 { //Check ZYXDA only, Ignore Overrun for cnt > 0 { ok, reg = read1Byte(LSM303AGR_ACC, STATUS_REG_A) if ok && ((reg & 0x80) != 0) { break } cnt-- } } if cnt <= 0 { fmt.Printf("ERROR ACC 2\r\n") return false, 0, 0, 0 } ok, regXH := read1Byte(LSM303AGR_ACC, OUTX_H_REG_A) ok, regXL := read1Byte(LSM303AGR_ACC, OUTX_L_REG_A) ok, regYH := read1Byte(LSM303AGR_ACC, OUTY_H_REG_A) ok, regYL := read1Byte(LSM303AGR_ACC, OUTY_L_REG_A) ok, regZH := read1Byte(LSM303AGR_ACC, OUTZ_H_REG_A) ok, regZL := read1Byte(LSM303AGR_ACC, OUTZ_L_REG_A) datX := int16(uint16(regXH)<<8 + uint16(regXL)) datY := int16(uint16(regYH)<<8 + uint16(regYL)) datZ := int16(uint16(regZH)<<8 + uint16(regZL)) return true, datX, datY, datZ }
main.goの差分
上記の mb20lsm303.go のお隣に置いてある main.go の追加差分が以下です。初期化関数 InitAccNormal1Hz()を呼び出したあと、ループの中でReadACCData()しています。
//冒頭略 opt := false time.Sleep(time.Millisecond * 100) InitAccNormal1Hz() //途中略 success, jX, jY, jZ := ReadACCData() if success { fmt.Printf("Acc Data: %d %d %d\r\n", jX, jY, jZ) } else { fmt.Printf("ERROR: reading Acc Data\r\n") } time.Sleep(time.Second * 2) } }
実機実行結果
micro:bit V2機をUSB接続後、以下でビルド&フラッシュ書き込み(書き込み後、即実行)です。通常、tinygoの接続先は自動で検出されます。
$ tinygo flash -target=microbit-v2
USBシリアルに接続したTeratermProで得た出力を以下に掲げます。前回までの出力が残っているので、今回追加した加速度センサの結果のところに線を引きました。
なお、micro:bit V2の場合、ボードのLED面(表面)を上向きに置くとZ軸が上を向く方角のようです。地球重力を観察した場合、下向きの力なのでマイナスの値が読める筈。なお、+32767が+2Gなので地球重力+1Gは16384くらいの値になると予想。ただし、初期設定で10bit Normalモードを指定しているので、下6ビットには値が入らず(つまり64の倍数値しかとれない)のハズ。
まあ、こんなもんかい。micro:bitは部品がデコボコしているので、微妙に傾いてるし。