Good news regarding power consumption for pin-wakeup from deepsleep

Hi folks,

Quite a few of you around here use deepsleep with pin wakeup: most importantly esp_sleep_enable_ext0_wakeup or esp_sleep_enable_ext1_wakeup. As many of you know, by default this increases the power consumption many-fold, with most V3 boards seeing a jump from roughly 20uA to 120uA which is rather painful.
After some digging around today, I have managed to tackle this problem with help from this issue.

A normal sketch to put the VME213 into deepsleep with wakeup from the user-button would look like this:

void deepsleep() {
  esp_sleep_enable_ext0_wakeup((gpio_num_t)21, LOW); // configure pin 21 as wakeup on LOW signal
  esp_deep_sleep_start();                            // start deepsleep
}

The Arduino-ESP32 package however automatically adds internal pull-up resistors on esp_deep_sleep_start, which are unnecessary as Heltec already integrated these into their design. As such, this should be ‘blocked’ in your code. The solution looks like this:

void deepsleep() {
  esp_sleep_enable_ext0_wakeup((gpio_num_t)21, LOW); // configure pin 21 as wakeup on LOW signal
  pinMode(21, OUTPUT);
  digitalWrite(21, HIGH);                            // set pin 21 to HIGH manually
  gpio_hold_en((gpio_num_t)21);                      // force pin 21 to stay HIGH
  gpio_deep_sleep_hold_en();                         // force all pins to keep their state during deepsleep
  esp_deep_sleep_start();                            // start deepsleep
}

Now enjoy zero additional power consumption during deepsleep!

Note that this applies to all V3 boards, not just the VME213 mentioned in the example!

Edit: refer to comment 8 for a crucial line to make this work in the Heltec_ESP32 framework.

4 Likes

@bns Thanks for the information. This is very promising. I wonder if you could share what library I need to use to be able to use gpio_hold_en(). Thank you!

I tried compiling my sketch for the “Vision Master E213” as per Heltec’s package for Arduino, v3.0.2 - it compiled without any problems. So I don’t know what happens on your side.

However, I myself use the plain Arduino-ESP32 board support package (not the Heltec package). The standard ESP32 core for Arduino also includes the “Heltec Vision Master E213” as a selectable board. You will lose the Heltec libraries in that case.

@bns Thank you! I am still having issues with finding where are these two functions are defined?
Could you share what #include files did you have for your Heltec’s package for Arduino, v3.0.2? Also, if I decide to switch to ESP32 core for Arduino boards what do #include in your sketch file?

I get erros thae these two functions are not found:
gpio_hold_en((gpio_num_t)21);
gpio_deep_sleep_hold_en();

Errors:
private/var/folders/dc/r6swdg9d5k155xk5yh0gjvfw0000gn/T/.arduinoIDE-unsaved2025320-34444-fe20th.r0qh/RTC_counter/RTC_counter.ino:26:3: note: suggested alternative: ‘rtc_gpio_hold_en’
gpio_hold_en((gpio_num_t)21); // force pin 21 to stay HIGH
^~~~~~~~~~~~
rtc_gpio_hold_en
/private/var/folders/dc/r6swdg9d5k155xk5yh0gjvfw0000gn/T/.arduinoIDE-unsaved2025320-34444-fe20th.r0qh/RTC_counter/RTC_counter.ino:27:3: error: ‘gpio_deep_sleep_hold_en’ was not declared in this scope
gpio_deep_sleep_hold_en(); // force all pins to keep their state during deepsleep
^~~~~~~~~~~~~~~~~~~~~~~
/private/var/folders/dc/r6swdg9d5k155xk5yh0gjvfw0000gn/T/.arduinoIDE-unsaved2025320-34444-fe20th.r0qh/RTC_counter/RTC_counter.ino:27:3: note: suggested alternative: ‘rtc_deep_sleep_start’
gpio_deep_sleep_hold_en(); // force all pins to keep their state during deepsleep
^~~~~~~~~~~~~~~~~~~~~~~
rtc_deep_sleep_start

I didn’t need to include anything, they are part of the core. What version of the Heltec core do you use?

Arduino Board Manager Shows: Heltec ESP32 Dev-boards 3.0.2 Installed
Arduino Library Manager Shows: Heltec ESP32 Dev-boards 2.1.2 Installed

What am I missing? Thanks.

What board do you select? Please show a screenshot of the Tools > Board > Heltec menu (not the Select Board and Port menu thingy, that one doesn’t show enough info).

Hi bns, I ran into the same issue as Sailor007. I saw that you solved it — could you please share how you implemented it in the E213 deep sleep example? Thanks a lot!

Right… after an hour of debugging, I found the reason: the gpio.h file included in the Heltec_ESP32 package is not the gpio.h file that is typically used. The real gpio.h file can be found here.

I am not sure if the file in the Heltec_ESP32 package is just a really really old version of the same file, or if it’s a completely different file altogether. It does look however like the Heltec package is missing crucial parts of the Arduino framework or running on a very old version of that framework. Calling out @Supporter here to check this out, please!

For the time being, this can be mitigated by adding the following line in your sketch:

#include <../include/driver/gpio.h>

(The reason why it worked for me is that I had included a library that added the above line itself, which is why it appeared to work for me like usual.)

There is the alternative explanation - use the standard ESP32 BSP (which is what quite a few of us do) and the code in the first post.