NodeLab: What Does One Extra Second Awake Cost a Battery-Powered ESP32 Sensor?

Share
NodeLab: What Does One Extra Second Awake Cost a Battery-Powered ESP32 Sensor?

Measuring how ESP32-C3 awake time affects the number of successfully received sensor updates from 500 mAh and 1100 mAh Li-Po batteries.

How long is one second?

It is a good question, but the answer is relative. The perception of one second is very different depending on which side of the toilet door you find yourself. :)

When it comes to battery-powered electronics, one second can also be surprisingly expensive.

I have built small battery-powered sensors for many years, starting with Atmel/Arduino processors, then ESP8266 devices and, more recently, ESP32s. One of the recurring questions is always the same:

How do I get more useful work out of the same battery?

For this experiment I wanted to look at something very specific. If a sensor wakes once per minute, takes its readings, transmits the data and goes back to deep sleep, how much difference does one additional second of being awake actually make?

The test

The hardware remained the same throughout each test series. I used a Seeed Studio XIAO ESP32-C3 with a DHT22 temperature and humidity sensor and a simple voltage-divider battery monitor.

I repeated the experiment with two Li-Po battery capacities: 500 mAh and 1100 mAh.

The sensor operated on a one-minute cycle. It woke, updated the required values, remained awake for the programmed period and then entered deep sleep for the balance of the minute.

The variable I changed was the awake period, from seven seconds down to three seconds.

The transmission figures used in this article are successfully received updates recorded by Home Assistant, rather than simply a local counter of attempted transmissions.

It is also important to note that this experiment measures the whole working sensor system, not merely the ESP32-C3 itself. The measured endurance therefore includes the XIAO board, Grove Shield, DHT22, voltage-divider circuit, Wi-Fi connection process and ESPHome software stack.

Configuration

Component Description
Processor XIAO ESP32-C3
Breakout board Grove Shield for XIAO
Battery 3.7 V, 500 mAh Li-Po
3.7 V, 1100 mAh Li-Po
Battery monitor Voltage divider, 2 × 1 MΩ
Sensor DHT22
Transmission interval 1 transmission per minute
Power strategy Awake → deep sleep → repeat

For the seven-second test, for example, the ESPHome configuration deliberately kept the unit awake for seven seconds and then put it into deep sleep for 53 seconds.

esphome:
  name: c3
  friendly_name: c3
  on_boot:
    priority: -100
    then: # Total: 7s
      - delay: 4s
      - component.update: read_counter
      - delay: 1s
      - component.update: xiao_dht
      - delay: 1s
      - component.update: xiao_bat
      - delay: 1s
      - deep_sleep.enter:
          id: deep_sleep_control

esp32:
  board: seeed_xiao_esp32c3
  framework:
    type: arduino

deep_sleep:
  id: deep_sleep_control
  sleep_duration: 53s

sensor:
  - platform: dht
    model: DHT22
    id: xiao_dht
    pin: 4
    update_interval: never
    temperature:
      name: "Temperature"
    humidity:
      name: "Humidity"

  - platform: adc
    name: "Battery"
    id: xiao_bat
    pin: 3
    attenuation: 12db
    sampling_mode: avg
    samples: 50
    update_interval: never
    unit_of_measurement: "V"
    accuracy_decimals: 1
    icon: mdi:battery-medium
    filters:
      - multiply: 2.049

  - platform: template
    name: "Counter"
    id: read_counter
    update_interval: never
    accuracy_decimals: 0
    lambda: |-
      id(temp_counter)+=1;
      return id(temp_counter);

globals:
  - id: temp_counter
    type: int
    restore_value: true
    initial_value: '0'

For the shorter awake-time tests, the awake and deep-sleep periods were adjusted while keeping the complete cycle at approximately one minute.

Results

Date Battery Awake time Transmissions Approx. runtime
25-03-26 500 mAh 7 s 3,095 2.15 days
25-03-30 500 mAh 6 s 4,275 2.97 days
25-04-02 500 mAh 5 s 4,524 3.14 days
25-04-14 500 mAh 4 s 4,840 3.36 days
25-04-30 500 mAh 3 s 5,184 3.60 days
25-05-08 1100 mAh 7 s 6,790 4.72 days
25-08-24 1100 mAh 6 s 8,907 6.19 days
25-08-12 1100 mAh 5 s 9,072 6.30 days
25-08-03 1100 mAh 4 s 9,093 6.31 days
25-09-07 1100 mAh 3 s 9,107 6.32 days

What does this mean for real-life applications?

The results above show how many one-minute cycles each battery completed under the specific test conditions.

It is tempting to take those cycle counts and directly extrapolate them to much longer reporting intervals.

For example, if a sensor only transmitted once per hour instead of once per minute, a simple cycle-count calculation would suggest much longer operating times.

A simple calculation based purely on the number of completed transmission cycles gives:

  • 500 mAh: approximately 216 days at 3 seconds awake, falling to about 129 days at 7 seconds awake.
  • 1100 mAh: approximately 379 days at 3–5 seconds awake, falling to about 283 days at 7 seconds awake.

However, these figures do not represent measured or predicted real-world battery life.

The original experiment used a one-minute cycle, so each wake cycle was followed by less than one minute of deep sleep. If the transmission interval were extended to one hour, the sensor would spend roughly another 59 minutes in deep sleep between each update.

Deep sleep still consumes energy.

The actual battery life at an hourly reporting interval would therefore depend on the deep-sleep current of the complete sensor system, including the board, regulator, Grove Shield and any connected circuitry.

The extrapolation is useful for illustrating how the measured cycle counts scale, but it cannot tell us how long the sensor would actually run.

That raises another useful question for a future experiment:

At what reporting interval does deep-sleep current become the dominant factor in battery life?

So, what did one second cost?

The first thing the results make very clear is that there is not a simple fixed cost per second.

The jump from seven seconds to six seconds was enormous

With the 500 mAh battery, reducing the awake period from seven seconds to six increased the number of transmissions from 3,095 to 4,275.

That is 1,180 additional transmissions, or about 38% more.

The 1100 mAh battery showed almost exactly the same behaviour. It increased from 6,790 to 8,907 transmissions.

That is 2,117 additional transmissions, or about 31% more.

One second clearly mattered.

But then things became more interesting.

The benefit was not linear

For the 500 mAh battery, reducing awake time continued to produce useful improvements:

Change Additional transmissions Improvement
7 s → 6 s +1,180 +38.1%
6 s → 5 s +249 +5.8%
5 s → 4 s +316 +7.0%
4 s → 3 s +344 +7.1%

Going all the way from seven seconds to three seconds increased the total from 3,095 to 5,184 transmissions.

That is an improvement of approximately 67.5% from the same nominal 500 mAh battery.

The 1100 mAh results were quite different:

Change Additional transmissions Improvement
7 s → 6 s +2,117 +31.2%
6 s → 5 s +165 +1.9%
5 s → 4 s +21 +0.2%
4 s → 3 s +14 +0.2%

Once the 1100 mAh setup reached about six seconds, reducing the programmed awake time further made almost no difference.

From six seconds to three seconds the total only increased from 8,907 to 9,107 transmissions — just over 2%.

That is probably the most interesting result in the entire experiment.

Bigger battery, more transmissions — but not always in direct proportion

The 1100 mAh battery has 2.2 times the nominal capacity of the 500 mAh battery.

At seven seconds, the measured result followed that almost perfectly:

  • 500 mAh: 3,095 transmissions
  • 1100 mAh: 6,790 transmissions
  • Ratio: approximately 2.19×

At shorter awake periods, however, that relationship changed.

Awake time 500 mAh 1100 mAh 1100/500 ratio
7 s 3,095 6,790 2.19×
6 s 4,275 8,907 2.08×
5 s 4,524 9,072 2.01×
4 s 4,840 9,093 1.88×
3 s 5,184 9,107 1.76×

So battery capacity alone does not explain all of the observed behaviour.

What can I conclude from this test?

There are a few things the measurements support quite strongly.

First, awake time matters. A battery-powered ESP32 that wakes frequently should do what it needs to do and return to deep sleep as quickly as practical.

Second, the cost of an additional second is not linear. I cannot take these results and say that every extra second costs a fixed number of transmissions.

Third, the seven-second tests stand out on both battery sizes. Removing that one second produced by far the biggest improvement in each test series.

That suggests there may be more happening than simply one additional second of processor current consumption.

And fourth, there appears to be a point of diminishing returns.

This is particularly obvious with the 1100 mAh battery. Below approximately six seconds, shortening the programmed awake period made very little difference to the final number of transmissions.

What this experiment does not prove

There are some important limitations.

These were practical battery-life tests, not laboratory power measurements. I measured the number of successfully received Home Assistant updates from a charged battery until the sensor stopped operating.

I did not measure the instantaneous current profile during each wake cycle.

I therefore cannot use this data alone to say exactly where the energy was consumed — CPU operation, Wi-Fi startup, association, transmission, sensor readings, ADC sampling, ESPHome overhead, or something else.

The two battery-capacity series were also performed at different times. The 1100 mAh tests span several months. That means battery condition, Wi-Fi conditions, software changes, temperature or other environmental factors could have influenced the absolute results.

And nominal battery capacity is just that: nominal. Two different Li-Po batteries should not automatically be expected to deliver their entire labelled capacities in exactly the same way before the electronics reach their minimum usable voltage.

So I would be cautious about treating the 500 mAh and 1100 mAh results as a precise battery-capacity comparison.

What is useful is the overall pattern, and the understanding that awake time does not equal airtime.

I originally thought of the variable as time-on-air.

That is not quite right.

In radio terminology, airtime is specifically the period during which the radio occupies the channel transmitting data. My ESPHome code was not directly controlling that. I was changing how long the complete ESP32-based sensor system stayed awake before entering deep sleep.

That includes much more than the actual transmission itself.

What does one extra second of awake time cost a battery-powered sensor?

And the answer, based on these results, is:

Potentially quite a lot — but it depends where that second is being spent.

The next question

The obvious next step is to stop looking only at battery endurance and look inside the wake cycle itself.

I would like to measure the current draw from the moment the ESP32 wakes until the moment it goes back to sleep and identify exactly where the energy goes:

  • booting the ESP32;
  • starting Wi-Fi;
  • connecting to the network;
  • reading the DHT22;
  • sampling the battery voltage;
  • transmitting the data;
  • remaining connected; and
  • entering deep sleep.

That would allow me to put an actual energy cost against each part of the cycle.

It would also make it possible to measure the deep-sleep current of the complete sensor system and determine how much that matters as the reporting interval becomes longer.

Because after doing this experiment, the question is no longer simply:

How expensive is one extra second?

The much more useful question is:

What is the ESP32 doing during that second?

And that sounds like another NodeLab experiment.