External wakeup from deep sleep on XIAO ESP32C

In deep sleep mode on XIAO ESP32C3 I can use a timer to wake up the XIAO from deep sleep every x seconds, check this example. The power consumption during deep sleep is an astonishing ~41uA (great success in Borats voice).
But in my case I need to wake up the XIAO from DEEP sleep using external sources. I came across this official documentation by espressif. The line that says ESP32C3 can’t be woken up from deep sleep using EXT0 and EXT1 as the case with the standard ESP32 killed my project in its crib :cry:
Is there any other ways to wake up the board from deep sleep using external triggers? Should I give up and choose some other processor, like the standard ESP32?

Did you ever find a solution for this? I’m reading the same thing you are and coming to the same conclusion. The only idea I have is to use an external trigger to power on the entire chip (FET + dry contact?) but that won’t work for all use cases.

Same question here. Is it possible to use the JTAG pad “EN” for this purpose. According to the Eagle schematic the Reset button is coupled by a 10K resistor to VCC 3.3v and attached to the CHIP_EN pin of the espressif chip, and the other side attached to ground. VCC and Ground are coupled with a 100nF capacitor.

Can you solder/connect the same setup on the “EN” JTAG pad ? Anyone tried that ?

Hello,
I haven’t been working on the project since christmas :frowning: I really don’t remember if I solved the isse with external interrupts, All I remember that it is possible to wakeup from deepsleep using external source, but can’t provide further info. All what I could find in my Code folder was this below, which I copied from somewhere (Don’t even remember from which website) you may try it, if it works. I will come back here to leave a reply if I resumed working on the project and got new expreince

#include "hal/gpio_types.h"
#include "esp_err.h"
#include "esp_sleep.h"
#define uS_TO_S_FACTOR 1000000ULL  //Conversion factor for micro seconds to seconds
#define TIME_TO_SLEEP 20           //Time ESP32 will go to sleep (in seconds)
#define rLed D0                    //red
#define yLed D1                    //yellow
#define gLed D2                    //greed (this should not blink as the board should be in sleep mode)

struct Button {
  const uint8_t PIN;
  uint32_t numberKeyPresses;
  bool pressed;
};

Button button1 = { D6, 0, false };

//variables to keep track of the timing of recent interrupts
unsigned long button_time = 0;
unsigned long last_button_time = 0;

void IRAM_ATTR isr() {
  button_time = millis();
  if (button_time - last_button_time > 250) {
    button1.numberKeyPresses++;
    button1.pressed = true;
    last_button_time = button_time;
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(button1.PIN, INPUT_PULLUP);
  attachInterrupt(button1.PIN, isr, FALLING);
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_21, 1);
}

void loop() {
  if (button1.pressed) {
    Serial.printf("Button has been pressed %u times\n", button1.numberKeyPresses);
    button1.pressed = false;
  }
}

void led_Flash(uint16_t flashes, uint16_t delaymS) {
  uint16_t index;
  for (index = 1; index <= flashes; index++) {
    digitalWrite(LED1, HIGH);
    delay(delaymS);
    digitalWrite(LED1, LOW);
    delay(delaymS);
  }
}```

hi there,
i was struggeling with the external deep sleep too on my xiao esp32c3 and a touch-button, and finally got it working
after lots of searching i found that the code needs a bitmask of the pin number, not the pin number or gpio number
for pin gpio3 it translated to: 1ULL << 3

in the below code i got a fairly long delay wich is only to give me more time to upload changes without pushing buttons so you can totally ignore those delays…

hope this helps.
this is the sleep related code i use in my sketch: (not my complete code)

#define   TouchPin  GPIO_NUM_3

void setup() {
  pinMode(TouchPin,  INPUT);
}

void gotoSleep() {
  Serial.println("going to sleep in 30 sec....");   
  delay(30000); 
  esp_deep_sleep_enable_gpio_wakeup(1ULL << 3,ESP_GPIO_WAKEUP_GPIO_HIGH);  
  Serial.println("going to sleep now"); 
  delay(1000);
  esp_deep_sleep_start();   

}

I have the C3 working as a nice low powered sensor using D0 as the battery monitor, D1 as a binary sensor (w/external pullup - using for a reed switch), D2 and D3 are interrupt sources. Here is the code snippet I use to enable the ints:

esp_deep_sleep_enable_gpio_wakeup((1ULL << 4), ESP_GPIO_WAKEUP_GPIO_HIGH);
esp_deep_sleep_enable_gpio_wakeup((1ULL << 5), ESP_GPIO_WAKEUP_GPIO_HIGH);
esp_sleep_enable_timer_wakeup(config.sleeptime * (unsigned long)1000000);
Serial.flush();
esp_deep_sleep_start();

On interrupt I test the source and act accordingly:
gpio_reason = esp_sleep_get_gpio_wakeup_status(); // C3
motion = 0;
motion |= (gpio_reason & 0x20) ? 0x3 : 0; // Activity on 4 - includes motion error bit
motion |= (gpio_reason & 0x10) ? 0x4 : 0; // inactivity on 5
sendStatus();

This seems to work for me. I’m using the ints from an ADXL345 for activity and inactivity

Wow, Nice It’s like a BLE Sense with WIFI :wink: Great stuff. :+1:
You get any power measurement’s?
I’m attempting the same with the Xiao BLE Sense and its LSM6DS3
using it’s interrupts and low power modes.( I’m NOT streaming the imu data just using Accel readings for sensing motion ie. being picked up. BLE connected , Phone app sends Enable /Disable , reads battery level char , tap detection and Drop or fall detect may Actually mean free-fall detect. (it’s not the fall that kills , It’s that sudden STOP ! :stuck_out_tongue_closed_eyes:
Curious what kinda LOW power numbers can be achieved.
GL :slight_smile:

Thanks. I haven’t measured the actual current in deep sleep, but it should be well under 100pa with the adxl in auto standby and the Serial disabled. As long as it’s running “stone cold” I’m happy.
I still prefer the Sense for wearables because of its all-in-one. With a small 100ma Lipo it still would be good for many days between charges, comparable to any typical wearable.
You’re right on the hit after the fall…lol.

Right! :-),
Well I just picked up a PowerProflier Kit II so I’ll be taking some measurements on this exactly and report any findings. Lots of general stuff out there but thin on any correlation to running code and real word numbers. Simple stuff like the BLE Peripheral and Central example’s as is power baseline profile., It’s a starting point at a minimum. SeeedSudio would be benefactor’s no doubt. Alll the Nordic stuff is geared to there SDK so it’s minimally helpful imo.
I’m trying to switch modes from (motion Sensitivity) to double tap detection with imu on the fly. Ultimately changing it via BLE app.
Onwards… :person_fencing:
GL :slight_smile:




I want to invent something and get one of theses…LOL

Have Fun.

Can you post the complete code which worked for you? Like I have been looking for a solution for a while now but no success getting the correct code.

Here is code I’m using to test the battery and multiple buttons. Works well.

#include "WiFi.h"
#include <PubSubClient.h>

#define DEBUG_ENABLED 0

const char* ssid     = "DronesAreWatching";
const char* password = "";   

const char* mqtt_server = "blue.home";
const char* mqttUser = "internal";
const char* mqttPassword = "";


void debug(String msg){
  if (DEBUG_ENABLED){
    Serial.println(msg);
  }
}

WiFiClient espClient;
PubSubClient client(espClient);

void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  debug("Connecting to ");
  debug(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    debug(".");
  }

  debug("WiFi connected");
  debug("IP address: ");
  // debug(WiFi.localIP());
}

void setup() {
  if (DEBUG_ENABLED){
    Serial.begin(115200);
    delay(100);
  }
  
  pinMode(D0, INPUT_PULLUP);
  debug("Startup...send message");

  setup_wifi();

  client.setServer(mqtt_server, 1883);
  client.connect("ESP8266Client", mqttUser, mqttPassword);

  uint64_t gpio_reason = esp_sleep_get_gpio_wakeup_status(); 
  debug(String(gpio_reason));
  int GPIO = 0;
  if (gpio_reason > 0){
    GPIO = log(gpio_reason)/log(2);
  }
  debug(String(GPIO));


  String GPIOString = String(GPIO);
  int str_len = GPIOString.length() + 1; 
  char char_array[str_len];
  GPIOString.toCharArray(char_array, str_len);

  client.publish("mouse/trigger", char_array);


  esp_deep_sleep_enable_gpio_wakeup((1ULL << 2), ESP_GPIO_WAKEUP_GPIO_LOW);  //GPIO2
  esp_deep_sleep_enable_gpio_wakeup((1ULL << 3), ESP_GPIO_WAKEUP_GPIO_LOW);  //GPIO3

  debug("Going to sleep in 5 seconds"); //time to send message
  delay(5000);

  if (DEBUG_ENABLED){
    Serial.flush();
  } 
  esp_deep_sleep_start();
}

void loop() {
}