m5stack / M5StickC

M5StickC Arduino Library
MIT License
484 stars 222 forks source link

Enabling wake-on-motion for MPU6886 #119

Closed standarddeviant closed 4 years ago

standarddeviant commented 4 years ago

I made a proof of concept Arduino sketch to enable wake-on-motion for the MPU6886 inside the M5StickC. I'd like to fork the repo, add support for wake-on-motion (to GPIO Pin 35), and then submit a pull request. Is there a testing/integration process for doing that or coding guidelines I should follow?

For those curious, the proof-of-concept sketch is here: https://gist.github.com/standarddeviant/ea0b7f12a32bf5de96992a8ef350351d

A demo video of that sketch is here: https://www.youtube.com/watch?v=v5GpsvjFsEw

I documented a few notes on this here on the m5stack community page: https://community.m5stack.com/topic/2039/wake-up-on-pick-up

Cheers!

ldoyle commented 4 years ago

I'm playing around with receiving interrupts from the AXP192 power managment chip, so here are some thoughts:

-> I think therefore the best solution to make all 3 interrupts work is to configure all as active low, open drain and register the ISR routine as FALLING edge. The ISR can then set a flag as in your code, and the loop must read the status of all devices whose interrupt is active (in your project this is just the IMU, for me it's just the AXP, but it would be exciting to have all 3 possible, e.g. with the wake-up when power is supplied or power button is short pressed etc.)

If I get any further with this, I might also be submitting a PR to correctly init the INT_PIN_CFG on MPU6886. My idea is to add IMU.Init() (or a new function IMU.Reset()) to the M5.begin() method which sets the interrupts correctly and possibly puts the IMU in low power state. Then, if someone actually needs to use the IMU, they call IMU.Init() maybe with optional arguments to enable only Accel or Gyro, whether to enable interrupt and so forth.

standarddeviant commented 4 years ago

@ldoyle That sounds interesting to me! I have wake-on-motion working from deep sleep on the ESP32 - I'll share a gist of that once I iron out a few things. I'd be happy to collaborate on APIs etc. That's neat info about the active-low open-drain config of the MPU6886 - I just checked the datasheet for myself. I plan to put some basic MPU6886 config logic in to a branch soon - maybe adding a special argument to enable "wake-on-motion" interrupts. Let's keep chatting!

standarddeviant commented 4 years ago

@ldoyle I made a proof-of-concept that wakes up on motion from deep sleep, per your suggestion. It doesn't configure as open-drain, but it could probably be made to work that way. I'm a bit naive on details re: open-drain vs. not. Here's my updated sketch that just counts the number of boots as a variable in RTC memory. That sketch is here: https://gist.github.com/standarddeviant/85c31cf34eb51e10aa3bb02dcd0bcbd1

standarddeviant commented 4 years ago

@ldoyle I want to clean up the API/example a bit, but I've made some progress here: https://github.com/standarddeviant/M5StickC/tree/mpu6886_wake_on_motion/examples/Advanced/IMU_Wake_On_Motion

I'm wondering if certain use-cases for waking up from GPIO35 from the 3 sources should coordinate. I'm thinking about better APIs to accomplish that example. There's still a few finnicky things in there that might intimidate newbies. Specifically, I'm thinking of more convenient APIs to handle the rtc_gpio_[de]init logic and where those APIs belong - i.e. AXP192 vs. IMU vs. RTC. More to come. :-)

ldoyle commented 4 years ago

I didn't have time to test much, but here are some thoughts:

standarddeviant commented 4 years ago

Thanks for the detailed reply! Point-by-point...

I'll ping this thread when I've made and tested those changes.

standarddeviant commented 4 years ago

@ldoyle I made the changes you suggested. You were right about the rtc_gpio_[de]init - they don't seem to be needed. I still can't get the open drain to work - not sure what that's all about. After reading a bit on EIS FSYNC, that's definitely not needed for wake-on-motion and I think has to do with integrating in to a camera for image stabilization.

I also got rid of the macros and now use binary masks instead of hex masks. I'm going to test a bit more with this, but might submit a PR soon.

ldoyle commented 4 years ago

Nice to see you're making progress, I haven't found any time to play with my M5 unfortunately. Yeah, some tutorials seem to have the gpio_init, some not. Interesting point about disabling interrupts, you're absolutely right once you read both variables set by the Irq things can be confusing without the "lock".

I'm not sure what is going wrong with the open-drain issue, I got my Axp interrupt working according to #110, specifically by setting also the IMU (although not in use) to active-low with this command:

// set int active is LOW
M5.I2C.writeByte(0x68, 0x37, 0xc8); //actually also sets open-drain

I can think of 2 things that might be going wrong:

Both ways Push-Pull would work while open-drain does not because: IMU has interrupt, sets line LOW, Axp or RTC has no interrupt: Pin35 is LOW correctly IMU has interrupt, sets line LOW, Axp or RTC has interrupt (pulls LOW which already is): Pin35 is LOW correctly IMU has no interrupt, sets line HIGH, Axp or RTC has no interrupt, so essentially "disconnected": Pin35 is HIGH correctly IMU has no interrupt, sets line HIGH, Axp or RTC has an interrupt pulling to LOW: depending on internal resistances Pin35 might measure LOW correctly, but a high current can flow out of the IMU high pin into the e.g. Axp low pin, worst case maybe harming the device.

Zontex commented 4 years ago

Hi Guys, there is official example for wake-up-on-motion MPU here: https://github.com/m5stack/M5StickC/blob/master/examples/Advanced/IMU_Wake_On_Motion/IMU_Wake_On_Motion.ino

Is it the same one you all been looking for?

ldoyle commented 4 years ago

Hi Zontex, as you can see from the linked merge request, it's actually @standarddeviant's work in the official repo now :) But yes, it seems the issue is therefore solved.