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

a weather station held together with an ESP32 and optimism

Building a garden weather station on an ESP32 with deep sleep and MQTT, and the soldering, brown-outs and humidity bugs that came with it.

A soldering iron and electronics on a workbench

I now know the temperature in my garden to a tenth of a degree, which is information I have never once needed and was nonetheless absolutely determined to have. The project was an ESP32 reading a temperature, humidity and pressure sensor, sleeping most of the time, and posting readings over WiFi to the MQTT broker that already runs in the house. It mostly works. The "mostly" is where all the interesting bits live.

the parts, and why these parts

The brains are a bog-standard ESP32 dev board, the kind that costs less than a pint and has WiFi built in. The sensor is a BME280, which gives temperature, humidity and barometric pressure over I2C in one tidy little package. Power is a single 18650 cell with a small boost converter, because I wanted the thing to live in a box at the bottom of the garden and not be tethered to the mains.

The whole appeal of the ESP32 for this is deep sleep. The chip is a power-hungry little thing when its radio is on, but in deep sleep it draws microamps. So the design is: wake up, read the sensor, connect to WiFi, publish, go back to sleep for a few minutes. Done right, a battery lasts weeks. Done wrong, which is how I started, it lasts a long weekend.

#define uS_TO_S 1000000ULL
#define SLEEP_SECONDS 300

void goToSleep() {
  esp_sleep_enable_timer_wakeup(SLEEP_SECONDS * uS_TO_S);
  esp_deep_sleep_start();
}

The trick that catches everyone is that the WiFi connection is by far the most expensive part of the cycle, in both time and current. So you want to be ruthless: connect, publish, disconnect, sleep. Don't sit there with the radio on waiting for anything. Every second of associated WiFi is battery you're not getting back.

A close-up of a circuit board and sensor

the soldering, which is not my craft

I will be honest about the assembly. I am a software person who solders the way I imagine a plumber writes code: it holds, it doesn't leak, and a professional would wince. My joints on the first board looked like little grey volcanoes. One of them was a cold joint on the sensor's I2C line, which produced the most baffling class of bug: the thing worked fine on the bench, where it was warm and undisturbed, and then dropped readings once it was outside in the cold and the joint contracted just enough to lose contact.

That cost me an evening of suspecting the firmware before I reflowed the joint and the problem evaporated. The lesson, relearned for roughly the fifth time, is that intermittent hardware faults masquerade as software bugs, and you should reach for a magnifying glass and reflow the suspicious joints before you reach for the debugger. Heat-shrink and a proper enclosure followed shortly after, partly for protection and partly so I'd stop having to look at my soldering.

the brown-out, which was real

The genuinely educational failure was the brown-out. The ESP32 would reboot at apparently random moments, and the serial log showed Brownout detector was triggered just before each one. The cause was the same WiFi radio that eats the battery: when it powers up to associate, it pulls a sharp spike of current, and my undersized boost converter couldn't deliver it fast enough. The voltage sagged, the brown-out detector did exactly its job, and the chip reset.

The fix was embarrassingly analogue. A fat capacitor across the supply rail, right next to the ESP32, to act as a local reservoir for that current spike. A few hundred microfarads and the random reboots stopped completely. No firmware change would have fixed it, because it wasn't a firmware problem. It was physics, and physics doesn't read your code.

the humidity reading that lies

The remaining "mostly" is the humidity. The BME280's humidity reading is fine in still air but reacts slowly, and if the sensor is mounted too close to its own electronics it reads a degree or two warm, which throws the relative humidity off. I've half-solved this by mounting the sensor on a little stalk away from the board and shielding it from direct sun, the poor man's Stevenson screen. It's better. It's not laboratory-grade, and I've made my peace with that.

A wider shot of the assembled circuit and wiring

what it actually does now

Every five minutes a little JSON blob lands on home/garden/weather and Home Assistant draws me a graph. The battery lasts about three weeks, which is close enough to my "charge it when I remember" tolerance. The readings are accurate enough to tell me whether it frosted overnight, which was the actual point, even if I dressed it up as a precision instrument.

Would I buy a commercial weather station that does all this for the price of the afternoons I've sunk into it? Almost certainly. But the commercial one wouldn't have taught me that a capacitor fixes WiFi reboots, or that a cold solder joint can pretend to be a firmware bug for an entire evening. The garden's temperature is a side effect. The station was the point.