In summer, I have a lot of potted plants out on the balcony, and I need to know when to water them. Indoors, most of my home automation gadgets are based on MySensors, but out on the balcony the signal is too weak, so I needed something WiFi-based, but without the high battery consumption typical of WiFi solutions.
This was an opportunity to learn about optimizing a WiFi based gadget for low power consumption, and I will share my insights with you here.
Building blocks
The solution consists of
- an ESP32 module with custom software
- a cheap plastic case protected by an upside-down Ziploc bag
- a pair of AAA batteries
- up to 4 cheap capacitive soil moisture sensors, of the kind you find on Aliexpress for less than a Euro
- my home network, with a DHCP server assigning pseudo-static IP addresses to everybody (based on MAC address)
- my home automation system, with an MQTT broker and OpenHAB for visualization and control
As always, full documentation including source code, hardware schematic and a requirements specification can be found on Github.
Design decisions
How to make it waterproof-ish
There will be rain out on the balcony, so the modules need to be waterproof-ish. Real waterproof sealed cases are expensive, so I opted for a cheap plastic case with a Ziploc bag over it, with the opening facing down … good enough for the intended use case.
Processor
The final design uses an ESP32-WROOM module.
I also tried a ESP32-C3 “Super Mini” module, the source code supports this. This is a single core RISC-V based processor, with the following pros and cons, compared to the ESP32:
- Pro: lower current draw when WiFi is on, I observed about 50 mA vs 130 mA
- Pro: easy to use the little development module in a production system, because it has no USB-serial chip that would consume power all the time, the ESP32-C3 has builtin USB capability
- Con: higher current draw during sleep, I measured about 40µA
- Con: unreliable WiFi connection. I think this is probably a property of the module rather than the ESP32-C3 chip, because of the tiny antenna — but that was a knockout criterion for me
Minimizing power consumption
- a bare ESP32-WROOM module is better than a development module — no power-consuming voltage regulators and USB interfaces. Power consumption during deep sleep, with a bare ESP32-WROOM, powered from 2x AAA battery, is 14µA.
- To avoid any power loss through a voltage regulator, I am running the ESP32 directly from a pair of AAA batteries. Newer processors will work down to 2.3V, I just had to make sure the soil moisture sensor also works below 3V (see below).
- to minimize the time the processor is awake, and in particular the time that Wifi is active, I try to reconnect to Wifi using previously established SSID, IP and channel number, which are cached in RTC memory.
Hardware
I used a 7×9 cm prototype board for ESP32 and ESP8266 boards, cut to fit inside a 100x60x25 mm plastic case. The soil sensors are connected via cables with an RJ12 6P4C connector on the module end, for easy connection “in the field”.
The capacitive soil sensors I got from Aliexpress use an NE555 chip that only works down to 3.0V, whereas the ESP32 itself will still work when the battery voltage is as low as 2.5V, so I replaced the NMOS NE555 with the CMOS version ILC555D, which work down to 2.0V. I also bypassed the voltage regulator on the sensor board.
Battery life
These factors contribute to power consumption or battery drain, in decreasing order of importance:
1. the self-discharge of the AAA batteries, according to this post, about 35 µA or 0.84 mAh per day
2. deep sleep, at ~14 µA or 0.34 mAh per day
3. wake time with WiFi on, up to 130 mA x ~300ms per wakeup every hour or 0.26 mAh per day
4. wake time, with WiFi OFF, 50 mA x ~300ms per wakeup or 0.10 mAh per day
This results in a battery life in excess of 500 days, good enough for me. Note that I have brought the design to the point where overall power consumption is dominated by the self-dischange of the Alkaline batteries, so there is no point in attempting to further optimize the power consumption of the processor module.
Lessons learned
Some things are outside of my control
The performance of the device, in terms of power consumption or battery life, depends of course on the design of the device itself and the design decisions I made (processor, program flow, etc.), but also on external factors that I cannot control. For example, power consumption depends on wake time, which is the aggregate of
- the time between turning on sensor power, and making measuring the sensor voltage — I chose 100ms, which appears to be enough for the sensor voltage to settle
- the time to re-connect to the WiFi access point, using stored information about WiFi channel, SSID etc — this takes about 160ms most of the time, but sometimes can take as much as 2-3s
- the time to look up the IP address for the MQTT broker, usually 20-40ms
- the time to connect to the MQTT broker, mostly 30ms, but sometimes up to 500ms, which I can’t explain
- the time to send MQTT messages — I can influence this, by deciding how much information to send
- the time to disconnect from the WiFi access point — mostly about 20ms, but sometimes as high as 130ms, which I can’t explain
An almost easy project
I found it fairly easy to create a first version of the code that sort of worked most of the time. Then I began to notice the rough edges, and it took a lot of time to get those fixed:
- easy: making measurements and reporting them via MQTT. Harder: get the measurements to be less jittery, and less affected by varying current consumption due to WiFi activity. I now get all the ADC measurements done before turning on WiFi.
- allow configuration changes via MQTT, and acknowledge the command by deleting the topic. Easy: get it to work most of the time, with occasional loss of a message. Harder: make it work every time, by inserting delays here and there, without a massive increase in the overall wake time