現時点の情報です。最新情報は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からの通知もあまり有効的に使えるものはないので、通知シリーズもここまでかもしれません。




コメント