M5capsuleでIMUを使う


# 目次


[1. はじめに](#1-はじめに)
[2. 課題](#2-課題)
[3. やったこと](#3-やったこと)
[4. おわりに](#4-おわりに)


# 1. はじめに
M5capsuleをもらったので使ってみようと思い立った。
動作に連動した何かを作りたいと思ったので、IMUを使ってみることにした。
まだあまり人柱がいないようなので、一助になればと思い投稿。

# 2.課題
IMUの使い方がよく分からない…
どういう数値が返ってきて、どの数値がなんのﾊﾟﾗﾒｰﾀを表すのか、全然わからん。

### そもそもIMUってなんぞや？

#### 【IMUとは？生成AIさんからの回答】

IMU（Inertial Measurement Unit）は、慣性計測ユニットの略で、3次元の慣性運動を検出する装置です。加速度センサー、ジャイロセンサー、温度センサーなどの物理情報センサーを1つのパッケージに統合したセンサーユニットです。﻿
IMUは、加速度と角速度を高精度に計測することができ、計測結果を利用することで運動体の挙動（姿勢・軌跡）を把握、制御するために使用されます。﻿


#### 【ジャイロセンサとは？生成AIさんからの回答】
ジャイロセンサは、物体の回転や向きの変化を角速度として検知し、電気信号で出力するセンサーです。角速度とは、単位時間あたりの回転角度のことを指し、単位はdps（degree per second）で表します。


なるほど、何が検知できるかはわかりましたが、M5capsuleさんのどの方向がどの軸なのかが不明。
公式にもそれらしい記述ないので、実際に調べないとわからんというのが課題認識です。

# 3.やったこと
### M5capsuleで実装テスト
https://github.com/m5stack/M5Unified

M5Unifiedが対応しているようだったので、これのExample-BasicのIMUのコードを参考に、
下記コードのようにArduinoでシリアルモニタで確認ができるようにしました。

<details><summary><b><font color="#409202">╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╮<br>╏&nbsp;&nbsp;&nbsp;&nbsp;<font color="#409202">ソースコードを表示（折りたたみ）</font>&nbsp;&nbsp;&nbsp;╏<br>╰╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╯</font></b></summary><div>

```c++
#include "M5Capsule.h"
#include <M5Unified.h>

static constexpr const uint8_t calib_value = 64;
static uint8_t calib_countdown = 0;
static int prev_xpos[18];

//上端
int up1 = 5;
int up2 = 500;
//下端
int down1 = -5;
int down2 = -500;

void updateCalibration(uint32_t c, bool clear = false)
{
  Serial.println("updateCalibration start");
  calib_countdown = c;

  if (c == 0) {
    clear = true;
  }

  if (clear)
  {
    memset(prev_xpos, 0, sizeof(prev_xpos));

    if (c)
    {
      M5.Imu.setCalibration(calib_value, calib_value, calib_value);
    }
    else
    {
      M5.Imu.setCalibration(0, 0, calib_value);
      M5.Imu.saveOffsetToNVS();
    }
  }
  Serial.println("updateCalibration done");
}

void startCalibration(void)
{
  updateCalibration(10, true);
}

void setup(void)
{
  auto cfg = M5.config();
  M5Capsule.begin(cfg);

  const char* name;
  auto imu_type = M5.Imu.getType();
  switch (imu_type)
  {
  case m5::imu_none:        name = "not found";   break;
  case m5::imu_sh200q:      name = "sh200q";      break;
  case m5::imu_mpu6050:     name = "mpu6050";     break;
  case m5::imu_mpu6886:     name = "mpu6886";     break;
  case m5::imu_mpu9250:     name = "mpu9250";     break;
  case m5::imu_bmi270:      name = "bmi270";      break;
  default:                  name = "unknown";     break;
  };

  //IMUの種類を表示。M5capsule はBMI270
  Serial.println("IMU type: " + String(name));


  if (imu_type == m5::imu_none)
  {
    for (;;) { delay(1); }
  }

  if (!M5.Imu.loadOffsetFromNVS())
  {
    startCalibration();
  }
  M5.Imu.begin();
}

//加速度とジャイロの値を分けて取得
int mode = 0;

void loop(void)
{
  M5Capsule.update();
  auto imu_update = M5.Imu.update();
  auto data = M5.Imu.getImuData();

  //加速度センサーの値を取得
  if(mode == 0){
    Serial.println("ax:" + String(data.accel.x) + "  ay:" + String(data.accel.y) + "  az:" + String(data.accel.z));
    Serial.println("up1:" + String(up1) + "  down1:" + String(down1));
  }

  //ジャイロセンサーの値を取得
  if (mode == 1){
    Serial.println("gx:" + String(data.gyro.x) + "  gy:" + String(data.gyro.y) + "  gz:" + String(data.gyro.z));
    Serial.println("  up2:" + String(up2) +"  down2:" + String(down2));
  }

  //ボタンで加速度/ジャイロの切り替え
  if (M5Capsule.BtnA.wasPressed()) {
      mode++;
      if(mode > 1){
        mode = 0;
      }
      Serial.println("Calibration start");
      M5Capsule.Speaker.tone(10000, 20);
      delay(1000);
      startCalibration();
  }    
}
```
</div></details>

軸方向の確認はこちらです。
M5capsule はBMI270なので、加速度ｾﾝｻとｼﾞｬｲﾛｾﾝｻがあります。
加速度ｾﾝｻは手で動かすくらいだと-10~+10くらい、ｼﾞｬｲﾛｾﾝｻは-500~+500くらいのアナログ出力値でした。

<iframe width="330" height="587" src="https://www.youtube.com/embed/7LICBeVYuko" title="M5capsuleのIMU軸を確認" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

# 4.おわりに
M5capでIMUを使うコード確認ができて、軸方向がわかりました。
これを使って何かを作っていきます。