M5Stack grayの9軸センサーMPU9250で加速度を検出する

# はじめに
M5Stack grayに入っている9軸IMUのMPU9250を動かしてみました。
少しハマった点があったので内容を残しておきます。
ただし、試した時期に依存した問題もあるのでその点はご了承ください。

# MPU9250
3軸加速度、3軸ジャイロ、3軸地磁気が組み合わさった9軸センサーです。
いわゆるよくあるx,y,z軸の加速度センサーです。
この記事では加速度のみ扱います。

[データシート](https://www.invensense.com/wp-content/uploads/2015/02/PS-MPU-9250A-01-v1.1.pdf)
[レジスタマップ](https://www.invensense.com/wp-content/uploads/2015/02/RM-MPU-9250A-00-v1.6.pdf)

# 開発環境
Arduino IDE

# M5Stackライブラリの取得
Arduino IDEのボードマネージャーから取得したM5Stack-Core-ESP32ではMPU9250は動作しませんでした。（2018/10/18現在の情報）

参考
[Doesn't work sample sketch "MP9250BasicAHRS" on M5Stack Gray](http://forum.m5stack.com/topic/281/doesn-t-work-sample-sketch-mp9250basicahrs-on-m5stack-gray)


I2C周りにトラブルがあるようなので、最新をgitHubからcloneして入れます。（安定版ではないので他の問題が発生する可能性はあります。）
https://github.com/espressif/arduino-esp32

インストール方法は下記参照
[arduino-esp32のインストール方法(Windows)](https://github.com/espressif/arduino-esp32/blob/master/docs/arduino-ide/windows.md)

clone先
`C:\Users\UserName\Documents\Arduino\hardware\espressif\esp32`

# サンプルを動かしてみる
まずはM5Stackのスケッチ例にMPU9250を動かせるものがあるのでそれを実際に動かしてみます。

スケッチ例/M5Stack/Modules/MPU9250/MPU9250BasicAHRS

MPU9250のセンサー値がLCDに表示されればOKです。

![44729218_198282501070419_1811151265925693440_n.jpg](https://qiita-image-store.s3.amazonaws.com/0/302503/a6a07907-4608-20d4-9bd1-2cf650c0c420.jpeg)


# キャリブレーション
`calibrateMPU9250()`がキャリブレーションを実行しています。
サンプルでは`setup()`内で呼ばれています。

```
// Calibrate gyro and accelerometers, load biases in bias registers
IMU.calibrateMPU9250(IMU.gyroBias, IMU.accelBias);
```

この関数を呼ぶとMPU9250の不揮発領域にオフセット値を保存するようなので、一度キャリブレーション実行後は呼ぶ必要はありません。
私はキャリブレーション時はX,Yを水平（M5StackのLEDを上向き）にして実行しました。その後は基本`calibrateMPU9250()`はコメントアウトしています。

# 加速度の取得
MPU9250はジャイロ・地磁気も取れますが、とりあえず加速度だけ使ってみます。
加速度はIMU.ax,ay,azに格納されています。

```
IMU.ax = (float)IMU.accelCount[0]*IMU.aRes;
IMU.ay = (float)IMU.accelCount[1]*IMU.aRes;
IMU.az = (float)IMU.accelCount[2]*IMU.aRes;
```

#M5Stackの置いた向きを検出
ここまでで、加速度が検出出来ているので、M5Stackを置いた向きを検出するコードを書きます。


例えば、静止している状態でLCD上向きにすると、理想的には
Z : 1000mG, X,Y : 0mG
となります。
ただし誤差があるので、適当にしきい値を設けてどちらを向いているか確認します。

ACCEL_THR_MAX は下向き（ほぼ1000mG）かかる方向を検出するためのしきい値。

```
const static uint32_t ACCEL_THR_MAX = 700;
const static uint32_t ACCEL_THR_MIN = 300;

if(az >=  ACCEL_THR_MAX && abs(ax) <= ACCEL_THR_MIN && abs(ay) <= ACCEL_THR_MIN){
  //DETECT_FRONT
}
```

これを全方向分書くとM5Stackを倒した向きを加速度センサーで検出出来ます。

```
      if(      ax >=  ACCEL_THR_MAX && abs(ay) <= ACCEL_THR_MIN && abs(az) <= ACCEL_THR_MIN){
        //DETECT_LEFT
      }else if(ax <= -ACCEL_THR_MAX && abs(ay) <= ACCEL_THR_MIN && abs(az) <= ACCEL_THR_MIN){
        //DETECT_RIGHT
      }else if(ay >=  ACCEL_THR_MAX && abs(ax) <= ACCEL_THR_MIN && abs(az) <= ACCEL_THR_MIN){
        //DETECT_TOP
      }else if(ay <= -ACCEL_THR_MAX && abs(ax) <= ACCEL_THR_MIN && abs(az) <= ACCEL_THR_MIN){
        //DETECT_BOTTOM
      }else if(az >=  ACCEL_THR_MAX && abs(ax) <= ACCEL_THR_MIN && abs(ay) <= ACCEL_THR_MIN){
        //DETECT_FRONT
      }else if(az <= -ACCEL_THR_MAX && abs(ax) <= ACCEL_THR_MIN && abs(ay) <= ACCEL_THR_MIN){
        //DETECT_BACK
      }else{
        //not update
      }
```

# サンプル
検出するM5Stackの向きによってAvatarで喋る・表情が変わるサンプルを作りました。

https://github.com/Katsushun89/M5Stack_Accelerometer