M5StickCの内部INT割込通知を利用する その2 MPU6886編

現時点の情報です。最新情報はM5StickC非公式日本語リファレンスを確認してみてください。

概要

M5StickCの内蔵IMUであるMPU6886の加速度センサーを利用して、ディープスリープ中に加速度を感じると復帰できるようにしました。

INT割込通知に関してはその1を参考にしてください。

スケッチ

#include <M5StickC.h>

void setImuInt(uint8_t threshold) {
  uint8_t buf;

  // MPU6886_PWR_MGMT_2
  Wire1.beginTransmission(MPU6886_ADDRESS);
  Wire1.write(MPU6886_PWR_MGMT_2);
  Wire1.endTransmission();
  Wire1.requestFrom(MPU6886_ADDRESS, 1);
  buf = Wire1.read();
  delay(10);
  Wire1.beginTransmission(MPU6886_ADDRESS);
  Wire1.write(MPU6886_PWR_MGMT_2);
  buf = buf | 0x07;
  Wire1.write(buf);
  Wire1.endTransmission();
  delay(10);

  // MPU6886_ACCEL_CONFIG2
  Wire1.beginTransmission(MPU6886_ADDRESS);
  Wire1.write(MPU6886_ACCEL_CONFIG2);
  Wire1.endTransmission();
  Wire1.requestFrom(MPU6886_ADDRESS, 1);
  buf = Wire1.read();
  delay(10);
  Wire1.beginTransmission(MPU6886_ADDRESS);
  Wire1.write(MPU6886_ACCEL_CONFIG2);
  buf = buf | 0x01;
  Wire1.write(buf);
  Wire1.endTransmission();
  delay(10);

  // MPU6886_INT_ENABLE
  Wire1.beginTransmission(MPU6886_ADDRESS);
  Wire1.write(MPU6886_INT_ENABLE);
  buf = 0x40; // Enable WOM_INT_EN
  Wire1.write(buf);
  Wire1.endTransmission();
  delay(10);

  // ACCEL_WOM_THR
  Wire1.beginTransmission(MPU6886_ADDRESS);
  Wire1.write(0x20); // ACCEL_WOM_THR
  buf = threshold;
  Wire1.write(buf);  // X-AXIS ACCELEROMETER
  Wire1.write(buf);  // Y-AXIS ACCELEROMETER
  Wire1.write(buf);  // Z-AXIS ACCELEROMETER
  Wire1.endTransmission();
  delay(10);

  // MPU6886_ACCEL_INTEL_CTRL
  Wire1.beginTransmission(MPU6886_ADDRESS);
  Wire1.write(MPU6886_ACCEL_INTEL_CTRL);
  Wire1.endTransmission();
  Wire1.requestFrom(MPU6886_ADDRESS, 1);
  buf = Wire1.read();
  delay(10);
  Wire1.beginTransmission(MPU6886_ADDRESS);
  Wire1.write(MPU6886_ACCEL_INTEL_CTRL);
  buf = buf | 0xC0; // ACCEL_INTEL_MODE
  Wire1.write(buf);
  Wire1.endTransmission();
  delay(10);

  // MPU6886_PWR_MGMT_1
  Wire1.beginTransmission(MPU6886_ADDRESS);
  Wire1.write(MPU6886_PWR_MGMT_1);
  Wire1.endTransmission();
  Wire1.requestFrom(MPU6886_ADDRESS, 1);
  buf = Wire1.read();
  delay(10);
  Wire1.beginTransmission(MPU6886_ADDRESS);
  Wire1.write(MPU6886_PWR_MGMT_1);
  buf = buf | 0x20;
  Wire1.write(buf);
  Wire1.endTransmission();
  delay(10);

  // INT_STATUS Clear 0x3a
  Wire1.beginTransmission(MPU6886_ADDRESS);
  Wire1.write(0x3a);
  Wire1.endTransmission();
  Wire1.requestFrom(MPU6886_ADDRESS, 1);
  buf = Wire1.read();
  delay(10);
}

void setup() {
  M5.begin();

  // RTC Init
  Wire1.beginTransmission(0x51);
  Wire1.write(0x00);
  Wire1.write(0x00);
  Wire1.write(0x00);
  Wire1.endTransmission();

  // GPIO35 pull-up
  M5.IMU.Init();

  // 衝撃が加わるとHIGHに通知(0x15-0x80ぐらいがおすすめ)
  setImuInt(0x20);

  // GPIO35(M5StickCのINT)がHIGHになったら起動
  pinMode(GPIO_NUM_35, INPUT);
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_35, HIGH);

  // ディープスリープ
  esp_deep_sleep_start();
}

void loop() {
}

IMUの設定なので、思ったより投げるコマンドが多くなりました。

基本的にはデータシートのWAKE-ON-MOTION INTERRUPTの項目を参考にしてください。

いろいろなパラメータをセットして、通知を有効にしてから加速度のしきい値をセットして、通知フラグをクリアすることで、その後の加速度で通知がされます。

今回はディープスリープの例だけですが、RTCと同じくattachInterrupt()を使うことで、動作させながら割込を発生させることができます。

まとめ

かなり苦戦していましたので、説明が雑になっています。わからないことがあったらTwitterかコメント欄で質問ください。

データシートが若干他のシリーズを元にしたままで、MPU6886向けでない記述があります。結局似ているシリーズのデータシートも参考にしながらなんとか動かすことができました。

また、MPU6886に連続して通信をする場合には、delay()をいれないとESP32がパニックになってリセットがかかりますので注意してください。

M5StickCの通知にはRTCとMPU6886の他に電源管理のAXP192が接続されていますが、AXP192でも試しているのですが割込は発生しているようなのですが、GPIO35の通信レベルが変わりません。

また、AXP192からの通知もあまり有効的に使えるものはないので、通知シリーズもここまでかもしれません。

続編

コメントする

メールアドレスが公開されることはありません。

管理者承認後にページに追加されます。公開されたくない相談はその旨本文に記載するかTwitterなどでDM投げてください。またスパム対策として、日本語が含まれない投稿は無視されますのでご注意ください。