はじめに
先日購入した電子工作ステーションで購入したラズパイ福袋2026に入っていた6軸重力加速度センサーモジュール (BMI160)をMachiKania type PをインストールしたRaspberry Pi Pico 2 Wに接続して加速度などを測定できたでのその方法をまとめました。今回もChatGPTに相談しながら試しました。
検証環境
今回は下記のハードウェア、ソフトウェアで検証しました。
ハードウェア
下記のハードウェアを使用しました。
- MachiKania簡易キット:Raspberry Pi Pico 2 Wを搭載
- 6軸重力加速度センサーモジュール (BMI160)
ソフトウェア
- MachiKania type P 1.6.1.0 KM-1511
接続
6軸重力加速度センサーモジュールとRaspberry Pi Pico 2 WをI2C通信で使用できるように次の表に示すように接続しました。
モジュールのSA0ピンをGNDに接続することでモジュールのスレーブアドレスが0x68にしています。なお、このピンを解放するとアドレスは0x69になります。
| モジュール | Pico 2W(物理) |
|---|---|
| 3V3 | 3v3(36) |
| GND | GND(38) |
| SCL | GP7(10) |
| SDA | GP6(9) |
| SA0 | GND(38) |
表に記載のない品は未接続です。
実態配線図を以下に示します。
BMI160
BMI160はBosch Sensortecが開発した3軸の加速度センサと3軸のジャイロセンサを組み合わせた慣性計測ユニットです。製品紹介ページに示された仕様は次のとおりです。
- 電源:DC3.2V~5V
- 消費電流:<1mA
- 通信モード:I2C/SPI
- AD16ビットコンバータ、16ビットデータ出力
- ジャイロ範囲:±125、±250、±500、±1000、±2000°/s
- 加速範囲:±2、±4、±8、±16g
- ピン間隔:2.54mm
- 動作温度:-40℃~85℃
BMI160の初期化シーケンス
BMI160の初期化は次の手順で実行します。
- チップIDの確認
CHIP_ID(0x00)レジスタのデータを取得し、その値が0xD1と一致するかを確認する。 - ソフトリセット
CMD(0x7E)レジスタにデータ0xB6を書き込み、設定をデフォルト状態あるいはNVMに保存された値にします - 加速度センサーの設定
-
ACC_CONF(0x40)レジスタにアンダーサンプリンク、帯域幅、出力データレートを設定します -
ACC_RANGE(0x41)レジスタに加速度計の重力加速範囲を設定します
-
- ジャイロセンサーの設定
-
GYR_CONF(0x42)レジスタに出力データレータと帯域幅を設定します -
GYR_RANGE(0x43)レジスタに角速度測定範囲を設定します
-
- PMU(電力管理ユニット)をノーマルモードにする。
CMD(0x7E)レジスタにデータ0x11と0x15を書き込み、加速度センサーとジャイロセンサーを測定可能な状態にします
ACC_CONF(0x40)レジスタの内容
加速度計の設定用ACC_CONFレジスタの構成は次のとおりです。
| 名前 | Register(0x40)ACC_CONF | |||||||
|---|---|---|---|---|---|---|---|---|
| Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| Read/Write | R/W | R/W | R/W | R/W | R/W | R/W | R/W | R/W |
| Rest Value | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 |
| Content | acc_us | acc_bwp | acc_odr | |||||
- acc_us:アンダーサンプリングのパラメータでノーマルモードは
0b0に、ローパワーモードにするには’0b1にします。 - acc_bwp:加速度計の帯域幅の設定でノーマルモードのときは
0b010にします。 - acc_odr:$100/2^{8-acc\_odr}$で得られるHz単位の出力データレートを定義します。acc_odrの値は0b0001〜0b1100の範囲です。0b1000が100Hzになります。
ACC_RANGE(0x41)レジスタの内容
加速度計の範囲設定用ACC_RANGEレジスタの構成は次のとおりです。
| 名前 | Register(0x41)ACC_RANGE | |||||||
|---|---|---|---|---|---|---|---|---|
| Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| Read/Write | R/W | R/W | R/W | R/W | R/W | R/W | R/W | R/W |
| Rest Value | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
| Content | Reserved | acc_range<3:0> | ||||||
acc_range<3:0>の値は次の4つから選びます。それ以外の値は±2gレンジに設定されます。
| 値 | レンジ |
|---|---|
| 0b0011 | ±2g |
| 0b0101 | ±4g |
| 0b1000 | ±8g |
| 0b1100 | ±16g |
GYR_CONF(0x42)レジスタの内容
ジャイロスコープの設定用GYR_CONFレジスタの構成は次のとおりです。
| 名前 | Register(0x42)GYR_CONF | |||||||
|---|---|---|---|---|---|---|---|---|
| Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| Read/Write | R/W | R/W | R/W | R/W | R/W | R/W | R/W | R/W |
| Rest Value | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 |
| Content | Reserved | gyr_bwp | gyr_odr | |||||
- gyr_odr:$100/2^{8-gyr\_odr}$で得られるHz単位の出力データレートを定義します。gyr_odrの値は0b0110〜0b1101の範囲です。0b1000が100Hzになります。
- gyr_bwp:ジャイロスコープの帯域幅係数は、センサーデータのローパスフィルターの3dBカットオフ周波数を定義します。
GYR_RANGE(0x43)レジスタの内容
ジャイロスコープの角速度測定範囲の設定用GYR_RANGEレジスタの構成は次のとおりです。
| 名前 | Register(0x43)GYR_RANGE | |||||||
|---|---|---|---|---|---|---|---|---|
| Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| Read/Write | R/W | R/W | R/W | R/W | R/W | R/W | R/W | R/W |
| Rest Value | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Content | Reserved | gyr_range<2:0> | ||||||
gyr_range<2:0>は角速度の範囲と解像度で次の表の値になります。
| range[2:0] | フルスケール | 解像度 |
|---|---|---|
| 000 | ±2000°/s | 16.4 LSB/°/s ⇔ 61.0 m°/s/LSB |
| 001 | ±1000°/s | 32.8 LSB/°/s ⇔ 30.5 m°/s/LSB |
| 010 | ±500°/s | 65.6 LSB/°/s ⇔ 15.3 m°/s/LSB |
| 011 | ±250°/s | 131.2 LSB/°/s ⇔ 7.6 m°/s/LSB |
| 100 | ±125°/s | 262.4 LSB/°/s ⇔ 3.8 m°/s/LSB |
| 101,110,111 | 予約済み |
初期化プログラム
上記を参考にBMI160を次のように初期化します。
- 電力管理:ノーマルモード
- 出力データレート:100Hz
- 加速度測定範囲:±4g
- 角速度の範囲:±2000°/s
BMI160の初期化サブルーチンを以下に示します。
REM ------------------------------------
REM BMI160
LABEL BMI160INIT
VAR R,P
REM CHIP_ID(0x00) check: should be 0xD1
R=I2CREAD(ADDR,0x00)
IF R!=0xD1 THEN RETURN 0
REM Soft reset
I2CWRITE ADDR,0x7E,0xB6
DELAYMS 100
REM Configure ODR/BW
REM ODR=100Hz,BWP=2
I2CWRITE ADDR,0x40,0x28
I2CWRITE ADDR,0x42,0x28
REM Range
REM ACC:0x05->4g
REM GYR:0x00->2000dps
I2CWRITE ADDR,0x41,0x05
I2CWRITE ADDR,0x43,0x00
REM Acc Power mode->normal
I2cwrite ADDR,0x7E,0x11
DELAYMS 5
REM Gyr Power mode->normal
I2CWRITE ADDR,0x7E,0x15
DELAYMS 100
RETURN 1
BMI160からのデータ読み出し
BMI160で計測されたデータはレジスタアドレス0x04から0x17(DATA_0からDATA_19)までに連続して格納されます。このレジスタに格納されるデータの先頭の0x04から0x0Bまでの8バイトはBMI160と接続した外部磁気センサの地磁気とホール抵抗のデータが格納されます。0x0Cから0x17の12バイトにはBMI160のジャイロセンサー、加速度センサーのデータが格納されてます。今回はBMI160のジャイロセンサーと加速度センサーのデータ12バイトを読み取ります。
データは次の表に示すようにLSB、MSBの順に格納されています。
| レジスタ | データ |
|---|---|
| 0x0C | GYR_X<7:0>(LSB) |
| 0x0D | GYR_X<15:8>(MSB) |
| 0x0E | GYR_Y<7:0>(LSB) |
| 0x0F | GYR_Y<15:8>(MSB) |
| 0x10 | GYR_Z<7:0>(LSB) |
| 0x11 | GYR_Z<15:8>(MSB) |
| 0x12 | ACC_X<7:0>(LSB) |
| 0x13 | ACC_X<15:8>(MSB) |
| 0x14 | ACC_Y<7:0>(LSB) |
| 0x15 | ACC_Y<15:8>(MSB) |
| 0x16 | ACC_Z<7:0>(LSB) |
| 0x17 | ACC_Z<15:8>(MSB) |
データ読み出しプログラム
レジスタ0x0Cから12バイトを連続して読み取り、バッファに格納します。格納したデータをもとに角加速度と加速度の値を計算します。下記にそのコードを示します。サブルーチンS16は2つの引数から符号付きのデータを作ります。
レジスタ0x0Cから12バイト分のデータをバッファDに読み込み、先頭から2バイトずつ読み取り角速度と加速度を計算します。
REM ====================================
REM Read 6-axis
LABEL BMI160READ
I2CREADDATA ADDR,D,12,0x0C
GX=GOSUB(S16,PEEK(D+ 0),PEEK(D+ 1))
GY=GOSUB(S16,PEEK(D+ 2),PEEK(D+ 3))
GZ=GOSUB(S16,PEEK(D+ 4),PEEK(D+ 5))
AX=GOSUB(S16,PEEK(D+ 6),PEEK(D+ 7))
AY=GOSUB(S16,PEEK(D+ 8),PEEK(D+ 9))
AZ=GOSUB(S16,PEEK(D+10),PEEK(D+11))
GXD#=FLOAT#(GX)/16.4
GYD#=FLOAT#(GY)/16.4
GZD#=FLOAT#(GZ)/16.4
AXG#=FLOAT#(AX)/8192
AYG#=FLOAT#(AY)/8292
AZG#=FLOAT#(AZ)/8293
RETURN 1
REM ====================================
REM Convert signed 16bit
LABEL S16
USEVAR LSB,MSB
VAR LSB,MSB,V
LSB=ARGS(1)
MSB=ARGS(2)
V=LSB+MSB*256
IF V>32767 THEN V=V-65536
RETURN V
プログラム全体
プログラム全体を以下に示します。
REM ====================================
REM BME160
USEVAR ADDR
USEVAR GX,GY,GZ
USEVAR AX,AY,AZ
USEVAR GXD,GYD,GZD
USEVAR AXG,AYG,AZG
ADDR=0x68
DIM D(12/4)
CLS
I2C
PRINT "Start BME160"
IF GOSUB(BMI160INIT)=0 THEN
PRINT "Initialize failed"
END
ENDIF
PRINT "Init OK"
DO
IF GOSUB(BMI160READ)=1 THEN
CURSOR 0,3
PRINT "ACC[g] X: ";SPRINTF$("%+8.5f",AXG#)
PRINT " Y: ";SPRINTF$("%+8.5f",AYG#)
PRINT " Z: ";SPRINTF$("%+8.5f",AZG#)
PRINT "GYR[dps] X: ";SPRINTF$("%+10.5f",GXD#)
PRINT " Y: ";SPRINTF$("%+10.5f",GYD#)
PRINT " Z: ";SPRINTF$("%+10.5f",GZD#)
ELSE
PRINT "Read failed"
CONTINUE
ENDIF
DELAYMS 50
IF INKEY()!=0 THEN BREAK
LOOP
END
REM ====================================
REM Initialize
REM
LABEL BMI160INIT
VAR R,P
REM CHIP_ID(0x00) check: should be 0xD1
R=I2CREAD(ADDR,0x00)
IF R!=0xD1 THEN RETURN 0
REM Soft reset
I2CWRITE ADDR,0x7E,0xB6
DELAYMS 100
REM Configure ODR/BW
REM ODR=100Hz,BWP-2
I2CWRITE ADDR,0x40,0x28
I2CWRITE ADDR,0x42,0x28
REM Range
REM ACC:0x05->4g
REM GYR:0x00->2000dps
I2CWRITE ADDR,0x41,0x05
I2CWRITE ADDR,0x43,0x00
REM Power mode->normal
I2CWRITE ADDR,0x7E,0x11
DELAYMS 5
I2CWRITE ADDR,0x7E,0x15
DELAYMS 100
RETURN 1
REM ====================================
REM Read 6-axis
LABEL BMI160READ
I2CREADDATA ADDR,D,12,0x0C
GX=GOSUB(S16,PEEK(D+ 0),PEEK(D+ 1))
GY=GOSUB(S16,PEEK(D+ 2),PEEK(D+ 3))
GZ=GOSUB(S16,PEEK(D+ 4),PEEK(D+ 5))
AX=GOSUB(S16,PEEK(D+ 6),PEEK(D+ 7))
AY=GOSUB(S16,PEEK(D+ 8),PEEK(D+ 9))
AZ=GOSUB(S16,PEEK(D+10),PEEK(D+11))
GXD#=FLOAT#(GX)/16.4
GYD#=FLOAT#(GY)/16.4
GZD#=FLOAT#(GZ)/16.4
AXG#=FLOAT#(AX)/8192
AYG#=FLOAT#(AY)/8292
AZG#=FLOAT#(AZ)/8293
RETURN 1
REM ====================================
REM Convert signed 16bit
LABEL S16
USEVAR LSB,MSB
VAR LSB,MSB,V
LSB=ARGS(1)
MSB=ARGS(2)
V=LSB+MSB*256
IF V>32767 THEN V=V-65536
RETURN V
実行結果
上記のプログラムで加速度、角速度を測定できました。
さいごに
MachiKaniaでBMI160を使って加速度、角速度を測定できるようになりました。今回もChatGPTの力を借り、その結果をもとにBMI160の初期化方法などを確認しました。ChatGPTの力を借りなくてもできるようになりたいですね。

