Speeding up ESPHome Wifi Connections

I ran some experiments on my battery powered gate sensor to reduce the time spent connecting to wifi as the ESP32 wifi radio is very power hungry and chews through batteries quickly.

My project has to wake up, connect, report sensor status via MQTT then go back to sleep. The entire sequence was able to be reduced from 8.1 seconds to 1.8s and crucially an 80% reduction in energy consumed, extending the battery life by 5x! It also lays great groundwork for projects that need more frequent sensor readings to operate indefinitely from relatively small batteries & solar panels.

  • DHCP is not slow if your router is relatively quick and handing out the address. The difference between a static, hard coded IP address and an IP assigned via DHCP was negligible on my network.
  • MQTT is also fast. My project both reads data (whether or not to stay awake for a software update) and then writes data (gate open or closed) within that 1.2 second window.
  • Wifi channel scan is slow. This is the bottleneck and takes several seconds.

Getting rid of wifi channel scan

Wifi channel scan involves tuning the wifi radio to each channel to see if your access point is talking on that channel. In order to bypass this on ESPHome, we need to do several things:

  1. Manually specify the channel in your config
  2. Manually specify the BSSID (MAC address) of your access point
  3. Set the fast_connect flag to skip the channel scan (not possible without 1 & 2)

Your YAML should look something like this:

wifi:
  networks:
  - ssid: !secret wifi_ssid
    channel: 11 
    bssid: !secret wifi_mac
    password: !secret wifi_password
  fast_connect: True

Configuring your access point / router

You need to set the 2.4GHz channel of your wifi access point (or router with built-in wifi) to a fixed channel number and hard code the same channel in your ESPHome YAML config.

Many APs will scan the spectrum and select a channel one with low background noise either periodically (e.g. in the middle of the night) or at boot up. This will cause connectivity loss to your ESPHome project if the channel changes. Instead, I suggest using an app on your laptop or Android phone to scan for neighbours and then manually choose the quietest channel and stick to it. Remember, 2.4GHz channels have very broad, overlapping side lobe frequencies. For best results, you should be setting your access point to only use 20MHz of bandwidth and choosing either channel 1, 6, or 11. This makes it possible to have no overlap with up to 2 other access points in the physical vicinity. Rather use wide bandwidth on your 5GHz radio for high throughput on laptops & phones etc.

Caveats

If you change your access point (which for some people is their ISP supplied router) you will lose access to your ESPHome device!

If your access point fails and needs replacing, you’ll have the same issue. This is where having a way to physically flash the device will be handy, or having a fallback AP mode enabled on your device (though this is also a great way to drain the batteries in a day if your wifi goes down for any reason!!).

Results

Current draw (yellow) during the wake-connect-MQTT-sleep sequence with a basic config (which will do a wifi channel scan), and then repeated on same slow 1 second per division with the fast connect config.

Zooming in to a 5x faster timebase we can measure the current.

Before the improvements we were using a little over a Coulomb for each transaction, compared to just 0.203 C after the optimisation.

I do think the memory depth of my scope is failing to integrate the ~300mA pulses of current drawn by the wifi radio during transmit – the slope of the integral math trace doesn’t appear to get any steeper there. This could partly explain why I’ve seen far shorter battery life than this data would predict.

In theory, if we report in every gate open or close (usually 2 per day) as well as every 6 hours it’s reasonable to assume 5 transactions per day i.e. 5.28 C. The leakage current of the micro at about 80uA plus the 1.5uA draw of my 2.2MΩ pull-up resistor (assume for half the day) totals about 7 C per day. A set of 2000mAh AA batteries should therefore last 2 x 3600 / (5.28 + 7) = 586 days i.e. 1 year & 7 months.

Real world performance

The 4x AA batteries were installed in the catio gate sensor on 27th August 2023 and died on 11th January 2025. That’s 503 days, very close to our prediction!

Now that I’ve implemented the fast connection optimisation, it’s going to be interesting to see just how long the batteries last, but given it’s theoretically 5x longer, we’re going to hopefully be waiting a long time for this result! The fresh batteries went in yesterday 22nd February 2025 so could last until around February/March 2033!

I’ve also increased the 6 hour heartbeat to 18 hours. This is because we open the gate each morning and close it each evening, so it seldom would stay in 1 state for more than 18. Thus we shouldn’t be hitting the heartbeat any more, reducing our number of transactions to just 2 per day in normal use. At this point we could be pushing into the limits of the AA battery shelf life (hopefully)!!

Software updates

Notice how the battery life dropped suddenly in January 2025?

I updated the software in December 2024 on my letterbox and chewed through a set of batteries in a month (after previously clocking over a year, just like the catio gate). I also updated the catio gate software in January 2025. It turns out that something changed in ESPHome that (in combination with my YAML at the time) increased the time spent awake substantially. Specifically, deep sleep was taking up to 5 failed attempts to occur (likely a race condition).

Updating software again and removing the command to shut down the ADC (which is no longer supported) resolved this issue.

It’s also worth noting that the software update process takes 10s of seconds or more. This is both due to the non-trivial file upload time and the up to 15 seconds (repeated for failed attempts) as I put the ESP into OTA update mode and attempt to trigger an update within 15 seconds (a manual race condition). Thus a software update can burn up potentially 5-10 C in one go. That’s several days of normal usage.