ESP32 wake up using external interrupt

Hi

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 :

Arduino : 1.8.2 (Windows 10), Carte : "LOLIN D32, Default, 80MHz, 921600, None"

C:\Users\Chuwi\Documents\Arduino_ESP32\DS_TouchWakeUp_et_Timer\DS_TouchWakeUp_et_Timer.ino: In function 'void setup()':

DS_TouchWakeUp_et_Timer:156: error: 'esp_deep_sleep_enable_ext0_wakeup' was not declared in this scope

Serial.println(esp_deep_sleep_enable_ext0_wakeup(GPIO_NUM_13, 1)); //1 = High, 0 = Low

^

exit status 1
'esp_deep_sleep_enable_ext0_wakeup' was not declared in this scope

Why is it not declared? Is it impossible to wake up from interrupt when programming with Arduino IDE?

Hii !
try

esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,1);

as seen in 'ExternalWakeUp' example

It compiles now! Thank you Sir :slight_smile:

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.

Thanks for your help.

Did you try reducing the code so that its just looking for a switch input to wake up ?

It would be easier to read the code that way.

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() { }

Get rid of all the code you dont need.

Your testing a switch wakeup from deep sleep so why do you need the I2C stuff ?

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

esp_sleep_enable_ext0_wakeup(MOTPIN, 1); //1 = High, 0 = Low

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?

 accelgyro.setMotionDetectionThreshold(10);

Hi,
did you solve your issue? I have the same problem...