Ramblings of an aging IT geek
← Ramblings of an aging IT geek
hardware

a back-garden weather station, held together with hope and a BME280

Building an ESP32 weather station that logs temperature, humidity and pressure to a local server, and the deep-sleep power tuning that kept it alive for more than a day.

An ESP32 board wired to a small sensor on a breadboard

I have a weather station in the back garden now. It mostly works, which for a first hardware project running off a battery in a British November is a higher bar than it sounds. It reads temperature, humidity and pressure every few minutes, posts them to a little server in the loft, and then goes back to sleep. The going-back-to-sleep part is the whole project, really. Everything else was an afternoon.

The hardware is unglamorous and that's deliberate. An ESP32 dev board, a BME280 sensor on the I2C bus for temperature, humidity and pressure, an 18650 cell, and a cheap TP4056 charging board so I can top it up without unscrewing the box. The BME280 is the sort of part that makes you feel briefly competent: four wires, a well-supported library, sensible readings within seconds. I had numbers on the serial monitor before I'd finished my tea.

temp=8.42C  humidity=87.1%  pressure=1009.3hPa

That 87% humidity is, of course, correct. It is November and I live in England.

the part that nearly didn't work

The naive version drained the battery in under a day. The ESP32's WiFi radio is hungry, and a board sat in a loop reading a sensor and holding a connection open will happily flatten an 18650 overnight. The fix, the thing the whole exercise is actually about, is deep sleep.

The pattern is: wake, read the sensor, connect to WiFi, post the reading, then put the chip into deep sleep with a timer to wake it again. In deep sleep the ESP32 pulls a few tens of microamps instead of the hundred-plus milliamps it draws with the radio up. The difference is roughly three orders of magnitude, which is the difference between a day and a fortnight.

esp_sleep_enable_timer_wakeup(5 * 60 * 1000000ULL); // 5 minutes, in microseconds
esp_deep_sleep_start();

Two things bit me here. First, deep sleep is a full reset, not a pause: execution restarts from the top of setup() on wake, so anything you want to survive has to live in RTC memory or be re-derived. That's fine once you expect it, baffling for an hour if you don't. Second, the slowest part of every wake cycle is the WiFi association and DHCP, not the sensor read. Caching a static IP and the channel shaved the radio-on time from around eight seconds to under three, and at these duty cycles the time the radio is awake is almost the entire energy budget.

A multimeter reading the board's sleep current on a breadboard

mostly works

The "mostly" is honest. The enclosure is a plastic box with holes drilled in the wrong places and a Stevenson-screen ambition it does not live up to, so direct sun would skew the temperature if we got any, which we don't. The pressure trend tracks the Met Office nicely, which is oddly satisfying to confirm with your own hardware. And the battery now lasts the thick end of two weeks per charge, up from less than a day, purely from being disciplined about when the radio is allowed to be on.

That's the lesson I'm taking from it. On a battery-powered radio device, the firmware is mostly a power-management problem wearing a sensor costume. The reading is easy. Deciding when to be awake is the engineering.