Introduction
Properly optimizing energy consumption of battery powered microcontrollers (MCUs) is fundamental to extend their battery life. Questions like when it is better to keep the device idling and when to enter light- or deep-sleep cannot be answered without measuring the power consumption during those sleep modes and the time and energy overhead required to enter them. Similar measurements are also required to evaluate when it is better to stay connected to the WiFi, and when to disconnect and reconnect to upload or download data.
Here I will use the Rhode & Schwarz NGU401 source measure unit (SMU) to take advantage of its fast sampling rate and high dynamic range to evaluate the energy consumption of an ESP32 MCU board running in different operation modes.
Measuring Setup
My plan was to evaluate the energy consumption of an ESP32 board in the following 12 operations modes:
- Idle: Idles for 3 s.
- Computation: Performs integer and floating operations continuously for 3 s.
- WiFi Connect: Connects to the WiFi router.
- WiFi Idle: While connect to the WiFi, it idles for 3 s.
- WiFi Download: TCP-connects to a local CHARGEN server, downloads 1 MB of data and then TCP-disconnects from it.
- WiFi Upload: TCP-connects to a local discard server, uploads 1 MB of data and then TCP-disconnects from it.
- WiFi Disconnect: Disconnects from the WiFi router.
- Light-sleep Overhead: Light-sleeps for 0 s.
- Light-sleep + Delay: Light-sleeps for 3 s.
- Deep-sleep Overhead: Deep-sleeps for 0 s.
- Deep-sleep + Delay: Deep-sleeps for 3 s.
- Reset: Resets the MCU.
I wrote a small ESP32 program that repeatedly switched between these operation modes. The MCU was programmed so that at every switch it generated a 50 ms GPIO pulse as a mark. To log the timing of the operation mode switches I connected and oscilloscope to the GPIO pin and the power input (VCC) of the ESP32 board.
Switching through all operation modes takes ~26 s, so I set the SMU to power the the ESP32 with a signal that supplied 0 V for 0.5 s, followed by 5V for 57 s an finally 0 V for 0.5 s. The VCC signal was captured with the channel 1 of the oscilloscope, while the GPIO signal was captured with the channel 2. The SMU was set to log at 500 ksps while the oscilloscope was set at 100 ksps (6,000,000 points for 60 s).
Measurements
The recording of VCC with both instrument allowed me to synchronize the GPIO waveform to the SMU waveforms.
The waveforms show that the MCU cycled through all the operation modes twice. Both cycles look very similar, except during the WIFI operation modes. To evaluate the power consumption I arbitrarily selected the first cycle.
Evaluation and Analysis
For every operation mode I calculated its duration, the average current, the charge consumption, the average power and the energy consumption. I made all measurements between GPIO falling and rising edges, except for the sleeping operation modes that had a delay. For those I arbitrarily evaluated a single second in the middle of the sleep (to avoid measuring the overhead caused entering or leaving a sleep mode).
Idle : 2999.9 ms, 50.1 mA, 150.2 mC, 250.3 mW, 751.0 mJ
Computation : 3000.0 ms, 71.9 mA, 215.6 mC, 359.2 mW, 1077.7 mJ
WiFi Connect : 2375.2 ms, 151.1 mA, 358.8 mC, 755.2 mW, 1793.6 mJ
WiFi Idle : 2999.9 ms, 59.6 mA, 178.8 mC, 297.9 mW, 893.8 mJ
WiFi Download : 2753.7 ms, 166.5 mA, 458.6 mC, 832.5 mW, 2292.5 mJ
WiFi Upload : 3920.3 ms, 165.5 mA, 648.9 mC, 827.5 mW, 3243.9 mJ
WiFi Disconnect : 1.9 ms, 134.5 mA, 0.3 mC, 672.6 mW, 1.3 mJ
Light-sleep Overhead : 3.0 ms, 127.2 mA, 0.4 mC, 636.0 mW, 1.9 mJ
Light-sleep : 1000.0 ms, 13.2 mA, 13.2 mC, 66.2 mW, 66.2 mJ
Deep-sleep Overhead : 331.9 ms, 50.7 mA, 16.8 mC, 253.7 mW, 84.2 mJ
Deep-sleep : 1000.0 ms, 12.1 mA, 12.1 mC, 60.5 mW, 60.5 mJ
Reset : 330.1 ms, 49.9 mA, 16.5 mC, 249.5 mW, 82.3 mJ
To get more useful values I took the Idle operation mode as the basal power usage of the board and evaluated how the different operation modes increased or decreased it.
Idle : 250.3 mW
Computation : 359.2 mW (+44%)
WiFi Idle : 297.9 mW (+19%)
WiFi Download : 832.5 mW (+233%)
WiFi Upload : 827.5 mW (+231%)
Light-sleep : 66.2 mW (-74%)
Deep-sleep : 60.5 mW (-76%)
With these results it is possible to roughly estimate how to program the MCU to keep energy consumption low. To get a more accurate estimation of when to stay connected to the WiFi or enter a sleep mode, the overhead of entering these operation modes needs to be taken into account.
Let’s answer the question: For what amount of idling time is it better to disconnect in contrast to staying connected? \(\)
\begin{align*}
297.9t &> 250.3t + 1793.6 + 1.3 \\
t &> 37.7
\end{align*}
Above 37.7 s disconnecting from the WiFi to later reconnect when data needs to be transferred will reduce power consumption.
Another way to optimize consumption is by reducing the data traffic (which also would allow the MCU to stay disconnected for a longer period of time). The measured time and energy required to upload 1 MB makes it possible to estimate the requirements for different amounts of traffic. For instance the requirements to upload and download 1 GB are:
Download 1 GB : 2754 s (45.9 m), 2.293 kJ
Upload 1 GB : 3920 s (65.3 m), 3.244 kJ
Let’s evaluate the sleeping modes. When should the MCU just idle, and when should it enter light- or deep-sleep?
\begin{align*}
250.3 t &> 66.2 t + 1.9 \\
t &> 0.01
\end{align*}
\begin{align*}
66.2 t + 1.9 &> 60.5 t + 84.2 \\
t &> 14.4
\end{align*}
For idling times longer than 10 ms, entering light-sleep will save energy, while for idling times longer than 14.4 s, energy can be saved even further by entering deep-sleep.
Conclusion
Optimizing power consumption of MCUs is important when power comes from batteries. MCUs usually provide a wide variety of facilities that help tweak the energy consumption, but in this post, I explored the main operation modes of the ESP32 MCU. I used an SMU and an oscilloscope to measure the energy consumption of an ESP32 board during different operation modes, but probably a better approach would have been to use a logic analyzer, as the waveform of the GPIO port is not relevant.
More than getting hard data, here I just tried one approach to measure energy consumption. To make more meaningful measurements, they must be repeated multiple times (to reduce the error) and ideally with the firmware and environmental conditions as close as possible to the conditions where the MCU is going to be deployed. The WiFi phases for instance showed a noticeable amount of variability in their timing and energy consumption, even when nothing was altered between cycles. Moreover, factors such as the quality of the wireless link and the network and server congestion have a huge impact on the datalink, and as consequence on the amount of energy the MCU consumed.