Building a Real-Time Agricultural IoT System: Edge vs Cloud
How I reduced cloud bandwidth costs by 70% using TinyML on ESP32 — architecture decisions, tradeoffs, and lessons from deploying at the edge.
The Problem
When I started building FarmAssist, I assumed the architecture would be straightforward: sensors collect data, send it to the cloud, cloud processes everything, dashboard displays results. This is what most IoT tutorials teach you.
Reality was different. The farms I was targeting had spotty connectivity at best — rural Karnataka, where a stable 4G signal is a luxury. Pushing thousands of sensor readings per minute to a cloud server wasn't just expensive, it was unreliable. Packets dropped. Latency spiked. The system would go blind during the moments it mattered most.
The Architecture Decision
I moved to an edge-first architecture. Instead of treating the ESP32 as a dumb data pipe, I turned it into a processing node. Using TensorFlow Lite Micro, I deployed quantized ML models directly onto the microcontroller. The device could classify soil conditions, detect anomalies, and make irrigation decisions locally — without any cloud round-trip.
The cloud became a sync layer, not a processing layer. Only aggregated insights and anomaly flags got transmitted, typically a few hundred bytes every 5 minutes instead of continuous raw data streams.
TinyML on Constrained Hardware
The ESP32 has 512KB of SRAM and 4MB of flash. Running a neural network on this requires aggressive optimization:
- Post-training quantization: Reduced model size from 2.1MB to 180KB (INT8 quantization) with only 1.2% accuracy loss.
- Feature engineering over model complexity: Instead of feeding raw sensor data into a deep model, I pre-computed rolling averages, rate-of-change, and statistical features. A simpler model on better features outperformed a complex model on raw data.
- Inference batching: Accumulated 30 seconds of readings, ran inference once. This kept CPU utilization under 40% and left headroom for communication tasks.
LoRa for Long-Range, Low-Power Communication
Between ESP32 sensor nodes and the Raspberry Pi gateway, I used LoRa (Long Range) radio. LoRa can transmit small payloads over several kilometers with minimal power draw — perfect for a distributed farm network.
The tradeoff: bandwidth is extremely limited (~250 bytes per transmission at reasonable data rates). This forced me to design compact binary protocols instead of JSON. Every byte mattered. I ended up with a 24-byte packet format that encoded sensor type, value, confidence score, and a timestamp delta.
Results
The edge-first approach yielded measurable improvements:
- 70% reduction in cloud bandwidth usage
- <50ms inference latency on-device (vs 200-800ms cloud round-trip)
- 90%+ classification accuracy on soil condition detection
- 35% reduction in water wastage through automated, data-driven irrigation
- System remained fully operational during 6+ hour connectivity outages
What I'd Do Differently
If I were starting over, I'd invest more time in over-the-air (OTA) model updates. Deploying updated ML models required physical access to each ESP32 node. In a production farm scenario with dozens of nodes spread over hectares, this doesn't scale.
I'd also explore federated learning — letting each node refine its model locally and sharing only gradient updates with the central system. This would improve accuracy across heterogeneous soil conditions without centralizing raw data.