The Bench
Writeups from the bench. Firmware, radios, power, the occasional rover.
Image Transmission Over a 0.5 Mbps Mesh When Wi-Fi Fails→
A graceful-degradation pipeline for an unmanned ground vehicle. When the primary link drops, the operator still has eyes on the UGV at lower frame rate, through the same downstream stack.
Charging Intuition: How a BMS Charging Station Reshaped My Engineering Thinking→
The BMS went silent. CAN was alive, the ESP32 was transmitting, the dashboard was refreshing on schedule — and the battery had vanished from the system’s understanding of reality. A field report on what it took to make telemetry, control logic, and an AI layer agree.
Shrinking a YOLO to Fit on a Pi 4: Human Detection for Drones→
Training YOLOv8n on smoke, fire, and human simultaneously, then cutting it down to a 3 MB INT8 TFLite file that runs on a Raspberry Pi 4 CPU. Real numbers, real tradeoffs, honest failure modes.
What's Left in This Battery? Four Tiny Models Inside an ESP32→
Predicting State-of-Charge, State-of-Health, and Remaining-Useful-Life for an 18650 cell on a board with a thermistor, an INA219, and two relays. Random forests, exported as C, fit under two megabytes of flash.
Chunked OTA Over LoRa on an ESP32-C3→
Pushing a firmware image to a battery-powered sensor node over a link that hands you ~200 bytes at a time and cuts out at inconvenient moments. A small, embarrassingly simple protocol that survives reboots mid-update.
Exploring the Unknown: a Frontier Planner That Learns to Guess→
Mapping an unknown indoor space end-to-end, without a cloud and without a human. A ROS 2 exploration stack that picks the next frontier using distance, heading, and a small U-Net guessing what’s beyond the wall.
Hunting a 3 µA Ghost: How a Pull-Up Killed Our Battery Budget→
A post-mortem on a low-power ESP32 design that slept at 21 µA instead of 18 µA. The cause was smaller than we expected.
Rewriting a BLE Stack in Three Weeks — and What We Broke→
Pairing was generating support tickets at a rate of 40 per week. We stripped the vendor SDK and started over. A field report.
Notes on Tuning a CAN Bus at -40°C→
Why the rover stopped arbitrating at three in the morning, and the oscilloscope trace that finally explained it.
An 8-bit Quantized Keyword Spotter in 42 kB of Flash→
Fitting a real wake-word model onto a Cortex-M0+ without TensorFlow Lite Micro. A tour of the compromises.
Stop Using strcpy. Use This Instead.→
A small opinion piece on why the C standard library is a liability in firmware, and the tiny helpers we reach for first.
Boost Converter Ringing at 2 MHz: A Layout Confession→
The EMI scan that failed. The loop area we underestimated. The cut trace that fixed it at 3am, two days before the cert lab.
A Short History of Why Our Rover's Arm Twitched→
Three months of intermittent servo glitches. The ground loop that explained all of them. Why we trust our scope more than our datasheet.
OTA Updates Without Bricking Customers→
A dual-bank bootloader pattern that's saved us three recalls. Includes the flowchart we print and tape to the wall.
Why We Don't Use Floating Point for Sensor Fusion→
A walkthrough of fixed-point quaternion math on an M4 without FPU. Deterministic, 6× faster, and nobody has to argue about epsilons.
The Case for the Humble LDO→
Every design review, someone asks why we didn't pick a switcher. Here's the one-page answer, with bench measurements.