Ultra low power design with ESP32 – 10 ways to do it right

Have you experienced your ESP32 modules going burning hot when running absolutely no work load? All at the same time when Espressif claims that the chip is really low power? Well - every chip is really low power these days if you know how to cut down on power consumption the right way. In here, we explore 10 ways of getting low power design with ESP32 right, in a decreasing order of priority.

low power design esp32

1. Calm those cores down!

The ESP32 does not always need to operate in beast mode! You do not usually need 240MHz x 2 worth of grunt to blink an LED.

You need to realize that in MOST applications, the ESP32 is going to be doing nothing at all except waiting for something to happen. That's what real-time systems do!
If your application is somewhat like this - scale the core frequency down to 80 MHz. That usually does the business really well.

2. Manage with one core

The problem with microcontrollers is that their power consumption does not go down when you stop performing calculations. You burn almost the same amount of power running an empty while loop as you would burn with some heavy processing.

So when you feel that your application is capable of working on one core - go for it. Crush and push your application into that one core and shut the other down to save power. In most applications, it is better to have one core running at 160MHz and being 60% busy than running 2 cores at 160 MHz each and keeping them 30% busy each.

3. Maintain radio silence

If you think about the inverse square law of radiation and then think about Wi-Fi data rates and range - you would realize that the radio is probably dumping away more juice than the cores are.

Do you need to keep scanning for a Wi-Fi SSID 10 times a second? Isn't that a little impractical? But well, that's what you might be doing!
Try to keep the radio in control and stop it snowballing your power consumption figures while you tear your hair out trying to optimize your code and I2C pull-up resistors!

4. Forget LwIP BSD-style socket APIs

Yes, they are easy to code. But they are meant for always-on systems and are no way the best way to code energy-efficient solutions. You will absolutely need to get down to the raw networking APIs to cut down on "blocking" time that sequential APIs enforce on you.

Having the flexibility to add reasonable time-outs to all your networking operations will significantly help reduce power consumption. Being able to measure time also lets you make intelligent decisions.

In a battery powered application, if sending one TCP packet with acknowledgement takes 3 seconds (when you know it should take 200ms), isn't it a good idea to just shut down and try again later rather than have the socket API take forever to send the data out?

5. Know your antenna

The LNA pin impedance of the ESP32 is not exactly 50 ohms. If you are trying to use a 50 ohm antenna directly tied to the LNA pin with no matching network, you will still be able to have proper communication - however, because of poor power transfer characteristics to the antenna, you will end up having low range and sensitivity.

This in turn means that you lost the opportunity to use a lower RF output power for the same range and potentially also suffered from data re-transmission when it was not even needed.

6. Switch off what you do not need

Instead of relying on the drivers in ESP-IDF (the SDK for ESP32), we highly recommend having your own set of APIs that write to the DPORT registers directly and can switch off any peripherals that are not required in your application. Turning off peripherals that you do not need can save a lot of power.

7. Use the cache right

The data and instruction caches make it really easy to prevent unnecessary fetch cycles from the flash memory. The flash memory is a power hungry device in itself when you consider ultra low power applications. Not only that, the serial interface to the flash also means additional clock and processing overhead as well.

By placing code in RAM or avoiding wild jumps, you can reduce flash access events and tune your power consumption down to a lower level. This can be very tricky - but very beneficial to an always-on application in the long run.

8. Shut the bootloader up

You do not always need a ton of log output. Adding logs not just takes up a lot of memory, but also wastes time sending data out over UART.
You can check the flash memory content sanity once in every 50 boot cycles if your application does not implement OTA or write data to the flash chip. There is no point being so paranoid that you checksum the flash content after every 5 seconds of deep sleep...

Find out if your bootloader is too paranoid. If it is, make sure you make it skip checking the flash contents and partitions every time it wakes up. Flash memory is usually very reliable if you do things right!

9. Put the peripherals to bed

Remember to turn off all other peripherals such as OLED displays or other sensors if you have them on board. If not that, put them to a low speed mode. This includes the flash memory chip and serial SRAM as well!

If you need to communicate with sensors or other peripherals when your ESP32 is sleeping, the last tip is for you!

10. ULP co-processor to the rescue

Sometimes it is very easy to just run everything off of the ULP co-processor itself.

Need to display battery level on an OLED display? Need to wake up when temperature changes? Get the ULP processor to do it! Don't wake the cores up.
You don't usually need to bring a tank to a stone fight.

As always...

Hope you enjoyed the article! If you are ever stuck developing an ESP8266 or ESP32 based solution - you know what to do... Contact Us!
We love discussing electronics design, there is always a lot to learn.
Scroll down and SUBSCRIBE to our articles from the footer of this page if you would like to read more articles from us directly from your inbox.

2 thoughts on “Ultra low power design with ESP32 – 10 ways to do it right”

  1. Can anybody tell me where approx 800uA is going when I call esp_deep_sleep_enable_timer_wakeup() & esp_deep_sleep_start() on a “WeMos LOLIN32 lite”.

    I end up with 890uA, it should be much less than 100uA…

    1. Everything matters when you are down to micros. You have to put the flash to sleep and also make sure GPIOs are in proper states. Also, check RTC configuration, better to configure deep sleep properly before going to deep sleep. Don’t just set the timer and put it to sleep, might leave something out!

Leave a Reply