概要
M5StickCで使われているIMUをちゃんと調べてみました。
IMUとは?
IMUとはInertial Measurement Unitの略で、加速度や角速度などの複数のセンサーを搭載したセンサーです。
加速度とは?
上記の任天堂のサイトがわかりやすいですが、どっちの方向に移動したかの移動量になります。X軸加速度、Y軸加速度 、Z軸加速度の3軸です。
角速度とは?
こちらも任天堂のサイトがありました。角速度は、ジャイロセンサーとも呼ばれることが多いですが、ジャイロを利用して、どの方向に回転したかを取得するセンサーです。またジャイロ以外の仕組みを利用した、角速度センサーも存在しています。
どの軸にどれだけ回転したかが角速度になります。こちらもX軸各角度、Y軸各角度、Z軸各角度の3軸です。
姿勢角度とは?
水平に対しての傾きをあらわす角度です。ざっくり説明すると、重力の向きを測定して、重力がかかっている方向から、現在の角度を計算します。重力以外の方法で求める場合もあります。重力からは方位がわからないので、2軸です。
方位とは?
地磁気センサーなどを利用して、方位を測定します。電子コンパスとも呼ばれています。
n軸IMUとは?
3軸IMU
3軸の場合には、加速度、角速度などの単独センサーのみです。一般的に単独センサーなのでIMUとは呼ばず、加速度センサーや角速度センサーなどと呼ばれます。
6軸IMU
加速度の3軸と角速度の3軸を足して、6軸IMUです。この2つ以外の組み合わせも可能ですが、一般的にはこの2つのセンサーになると思います。
姿勢角度は加速度と角速度から計算することができるので、センサー自体は6軸ですが、利用は8軸使うことができます。ただし、計算で出す姿勢角度は誤差が出やすいです。
9軸IMU
加速度の3軸と角速度の3軸に地磁気センサーの情報を足して、9軸IMUです。地磁気センサーは2軸もしくは3軸のセンサーになるので、姿勢角度の精度があがっているはずです。
M5StackCのMPU6886を動かしてみる
スケッチ例
#include <M5StickC.h> float accX = 0.0F; float accY = 0.0F; float accZ = 0.0F; float gyroX = 0.0F; float gyroY = 0.0F; float gyroZ = 0.0F; float pitch = 0.0F; float roll = 0.0F; float yaw = 0.0F; int mode = -1; void setup() { M5.begin(); M5.IMU.Init(); } void loop() { M5.update(); // データ取得 M5.IMU.getGyroData(&gyroX, &gyroY, &gyroZ); M5.IMU.getAccelData(&accX, &accY, &accZ); M5.IMU.getAhrsData(&pitch, &roll, &yaw); // モードチェンジ if ( mode == -1 || M5.BtnA.wasReleased() ) { mode++; mode = mode % 3; // プロッタ用のタイトル出力 if ( mode == 0 ) { Serial.printf("gyroX,gyroY,gyroZ\n"); } else if ( mode == 1 ) { Serial.printf("accX,accY,accZ\n"); } else if ( mode == 2 ) { Serial.printf("pitch,roll,yaw\n"); } } // データ出力 if ( mode == 0 ) { Serial.printf("%6.2f,%6.2f,%6.2f\n", gyroX, gyroY, gyroZ); } else if ( mode == 1 ) { Serial.printf("%5.2f,%5.2f,%5.2f\n", accX, accY, accZ); } else if ( mode == 2 ) { Serial.printf("%5.2f,%5.2f,%5.2f\n", pitch, roll, yaw); } delay(10); }
スケッチ例のIMUを改造したものです。数値だけ見てもIMUのデータは理解できないので、Arduinoのシリアルプロッタを使ってグラフ化しています。
BtnAを押すことで、ジャイロ(角速度)、加速度、姿勢角を切り替えながら出力するように作ってあります。M5StickCの画面には何も表示されないので注意してください。
グラフ化の原理
Serial出力にカンマ区切りの数値データを出力することで、自動的にグラフ化してくれる機能がArduino IDEにはあります。
そのままだとどのデータかがわかりにくいので、グラフにタイトルを出しています。タイトルはカンマ区切りの文字列を出力すると、更新されます。
Serial.printf("%6.2f,%6.2f,%6.2f\n", gyroX, gyroY, gyroZ);
上記がジャイロ(角速度)のデータ出力部分。
Serial.printf("gyroX,gyroY,gyroZ\n");
上記がジャイロ(角速度)のタイトル出力部分。
ジャイロ(角速度)をためす

画面を上にして、机に置いたM5StickCでジャイロ(角速度)を動かした画面です。スケッチを実行してからArduino IDEのツールからシリアルプロッタを選択して画面を表示してください。
グラフのタイトルが表示されない場合にはBtnAを押すと、次のグラフに切り替わるので、もう一周してジャイロを表示してみてください。
上記だとX軸が6、Y軸が-5、Z軸が-10ぐらい原点からずれています。個体差があると思いますが、M5StickCの標準ライブラリだと補正していないので、若干の誤差がでます。

各軸に対して回転を加えた場合の図です。ちょっと動かすだけでも数百の値になるので、10ぐらいの誤差だったら問題ないかもしれません。
ぐりぐり動かしてみて、どの方向に回転するとどれぐらいの数値になるのかを試してみてください。
加速度をためす

画面を上にして、机に置いたM5StickCで加速度を動かした画面です。Z軸が1ぐらいの数値になっています。これは重力で1Gの力が下向きにかかっていることになります。
加速度は重力の方向に1Gがかかりますので、M5StickCの向きを変えることで、静止していても各軸の数値が変わります。M5StickCを立てるとY軸が1Gになり、X軸とZ軸が0Gになります。

上記が各方向にM5StickCを振った場合の図です。単位がGなので、結構がんばってもそれほど大きな数字にはなりません。初期化で最大値が8Gまでに設定されているので、8G以上の力を加えても8Gまでの測定になります。
設定範囲は2G、4G、8G、16Gが選択することができます。
M5.Mpu6886.SetAccelFsr(M5.Mpu6886.AFS_16G);
2Gなど小さい範囲にすると、より高精度で測定することができるはずです。ただここの設定値はMPU6886とSH200で設定できる範囲と方法が違うので注意しましょう!
姿勢角度をためす

んー、なんか動きがおかしいですね。ピッチは前後に傾いている角度がわかります。ロールは左右に傾いている角度がわかります。ヨーは方位なので地磁気センサーを搭載していないM5StickCだと起動時の方位を原点として、加速度から方向を計算しています。
動かしてみるとわかるのですが、ちゃんとした精度で姿勢角度を使うのは難しそうです。これだったら加速度の値から自分で計算したほうがいいのかな?
まとめ
なんとなく理解していなかったIMUが少しわかった気がします。姿勢角度はもうちょっと精度をたかめる方法があると思いますが、現状のところ使わない方がいい気がします。
本格的にIMUを使うには、BluetoothSerialでセンサーの値を飛ばしながら動かして、どんな数値になるのかを確認しながら進めたほうが良さそうです。
グラフだと実際の数値がわからないので、シリアルプロッタを閉じてから、シリアルモニタを開くと実際の数字を確認することができます。
同時に見たかったり、数字を保存したい場合にはProcessingなどを使って、自分で処理をするのがよいと思います。
現時点の情報です。最新情報はM5StickC非公式日本語リファレンスを確認してみてください。
コメント
[…] M5StickCの6軸IMU MPU6886を調べる – Lang-ship https://lang-ship.com/blog/work/m5stickc-imu-mpu6886/ […]
[…] おなじみLangShip様の解説が入口になります。 https://lang-ship.com/blog/work/m5stickc-imu-mpu6886/ ここで不足している部分を自分で補います。 […]