I'm trying to use the deep sleep of the ESP32 and wake up using an interrupt from a MPU6050 accelerometer.
But when I compile the code, I get an error :
Thank you. Now I have no more compilation error, but the sensor does not wake the ESP32. Can you tell me what is wrong with my code or provide an example on how to achieve this?
I want to put the ESP32 in deep sleep and have my accelerometer MPU6050 wake it when it detects a movement.
#define Threshold 40 /* Greater the value, more the sensitivity */
#define uS_TO_S_FACTOR 1000000 /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP 10 /* Time ESP32 will go to sleep (in seconds) */
// Bus 2 : l'accéléro
#define SDA2 5
#define SCL2 4
RTC_DATA_ATTR int bootCount = 0;
touch_pad_t touchPin;
#define BUTTON_PIN_BITMASK 0xFF00000000 // all pins
#include <Wire.h>
#include <MPU6050.h>
MPU6050 accelgyro;
/*
Method to print the reason by which ESP32
has been awaken from sleep
*/
void print_wakeup_reason() {
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch (wakeup_reason)
{
case 1 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
case 2 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
case 3 : Serial.println("Wakeup caused by timer"); break;
case 4 : Serial.println("Wakeup caused by touchpad"); break;
case 5 : Serial.println("Wakeup caused by ULP program"); break;
default : Serial.println("Wakeup was not caused by deep sleep"); break;
}
}
/*
Method to print the touchpad by which ESP32
has been awaken from sleep
*/
void print_wakeup_touchpad() {
touch_pad_t pin;
touchPin = esp_sleep_get_touchpad_wakeup_status();
/* Touch Sensor Pin Layout
T0 = GPIO4
T1 = GPIO0
T2 = GPIO2
T3 = GPIO15
T4 = GPIO13
T5 = GPIO12
T6 = GPIO14
T7 = GPIO27
T8 = GPIO33
T9 = GPIO32 */
switch (touchPin)
{
case 0 : Serial.print("Touch detected on GPIO 4 : value "); Serial.println(touchRead(T0)); break;
case 1 : Serial.print("Touch detected on GPIO 0 : value "); Serial.println(touchRead(T1)); break;
case 2 : Serial.print("Touch detected on GPIO 2 : value "); Serial.println(touchRead(T2)); break;
case 3 : Serial.print("Touch detected on GPIO 15 : value "); Serial.println(touchRead(T3)); break;
case 4 : Serial.print("Touch detected on GPIO 13 : value "); Serial.println(touchRead(T4)); break;
case 5 : Serial.print("Touch detected on GPIO 12 : value "); Serial.println(touchRead(T5)); break;
case 6 : Serial.print("Touch detected on GPIO 14 : value "); Serial.println(touchRead(T6)); break;
case 7 : Serial.print("Touch detected on GPIO 27 : value "); Serial.println(touchRead(T7)); break;
case 8 : Serial.print("Touch detected on GPIO 33 : value "); Serial.println(touchRead(T8)); break;
case 9 : Serial.print("Touch detected on GPIO 32 : value "); Serial.println(touchRead(T9)); break;
default : Serial.println("Wakeup not by touchpad"); break;
}
}
void callback0() {}
void callback1() {}
void callback2() {}
void callback3() {}
void callback4() {}
void callback5() {}
void callback6() {}
void callback7() {}
void callback8() {}
void callback9() {}
bool InitAccelero () {
Wire.begin(SDA2, SCL2);
accelgyro.initialize();
// accelgyro.setIntDMPEnabled(false);
// verify connection
bool Success = accelgyro.testConnection();
if (Success) {
Serial.println("MPU6050 connection successful");
// supply your own gyro offsets here, scaled for min sensitivity
accelgyro.setXGyroOffset(29);
accelgyro.setYGyroOffset(-30);
accelgyro.setZGyroOffset(-45);
accelgyro.setXAccelOffset(-3499);
accelgyro.setYAccelOffset(-5049);
accelgyro.setZAccelOffset(887);
}
else Serial.println("MPU6050 connection failed");
return Success;
}
void setup() {
Serial.begin(115200);
accelgyro.setIntMotionEnabled(true); // INT_ENABLE register enable interrupt source motion detection
accelgyro.setMotionDetectionThreshold(10); // 1mg/LSB
accelgyro.setMotionDetectionDuration(2); // number of consecutive samples above threshold to trigger int
bool AcceleroSuccess = InitAccelero ();
delay(1000); //Take some time to open up the Serial Monitor
//Increment boot number and print it every reboot
++bootCount;
Serial.println("Boot number: " + String(bootCount));
delay(200);
//Print the wakeup reason for ESP32 and touchpad too
print_wakeup_reason();
print_wakeup_touchpad();
// touchAttachInterrupt(T0, callback0, Threshold);
touchAttachInterrupt(T1, callback1, Threshold);
touchAttachInterrupt(T2, callback2, Threshold);
touchAttachInterrupt(T3, callback3, Threshold);
// touchAttachInterrupt(T4, callback4, Threshold);
touchAttachInterrupt(T5, callback5, Threshold);
touchAttachInterrupt(T6, callback6, Threshold);
touchAttachInterrupt(T7, callback7, Threshold);
touchAttachInterrupt(T8, callback8, Threshold);
touchAttachInterrupt(T9, callback9, Threshold);
//Configure Touchpad as wakeup source
// esp_sleep_enable_touchpad_wakeup();
//Configure Timer as wakeup source
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
// Configure RTCIO as wakeup source
esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 1); //1 = High, 0 = Low
//Go to sleep now
Serial.println("Going to sleep now");
delay(200);
esp_deep_sleep_start();
}
void loop() {
}
The touchpin part was from previous tests, but touch and external wakeup are exclusive.
You're right. Here is a simpler code: I'll try it this evening back home.
// Bus 2 : l'accéléro
#define SDA2 5
#define SCL2 4
#define MOTPIN 13
#include <Wire.h>
#include "I2Cdev.h"
#include <MPU6050.h>
RTC_DATA_ATTR int bootCount = 0;
MPU6050 accelgyro;
/*
Method to print the reason by which ESP32 has been awaken from sleep
*/
void print_wakeup_reason() {
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch (wakeup_reason)
{
case 1 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
case 2 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
case 3 : Serial.println("Wakeup caused by timer"); break;
case 4 : Serial.println("Wakeup caused by touchpad"); break;
case 5 : Serial.println("Wakeup caused by ULP program"); break;
default : Serial.println("Wakeup was not caused by deep sleep"); break;
}
}
bool InitAccelero () {
Wire.begin(SDA2, SCL2);
accelgyro.initialize();
bool Success = accelgyro.testConnection(); // verify connection
if (Success) {
Serial.println("MPU6050 connection successful");
}
else Serial.println("MPU6050 connection failed");
return Success;
}
void IRAM_ATTR Motion() {
Serial.println("MOTION DETECTED!!!");
}
void setup() {
Serial.begin(115200);
pinmode (MOTPIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(MOTPIN), Motion, RISING);
accelgyro.setIntMotionEnabled(true); // INT_ENABLE register enable interrupt source motion detection
accelgyro.setMotionDetectionThreshold(10); // 1mg/LSB
accelgyro.setMotionDetectionDuration(2); // number of consecutive samples above threshold to trigger int
bool AcceleroSuccess = InitAccelero ();
delay(1000); //Take some time to open up the Serial Monitor
//Increment boot number and print it every reboot
++bootCount;
Serial.println("Boot number: " + String(bootCount));
delay(200);
//Print the wakeup reason for ESP32 and touchpad too
print_wakeup_reason();
// Configure RTCIO as wakeup source
esp_sleep_enable_ext0_wakeup(MOTPIN, 1); //1 = High, 0 = Low
//Go to sleep now
Serial.println("Going to sleep now");
delay(200);
esp_deep_sleep_start();
}
void loop() { }
I'll try the switch test, but what I want to do in the end is wakeup from accelerometer, hence the I2C stuff.
I changed the code to add an attachInterrupt instruction.
The important part of the code (or so I believe) is here:
attachInterrupt(digitalPinToInterrupt(MOTPIN), Motion, RISING);
accelgyro.setIntMotionEnabled(true); // INT_ENABLE register enable interrupt source motion detection
accelgyro.setMotionDetectionThreshold(10); // 1mg/LSB
accelgyro.setMotionDetectionDuration(2); // number of consecutive samples above threshold to trigger int
bool AcceleroSuccess = InitAccelero ();
But do I need the attachInterrupt if I also declare
So I have a code that wakes the ESP32 up on button push :
/*
Deep Sleep with External Wake Up
Push Button to GPIO 33 pulled down with a 10K Ohm resistor
GND --- 10k --- BP --- VCC
|
---- Pin 33
Only RTC IO can be used as a source for external wake
source. They are pins: 0,2,4,12-15,25-27,32-39.
*/
RTC_DATA_ATTR int bootCount = 0;
/* Method to print the reason by which ESP32 has been awaken from sleep */
void print_wakeup_reason() {
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
Serial.println("EXT0 Test");
switch (wakeup_reason)
{
case 1 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
case 2 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
case 3 : Serial.println("Wakeup caused by timer"); break;
case 4 : Serial.println("Wakeup caused by touchpad"); break;
case 5 : Serial.println("Wakeup caused by ULP program"); break;
default : Serial.println("Wakeup was not caused by deep sleep"); break;
}
}
void setup() {
Serial.begin(115200);
delay(300); //Take some time to open up the Serial Monitor
++bootCount;
Serial.println("Boot number: " + String(bootCount));
delay(30);
//Print the wakeup reason for ESP32
print_wakeup_reason();
delay(50);
esp_sleep_enable_ext0_wakeup(GPIO_NUM_33, 1); //1 = High, 0 = Low
Serial.println("Bye !");
delay(100);
esp_deep_sleep_start();
}
void loop() {}
Now, I want to wake up from the accelerometer. This code seems to be working but requires the accelerometer to get shocked to wake up the ESP:
// Bus 2 : l'accéléro
#define SDA2 5
#define SCL2 4
#include <Wire.h>
#include "I2Cdev.h"
#include <MPU6050.h>
RTC_DATA_ATTR int bootCount = 0;
MPU6050 accelgyro;
/*
Method to print the reason by which ESP32 has been awaken from sleep
*/
void print_wakeup_reason() {
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch (wakeup_reason)
{
case 1 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
case 2 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
case 3 : Serial.println("Wakeup caused by timer"); break;
case 4 : Serial.println("Wakeup caused by touchpad"); break;
case 5 : Serial.println("Wakeup caused by ULP program"); break;
default : Serial.println("Wakeup was not caused by deep sleep"); break;
}
}
bool InitAccelero () {
Wire.begin(SDA2, SCL2);
accelgyro.initialize();
bool Success = accelgyro.testConnection(); // verify connection
if (Success) {
Serial.println("MPU6050 connection successful");
}
else Serial.println("MPU6050 connection failed");
return Success;
}
void setup() {
Serial.begin(115200);
bool AcceleroSuccess = InitAccelero ();
accelgyro.setIntMotionEnabled(true); // INT_ENABLE register enable interrupt source motion detection
accelgyro.setMotionDetectionThreshold(10); // 1mg/LSB
// accelgyro.setMotionDetectionDuration(2); // number of consecutive samples above threshold to trigger int
accelgyro.setInterruptMode(HIGH);
delay(1000); //Take some time to open up the Serial Monitor
//Increment boot number and print it every reboot
++bootCount;
Serial.println("Boot number: " + String(bootCount));
delay(20);
print_wakeup_reason(); //Print the wakeup reason for ESP32
// Configure RTCIO as wakeup source
esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 0); //1 = High, 0 = Low
//Go to sleep now
Serial.println("Going to sleep now");
delay(200);
esp_deep_sleep_start();
}
void loop() { }
I guess this line is intended to handle this, but how can I have the ESP wake up on simple movement?