M5StickCの6軸IMU(SH200Q)検証

現状とライブラリのバージョンが違うので、同じコードが動かないと思います。最新情報はM5StickC非公式日本語リファレンスで確認してください。

情報

  • http://senodia.com/en/Product/detail/id/17.html
  • http://senodia.com/Uploads/Product/5b2b6ef1216e8.pdf

IMUは英語のページと、データシートがあるので良かったです。

データシートでの軸

IMUは使ったことがないのですが、図を見る限り普通の座標系な気がします。

実験

机の上に、横に置いて、上から見た図の写真です。この方向からいろいろな方向に動かして、加速度とジャイロの反応を調べました。

表示されているのが上から、ジャイロの現在値、最大値、最小値。加速度の現在地、最大値、最小値です。ボタンを押すと数値をリセットするので、調べ終わったらリセットして、他の方向を調べています。

加速度(acc)

X軸加速度

左右に動かしても反応しなかったのですが、なんと右側を持ち上げるとプラスに反応。左側を持ち上げるとマイナスの加速度でした。

Y軸加速度

Y軸は手前に傾けるとプラス、手前を持ち上げるとマイナスでした。

Z軸加速度

Z軸は左に回転するとプラス、右に回転するとマイナスでした。

ジャイロ(Gyro)

X軸ジャイロ

元の状態が0で、手前を持ち上げるとプラスで、写真の状態で0.5になり、奥を持ち上げるとマイナスになります。

Y軸ジャイロ

元の状態が0で、右側を持ち上げるとプラスで、写真の状態で0.5になり、左側を持ち上げるとマイナスになります。

Z軸ジャイロ

元の状態が0.5で、どの方向にでも90度傾けると0.0になっていたように思えます。

実験プログラム

#include <M5StickC.h>
int16_t accX = 0;
int16_t accY = 0;
int16_t accZ = 0;
int16_t gyroX = 0;
int16_t gyroY = 0;
int16_t gyroZ = 0;
void setup() {
  // put your setup code here, to run once:
  M5.begin();
  M5.IMU.Init();
  M5.Lcd.setRotation(3);
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setTextSize(1);
  M5.Lcd.setCursor(40, 0);
  M5.Lcd.println("SH200I TEST");
  M5.Lcd.setCursor(0, 15);
  M5.Lcd.println("  X       Y       Z");
  pinMode(M5_BUTTON_HOME, INPUT);
  pinMode(M5_BUTTON_RST, INPUT);
}
float max_gyroX = 0;
float min_gyroX = 0;
float max_gyroY = 0;
float min_gyroY = 0;
float max_gyroZ = 0;
float min_gyroZ = 0;
float max_accX = 0;
float min_accX = 0;
float max_accY = 0;
float min_accY = 0;
float max_accZ = 0;
float min_accZ = 0;
void loop() {
  if (digitalRead(M5_BUTTON_HOME) == LOW || digitalRead(M5_BUTTON_RST) == LOW ) {
    max_gyroX = 0;
    min_gyroX = 0;
    max_gyroY = 0;
    min_gyroY = 0;
    max_gyroZ = 0;
    min_gyroZ = 0;
    max_accX = 0;
    min_accX = 0;
    max_accY = 0;
    min_accY = 0;
    max_accZ = 0;
    min_accZ = 0;
    delay(1000);
  }
  // put your main code here, to run repeatedly:
  M5.IMU.getGyroData(&gyroX, &gyroY, &gyroZ);
  M5.IMU.getAccelData(&accX, &accY, &accZ);
  if ( max_gyroX < ((float) gyroX) * M5.IMU.gRes ) {
    max_gyroX = ((float) gyroX) * M5.IMU.gRes;
  }
  if ( ((float) gyroX) * M5.IMU.gRes < min_gyroX ) {
    min_gyroX = ((float) gyroX) * M5.IMU.gRes;
  }
  if ( max_gyroY < ((float) gyroY) * M5.IMU.gRes ) {
    max_gyroY = ((float) gyroY) * M5.IMU.gRes;
  }
  if ( ((float) gyroY) * M5.IMU.gRes < min_gyroY ) {
    min_gyroY = ((float) gyroY) * M5.IMU.gRes;
  }
  if ( max_gyroZ < ((float) gyroZ) * M5.IMU.gRes ) {
    max_gyroZ = ((float) gyroZ) * M5.IMU.gRes;
  }
  if ( ((float) gyroZ) * M5.IMU.gRes < min_gyroZ ) {
    min_gyroZ = ((float) gyroZ) * M5.IMU.gRes;
  }
  if ( max_accX < ((float) accX) * M5.IMU.aRes ) {
    max_accX = ((float) accX) * M5.IMU.aRes;
  }
  if ( ((float) accX) * M5.IMU.aRes < min_accX ) {
    min_accX = ((float) accX) * M5.IMU.aRes;
  }
  if ( max_accY < ((float) accY) * M5.IMU.aRes ) {
    max_accY = ((float) accY) * M5.IMU.aRes;
  }
  if ( ((float) accY) * M5.IMU.aRes < min_accY ) {
    min_accY = ((float) accY) * M5.IMU.aRes;
  }
  if ( max_accZ < ((float) accZ) * M5.IMU.aRes ) {
    max_accZ = ((float) accZ) * M5.IMU.aRes;
  }
  if ( ((float) accZ) * M5.IMU.aRes < min_accZ ) {
    min_accZ = ((float) accZ) * M5.IMU.aRes;
  }
  M5.Lcd.setCursor(0, 24);
  M5.Lcd.printf("%+7.2f %+7.2f %+7.2f\n", ((float) gyroX) * M5.IMU.gRes, ((float) gyroY) * M5.IMU.gRes, ((float) gyroZ) * M5.IMU.gRes);
  M5.Lcd.printf("%+7.2f %+7.2f %+7.2f\n", max_gyroX, max_gyroY, max_gyroZ);
  M5.Lcd.printf("%+7.2f %+7.2f %+7.2f\n", min_gyroX, min_gyroY, min_gyroZ);
  M5.Lcd.setCursor(0, 50);
  M5.Lcd.printf("%+7.2f %+7.2f %+7.2f\n", ((float) accX) * M5.IMU.aRes, ((float) accY) * M5.IMU.aRes, ((float) accZ) * M5.IMU.aRes);
  M5.Lcd.printf("%+7.2f %+7.2f %+7.2f\n", max_accX, max_accY, max_accZ);
  M5.Lcd.printf("%+7.2f %+7.2f %+7.2f\n", min_accX, min_accY, min_accZ);
}

サンプルスケッチのSH200Iに最小値と最大値を保存するようにした物になります。温度計は表示上邪魔なので消してしまいました。

まとめ

サンプルスケッチを動かしてみて、数値の動きが意図していたのと違っていたので実験してみましたが、予想と違う結果になりました。

加速度は純粋な座標軸じゃなくて、座標軸に対する回転方向の加速度な気がします。ただ、加速度とジャイロで軸の方向が違う気がするので謎が深まります。

ジャイロはおそらく重力を基準としているので、チップの付いている向きと重力の向きが違うのかもしれません。

ちょっと腑に落ちないところがあるので、他の人も検証してもらいたいです。私の端末がおかしいのか、そもそもデータシートから間違っているのかが知りたいです。。。

コメント

  1. cartman より:

    手元にないので何ともですが,sdkの中身を覗いてもおかしい計算をしているようには見えないのでデータシートのほうですかね?

    てっきり左手座標と右手座標の間違いかと思ったのですが,高さ方向を変えてx軸の変化だとよくわからんですね

    https://github.com/m5stack/M5StickC/blob/master/src/IMU.cpp

    • cartman より:

      図でおかしいのは,軸は左手座標系なのに回転方向が反時計回りになっているところですかね.一般的に左手座標系の場合,時計回りがプラス方向かと思います.

      • mt より:

        そもそも加速度とジャイロの数字が逆と思えるので、何が正しいのかがわからない状態です、、、
        データシートとソースコード上、正しいはずなんですけれどね

  2. safa より:

    自分の端末も同じ結果でした

    なんででしょうね。。。

    • mt より:

      データシートと実際の動きが違う気がしますよね
      全部この動きであれば、この動き前提のプログラムを作ればいいんですけれど、ちょっともやっとします

  3. hirotakaster より:

    こんばんわ。僕もSH200Q(ただし、M5StickVに搭載されているもの)を検証している所ですが、加速度の値が明らかにおかしい感じがしています。さっぱりどういう座標と値を意味しているのか、理解が出来ていなくて、うーんといった感じがしています。

    • mt より:

      おっ、初期ロットですか?
      初期以外はMPU6866ですっけ?

      M5StickCも変わるのかな。。。
      ただSH200Qはやっぱりデータシートと動きが違いますよね?

  4. hirotakaster より:

    僕は初期ロットのSH200Qを引いてしまい(InvenSenseの方を使いたいですが…)、M5StickCのIMU部分をpythonにしてデータを取得していますが、記載されている通りの謎の動きで、うーん…といった感じです。データシートの値と違いすぎるので、諦めて取れる値を使おうかなと思っている所です。

    • mt より:

      結局の所習得できるデータでがんばるしかないんですよね。。。
      ただ、ロットで互換性まったくないセンサー搭載するのはやめて欲しい!