Electronic – arduino – ESP32 (WROOM32) consuming ~77 µA (much too high!) in deep sleep

arduinoesp32low-power

I tried to reduce the current consumption of a ESP32 in deep sleep with the ULP enabled. However, the best I can achieve is about ~77 µA of current consumption. I'm using a very minimalistic carrier board (schematic) together with a WROOM32 ESP32-module, which has only 2 pull-up resistors for the 2 needed switches (RESET / GPIO0). I use an external 3.3V-linear regulator and I'm measuring the current that flows out of this regulator.

The program basically starts a ULP program, that has wakeup-period of 1 second set and then goes to deep sleep. The ULP program is 5 instructions long (no loops) and finally calls 'HALT'. So, the ULP should halt almost instantly and wait for the next RTC wakeup after 1 second.

What I've tried so far:

  • I tried to call rtc_gpio_isolate(GPIO_NUM_12); and rtc_gpio_isolate(GPIO_NUM_15); which did not resolve the issue.
  • Then I reduced the program to not start the ULP and instead use only RTC-Timer wakeup using esp_sleep_enable_timer_wakeup(1000000*600); before sending it to deep sleep. This did not change anything. So the ULP seemed not to be the issue…

ESP32 High Power Consumption in Deep Sleep Mode

Best Answer

I revised my measurement setup:

  • measuring the voltage drop over a 1 kOhm resistor put in series with the ESP32s GND connection using a oscilloscope
  • the resistor is shorted during the ESP32's startup to allow it to draw enough current during startup
  • the oscilloscope uses 10:1 probes. Hence, I set the oscilloscope to 1:0.01 probes and the channels unit to A(mpere). So it directly converts the units correctly and displays the current that flows through the resistor. Without the ESP32 (but still the voltage regulator connected) the oscilloscope shows near 0A (<200nA, so this should be close enough) and when the ESP is connected and in deep sleep it measured ~77 µA or ~84 µA on average - depending on the some settings in software.

I did several tests:

  • adc_power_off() - no effect on current drawn (seems to be disabled by default)
  • rtc_gpio_force_hold_dis_all() - no effect on current drawn
  • rtc_gpio_isolate(GPIO_NUM_0 - …) - reduced current from ~84 µA to ~77 µA; however the current then has a periodic sine pattern (seems to be 50 Hz interference from the power grid).
  • esp_sleep_enable_timer_wakeup() -

FINAL SOLUTION:

NOT WORKING: Calling rtc_gpio_isolate() for GPIO12 and GPIO15 is the suggested in the internet (e.g. Espressif's docs or another Espressif example, also some non-Espressif code that I can't find right now).

Since this did not work, I was calling this function for -ALL- RTC GPIOs, which seems to cause different issues for other pins. I believe due to floating input connections of pins in input mode or something like this. BUT, Instead calling gpio_reset_pin() on all RTC GPIO PINS did resolve it! According to the docs this will "Reset an gpio to default state (select gpio function, enable pullup and disable input and output)."

Further research showed that I needed only to call gpio_reset_pin() for gpio_reset_pin(GPIO_NUM_2); (note not 12, but 2!) to achieve the same result. And finally also rtc_gpio_isolate(GPIO_NUM_2); does achieve the same result - but not when calling rtc_gpio_isolate() for all the other GPIO pins too...

Result:

~7 µA current consumption (long term average)... that's even below 10 µA from the specs. Yeah! This also works when the ULP is enabled. While the ULP is enabled the current consumption shoots up to ~230 µA and then decreases to 7 µA again when the ULP is in HALT-state (until its again woken up be the configured RTC period).

This is the code I used to reset all the pins:

gpio_reset_pin(GPIO_NUM_0);
gpio_reset_pin(GPIO_NUM_2);
gpio_reset_pin(GPIO_NUM_4);
gpio_reset_pin(GPIO_NUM_12);
gpio_reset_pin(GPIO_NUM_13);
gpio_reset_pin(GPIO_NUM_14);
gpio_reset_pin(GPIO_NUM_15);
gpio_reset_pin(GPIO_NUM_25);
gpio_reset_pin(GPIO_NUM_26);
gpio_reset_pin(GPIO_NUM_27);
gpio_reset_pin(GPIO_NUM_32);
gpio_reset_pin(GPIO_NUM_33);
gpio_reset_pin(GPIO_NUM_34);
gpio_reset_pin(GPIO_NUM_35);
gpio_reset_pin(GPIO_NUM_36);
gpio_reset_pin(GPIO_NUM_37);
gpio_reset_pin(GPIO_NUM_38);
gpio_reset_pin(GPIO_NUM_39);

My best guess is that the isolate call does completely disconnect the inputs while the reset call additionally activates the pullup, which prevents interferences to be captured by the 'isolated' inputs causing continuous flipping of the inputs between high and low, which consumes some energy in the pins input logic and also causes those 50 Hz sinusoidal fluctuations.

So far I've no idea what's up with the GPIO_NUM_2 pin. There is nothing connected to it, nor should there be any special usage of the pin per default.