21 Low-Power Sensor Networks
Multi-Sensor Aggregation and Battery Optimization
power management, deep sleep, battery life, sensor networks, duty cycling, ESP32 sleep
- Sleep Mode: a low-power MCU state where most clocks and peripherals are disabled; the device wakes on interrupt or timer to take a measurement then returns to sleep
- Duty Cycle: the fraction of time a sensor or device is active versus sleeping; lower duty cycle means lower average power consumption
- Energy Harvesting: the process of capturing ambient energy (solar, thermal, kinetic, RF) to supplement or replace battery power in IoT nodes
- LDO Regulator: Low-Dropout Regulator — a linear voltage regulator that operates with very small difference between input and output voltage, improving efficiency at low current loads
- Sleep Current: the quiescent current drawn by a device in its lowest-power sleep state, critical for estimating battery life between sampling events
- Power Gating: switching off power to entire circuit blocks (sensors, radios, peripherals) when not needed using a transistor switch, eliminating leakage current
- Battery Capacity (mAh): the total charge a battery can deliver at a given discharge rate; used with average current to calculate expected battery lifetime in IoT devices
21.2 Learning Objectives
By the end of this chapter, you will be able to:
- Design multi-sensor data aggregation systems with structured JSON payloads
- Calculate power budgets for battery-powered sensor nodes using energy-per-cycle analysis
- Implement deep sleep modes that reduce current consumption to microamp levels
- Justify transmission buffering as the dominant power optimization by quantifying its 3x+ battery life improvement over alternative strategies
- Select the appropriate sensor fusion algorithm for a given constraint profile by applying complementary vs Kalman filter tradeoff criteria
Battery-powered IoT sensors face the same challenge as your phone – they need to do useful work while making the battery last as long as possible. The trick is “deep sleep,” where the device wakes up briefly to take a reading, then goes back to sleep, using almost no power. It is like setting an alarm to check the temperature every 10 minutes instead of staring at the thermometer all day.
21.3 Introduction
Battery-powered IoT sensor nodes face a fundamental challenge: they must collect and transmit data reliably while consuming minimal power. A well-designed power management strategy can extend battery life from weeks to years. This chapter covers the techniques that make long-term remote sensing practical – from structuring multi-sensor data payloads, through deep sleep and duty cycling, to transmission buffering strategies that yield the largest real-world battery life gains.
21.4 Phoebe’s Field Notes: Where Battery Life Comes From

Phoebe’s Why
A battery budget is charge bookkeeping. Current is charge flow, so every active burst removes a small packet of charge and every sleep interval removes a much smaller packet for longer. The chemistry also sets voltage, and real cells are not ideal voltage sources: internal resistance makes the terminal voltage sag when radio current spikes. Capacity in mAh tells you charge, energy in Wh tells you charge times voltage, and the useful budget is smaller than the label after cold, aging, cutoff voltage, and self-discharge derating.
The Derivation
Current is charge per time:
\[I = \frac{dQ}{dt}\]
For one constant-current state:
\[\Delta Q_{\mathrm{mAh}} = I_{\mathrm{mA}}\frac{\Delta t_{\mathrm{s}}}{3600}\]
For one wake-sample-transmit-sleep cycle:
\[Q_{\mathrm{cycle}} = \sum_i I_i\frac{t_i}{3600}\]
Cycles per day convert the cycle ledger to daily charge:
\[N_{\mathrm{day}} = \frac{24\times60}{T_{\mathrm{min}}}\]
\[Q_{\mathrm{day}} = N_{\mathrm{day}}Q_{\mathrm{cycle}}\]
Battery lifetime follows from usable capacity, not nameplate capacity:
\[t_{\mathrm{days}} = \frac{k_{\mathrm{derate}}C_{\mathrm{mAh}}}{Q_{\mathrm{day}} + Q_{\mathrm{self}}}\]
Energy adds voltage:
\[E_{\mathrm{Wh}} = \frac{V_{\mathrm{nom}}C_{\mathrm{mAh}}}{1000}\]
A radio burst also pulls the terminal voltage down through internal resistance:
\[V_{\mathrm{load}} = V_{\mathrm{oc}} - I_{\mathrm{load}}R_{\mathrm{int}}\]
Worked Numbers: This Chapter’s Weather Node
- Cycle count: \(24\times60/15\) \(= 96.0\) cycles/day.
- Sensor read: \(30\text{ mA}\times3/3600\) \(= 0.0250\) mAh/cycle.
- Wi-Fi transmit: \(170\text{ mA}\times2/3600\) \(= 0.0944\) mAh/cycle.
- Deep sleep: \(0.01\text{ mA}\times895/3600\) \(= 0.00249\) mAh/cycle.
- Unbuffered total: \((0.0250 + 0.0944 + 0.00249)\times96.0\) \(= 11.7\) mAh/day, so \(2000/11.7\) \(= 171\) days.
- Buffered total: sensor charge stays \(2.40\) mAh/day, Wi-Fi charge becomes \(12\times0.0944\) \(= 1.13\) mAh/day, and sleep is about \(0.239\) mAh/day. The exact sum is \(3.77\) mAh/day, so \(2000/3.77\) \(= 530\) days.
- Energy scale: a \(3.7\) V, \(2000\) mAh Li-ion stores about \(3.7\times2000/1000\) \(= 7.40\) Wh before derating and cutoff losses.
Arithmetic note: the chapter rounds the buffered daily total to \(3.7\) mAh/day before dividing, which gives \(541\) days. Carrying the displayed component values gives \(530\) days; the engineering conclusion stays the same, about a \(3.1\times\) lifetime improvement from batching transmissions.
Use this chapter as a battery-life design review:
- First you shape the payload so multiple sensors can report together without wasting bytes.
- Then you make the node sleep correctly: wake, measure, transmit only when needed, and return to deep sleep.
- Next you run the power budget and see why buffering cuts transmissions from
96to12per day. - Finally you choose fusion and radio strategy, then check wake-source and data-ready pitfalls.
Checkpoints turn long calculations into design decisions; optional blocks can wait until the main path is clear.
21.5 Multi-Sensor Data Aggregation
Combining multiple sensors into a single IoT node requires structured data handling. JSON payloads provide a flexible, human-readable format for transmitting aggregated sensor data.
Focus first on the payload design question: how many sensor values must be transmitted, how often, and how expensive is each byte over the chosen radio link? Use the estimator below before writing firmware.
Wake up -> read all sensors -> validate readings -> pack one payload -> transmit once -> return to sleep.
#include <DHT.h>
#include <Wire.h>
#include <BH1750.h>
#include <Adafruit_BMP280.h>
DHT dht(4, DHT22);
BH1750 lightMeter;
Adafruit_BMP280 bmp;
struct SensorData {
float temperature;
float humidity;
float pressure;
float altitude;
float light;
unsigned long timestamp;
};
void setup() {
Serial.begin(115200);
Wire.begin();
dht.begin();
lightMeter.begin();
bmp.begin(0x76);
}
SensorData readAllSensors() {
SensorData data;
data.temperature = dht.readTemperature();
data.humidity = dht.readHumidity();
data.pressure = bmp.readPressure() / 100.0;
data.altitude = bmp.readAltitude(1013.25);
data.light = lightMeter.readLightLevel();
data.timestamp = millis();
return data;
}
void loop() {
SensorData data = readAllSensors();
// Create JSON payload
String json = createJSON(data);
Serial.println(json);
// Publish to MQTT or send via HTTP
// publishData(json); // Implement based on your platform (MQTT, HTTP, etc.)
delay(10000);
}
String createJSON(SensorData data) {
// Note: Check isnan() before production use -- DHT22 can return NaN on read failure
String json = "{";
json += "\"temperature\":" + String(data.temperature) + ",";
json += "\"humidity\":" + String(data.humidity) + ",";
json += "\"pressure\":" + String(data.pressure) + ",";
json += "\"altitude\":" + String(data.altitude) + ",";
json += "\"light\":" + String(data.light) + ",";
json += "\"timestamp\":" + String(data.timestamp);
json += "}";
return json;
}The manual String concatenation above works for learning, but production code should use the ArduinoJson library. It handles memory allocation, escaping, NaN values, and nested objects safely:
#include <ArduinoJson.h>
JsonDocument doc;
doc["temperature"] = data.temperature;
doc["humidity"] = data.humidity;
doc["pressure"] = data.pressure;
String json;
serializeJson(doc, json);
Checkpoint: Payloads Set the Energy Baseline
You now know:
- Wake once, read all sensors, pack one payload, transmit once, and return to sleep.
- Payload size depends on field count, key length, value length, timestamp use, and buffering.
- The same
96readings per day become cheaper when grouped, especially under LoRaWAN’s242 bytesceiling.
The payload plan answers what must be sent; next, minimize awake time.
21.6 Low-Power Sensor Reading
Deep sleep modes reduce current consumption from milliamps to microamps, dramatically extending battery life.
Open this after using the duty-cycle calculator. The important habit is: read quickly, transmit only when needed, configure the wake source, then sleep.
#include <esp_sleep.h>
#define SLEEP_DURATION 60 // seconds
void setup() {
Serial.begin(115200);
// Read sensors
float temperature = readTemperature();
// Send data
sendDataToCloud(temperature);
// Enter deep sleep
Serial.println("Entering deep sleep...");
esp_sleep_enable_timer_wakeup(SLEEP_DURATION * 1000000ULL); // microseconds
esp_deep_sleep_start();
}
void loop() {
// Not used - device resets after deep sleep
}
Checkpoint: Duty Cycle Is Average Current
You now know:
- A low-power loop is wake source, sensor read, optional transmit, and return to sleep.
- The calculator combines
5active seconds at150 mAwith a15minute period and0.01 mAsleep current. - Deep sleep shifts the design question from peak current to cycle average.
Once the cycle is defined, battery life is accounting.
21.7 Power Budget Calculation
Understanding power budgets is essential for designing battery-powered sensor nodes. Let us calculate the battery life for a typical environmental monitoring node.
21.7.1 Example: Weather Station Power Analysis
System Configuration:
- ESP32 with BME280 sensor
- Wi-Fi transmission every 15 minutes
- 2000 mAh battery
Current Consumption:
| State | Current | Duration per Cycle |
|---|---|---|
| Sensor Read | 30 mA | 3 seconds |
| Wi-Fi Connect + TX | 170 mA | 2 seconds |
| Deep Sleep | 10 uA | 895 seconds |
Calculation:
- Sensor read energy: 30 mA x (3 / 3600) h = 0.025 mAh per cycle
- Wi-Fi transmit energy: 170 mA x (2 / 3600) h = 0.094 mAh per cycle
- Sleep period energy: 0.01 mA x (895 / 3600) h = 0.0025 mAh per cycle
- Total per 15-minute cycle: 0.12 mAh
- Cycles per day: 96
- Daily consumption: 96 x 0.12 = 11.5 mAh/day, plus about 0.24 mAh/day sleep = 11.7 mAh/day total
- Battery life: 2000 mAh / 11.7 mAh/day = about 171 days
21.7.2 Transmission Buffering Strategy
The biggest power consumer is Wi-Fi/LoRa transmission. Buffering multiple readings before transmitting dramatically reduces power consumption.
Using the detailed breakdown from our example: - Sensor reading: 30 mA for 3 seconds = 0.025 mAh - Wi-Fi transmission: 170 mA for 2 seconds = 0.094 mAh
Original approach: 96 transmissions/day (one per 15-minute reading)
Buffered approach (transmit every 2 hours): 12 transmissions/day (8 readings per transmission)
#include <esp_sleep.h>
#define READINGS_PER_TX 8
// RTC memory survives deep sleep (normal RAM is lost on wake)
RTC_DATA_ATTR float tempBuffer[READINGS_PER_TX];
RTC_DATA_ATTR int bufferIndex = 0;
void setup() {
// Read sensor (fast, low power)
tempBuffer[bufferIndex++] = bmp.readTemperature();
if (bufferIndex >= READINGS_PER_TX) {
// Transmit all buffered readings
connectWiFi();
sendAllReadings(tempBuffer, READINGS_PER_TX);
disconnectWiFi();
bufferIndex = 0;
}
// Configure wake source and enter deep sleep
esp_sleep_enable_timer_wakeup(15 * 60 * 1000000ULL); // 15 minutes
esp_deep_sleep_start();
}
void loop() {
// Not used - device resets after deep sleep
}Using the detailed breakdown: sensor reading (30 mA, 3s) and Wi-Fi transmission (170 mA, 2s) are separate operations.
Original approach (96 transmissions/day):
- Sensor reads: \(96 \times 30\text{mA} \times \frac{3}{3600}\text{h} = 2.4\) mAh/day
- Wi-Fi TX: \(96 \times 170\text{mA} \times \frac{2}{3600}\text{h} = 9.0\) mAh/day
- Sleep: \(\approx 0.24\) mAh/day
- Total: 11.6 mAh/day → Battery life: \(\frac{2000}{11.6} = 172\) days
Buffered approach (12 transmissions/day, 8 readings per transmission):
- Sensor reads: \(96 \times 30\text{mA} \times \frac{3}{3600}\text{h} = 2.4\) mAh/day (unchanged)
- Wi-Fi TX: \(12 \times 170\text{mA} \times \frac{2}{3600}\text{h} = 1.1\) mAh/day
- Sleep: \(\approx 0.24\) mAh/day
- Total: 3.7 mAh/day → Battery life: \(\frac{2000}{3.7} = 541\) days
Result: Wi-Fi energy drops from 9.0 to 1.1 mAh/day (87.5% reduction), extending battery life by 3.1× (172 → 541 days). Transmission buffering is the single most effective optimization.
Checkpoint: Optimize the Dominant Term First
You now know:
- In the weather-station example, sensor read is
30 mAfor3 seconds, Wi-Fi transmit is170 mAfor2 seconds, and sleep is895 seconds. - Sending every reading produces
96transmissions per day; buffering8readings cuts that to12. - That drops Wi-Fi energy from
9.0to1.1 mAh/dayand moves battery life from about171or172days to541days.
21.7.3 Power Optimization Hierarchy
21.8 Sensor Fusion Tradeoffs
Core Concept: Sensor fusion combines data from multiple sensors (e.g., accelerometer + gyroscope + magnetometer) using algorithms like complementary filters or Kalman filters to produce more accurate and reliable measurements than any single sensor alone.
Why It Matters: Individual sensors have inherent limitations – accelerometers drift over time, gyroscopes accumulate integration errors, and magnetometers are affected by nearby metals – but fusing their outputs compensates for each sensor’s weaknesses while amplifying their strengths.
Key Takeaway: Start with a simple complementary filter (weighted average of fast and slow sensors) for orientation sensing – it requires only 5 lines of code and achieves 80% of Kalman filter accuracy without the computational complexity or tuning challenges.
Option A: Complementary Filter - Simple weighted combination using high-pass filter on one sensor and low-pass filter on another (e.g., gyroscope + accelerometer for orientation)
Option B: Kalman Filter - Statistically optimal recursive estimator that models system dynamics, measurement noise, and process noise for state estimation
Decision Factors:
| Factor | Complementary Filter | Kalman Filter |
|---|---|---|
| Computational load | Very low (few multiplies) | High (matrix operations) |
| Memory footprint | ~20 bytes | 200-2000 bytes |
| Tuning complexity | 1-2 parameters | 5-20+ parameters |
| Accuracy | Good (80-90% of optimal) | Optimal (by definition) |
| Sensor modeling | Assumes fixed noise | Adapts to varying conditions |
| Latency | Minimal | Slight (prediction step) |
| Implementation time | Hours | Days to weeks |
Choose Complementary Filter when: Constrained MCU (8-bit AVR, small ARM Cortex-M0); battery life critical; quick prototyping; simple sensor fusion (2-3 sensors); accuracy requirements modest.
Choose Kalman Filter when: Accuracy is paramount; sensors have varying reliability over time; need state prediction between measurements; tracking moving targets; fusion of many sensors (5+); adequate computational resources available.
Practical guideline: Start with complementary filter for proof-of-concept. If accuracy is insufficient, upgrade to Kalman.
Option A: Smart Sensors - Sensors with on-chip intelligence including calibration, digital output, threshold detection, and sometimes embedded ML (e.g., BNO055 with on-chip sensor fusion, MAX30102 with SpO2 algorithm)
Option B: Raw Sensors + External MCU - Basic analog/digital sensors where all processing, calibration, and fusion happens in your microcontroller (e.g., MPU6050 raw mode + custom fusion code)
Decision Factors:
| Factor | Smart Sensors | Raw Sensors + MCU |
|---|---|---|
| Host MCU load | Minimal (data ready) | High (continuous processing) |
| Algorithm control | Vendor black-box | Full transparency |
| Calibration | Factory-set | Custom per-unit possible |
| Latency | Fixed (sensor-determined) | Configurable |
| Cost per unit | Higher ($5-$30) | Lower ($1-$10) |
| Power (total system) | Often lower | Often higher |
| Debugging visibility | Limited | Full access |
| Algorithm updates | Firmware upgrade (rare) | OTA software update |
Choose Smart Sensors when: Rapid development required; limited MCU resources; vendor algorithm is proven for your use case; consistent behavior across units needed.
Choose Raw Sensors when: Custom algorithms required (proprietary IP, research); maximum flexibility for parameter tuning; need visibility into intermediate values; cost-optimized high-volume production.
Checkpoint: Fusion Costs Power Too
You now know:
- A complementary filter starts cheaply: a few multiplies, about
20 bytes, and80-90%of optimal accuracy. - A Kalman filter adds matrix operations,
200-2000 bytes, and5-20+tuning parameters. - Smart sensors trade higher part cost (
$5-$30) for lower host MCU load; raw sensors cost less ($1-$10) but need more firmware.
The last pass is operational safety: always wake, and read only after conversion finishes.
21.9 Common Power Pitfalls
The Mistake: Calling deep sleep functions (ESP32’s esp_deep_sleep_start(), STM32’s HAL_PWR_EnterSTOPMode(), nRF52’s sd_power_system_off()) without configuring a valid wake source, causing the device to sleep forever and require manual reset or power cycle to recover.
Why It Happens: Deep sleep disables most peripherals and CPU activity to achieve microamp-level current consumption. Unlike light sleep, there is no automatic wake on timer expiration unless explicitly configured. Developers test with short delays during development, then remove the delay for “production” without adding proper wake sources, bricking the device.
The Fix: Always configure at least one wake source before entering deep sleep.
- Use a timer wake source for periodic sensing.
- Use an external GPIO wake source for buttons, interrupts, or event-driven sensors.
- During development, keep a fail-safe timer wake source even if the final product wakes from an interrupt.
21.10 Optional Wake-Source Pattern
// WRONG: Entering deep sleep with no wake source (ESP32)
esp_deep_sleep_start(); // Device sleeps forever! Requires power cycle.
// CORRECT: Configure timer wake source (10 seconds)
esp_sleep_enable_timer_wakeup(10 * 1000000); // 10 seconds in microseconds
esp_deep_sleep_start();
// CORRECT: Configure external interrupt wake (GPIO 33, active LOW)
esp_sleep_enable_ext0_wakeup(GPIO_NUM_33, 0); // Wake when GPIO33 goes LOW
esp_deep_sleep_start();
// CORRECT: Multiple wake sources (timer OR button)
esp_sleep_enable_timer_wakeup(60 * 1000000); // 60-second timeout
esp_sleep_enable_ext0_wakeup(GPIO_NUM_0, 0); // Boot button wake
esp_deep_sleep_start();Recovery Strategy: During development, always include a “fail-safe” wake source like a 5-minute timer even if primary wake is external interrupt.
The Mistake: Reading sensor data registers immediately after triggering a measurement, before the sensor’s internal ADC has completed conversion, resulting in stale data from the previous measurement or invalid values.
Why It Happens: Sensors like the BMP280 (temperature/pressure), ADS1115 (precision ADC), and HX711 (load cell) have multi-millisecond conversion times. The datasheet specifies conversion time, but example code often uses fixed delays or omits waiting entirely. At 400kHz I2C, you can read registers in ~50us, but BMP280 needs 44ms in ultra-high-resolution mode.
The Fix: Check the sensor’s data-ready signal or wait for the specified conversion time. The behavior to remember is: trigger measurement, wait until conversion is complete, then read the result.
21.11 Optional Data-Ready Pattern
// WRONG: Reading BMP280 immediately after trigger (44ms conversion!)
bmp.takeForcedMeasurement();
float temp = bmp.readTemperature(); // Returns PREVIOUS measurement!
// CORRECT: Wait for conversion time (check datasheet)
bmp.takeForcedMeasurement();
delay(44); // Ultra-high resolution mode: 44ms
float temp = bmp.readTemperature();
// BETTER: Poll status register for data-ready flag
bmp.takeForcedMeasurement();
while ((bmp.getStatus() & 0x08) == 0) { // Bit 3 = "measuring"; 0 = conversion done
delayMicroseconds(100); // Poll every 100us
}
float temp = bmp.readTemperature();Conversion Times to Know: BMP280 standard: 8ms, ultra-high: 44ms. ADS1115 at 8 SPS: 125ms, at 860 SPS: 1.2ms. HX711 at 10 Hz: 100ms.
21.12 Knowledge Check
Question 1: A battery-powered environmental monitoring node uses an ESP32 with BME280 sensor, transmitting readings every 15 minutes via Wi-Fi. Current consumption is: sensor read 30mA (3 seconds), Wi-Fi TX 170mA (2 seconds), deep sleep 10uA. Using a 2000mAh battery, approximately how long will the node operate?
Answer: Approximately 170 days (5.7 months)
Calculation:
- Sensor Read Energy: 30mA x (3/3600)h = 0.025 mAh per cycle
- Wi-Fi TX Energy: 170mA x (2/3600)h = 0.094 mAh per cycle
- Sleep Period Energy: 0.01mA x (895/3600)h = 0.0025 mAh per cycle
- Total per 15-minute cycle: 0.12 mAh
- Cycles per day: 96
- Daily consumption: 96 x 0.12 + 0.24 (sleep) = 11.7 mAh/day
- Battery life: 2000mAh / 11.7 mAh/day = 171 days
Question 2: What is the most effective way to extend battery life by 3x or more for the node described above?
Answer: Reduce Wi-Fi transmissions by buffering multiple readings
Wi-Fi transmission dominates the power budget (80%+ of energy). By buffering 8 readings and transmitting every 2 hours instead of every 15 minutes: - Wi-Fi transmissions drop from 96 to 12 per day (87.5% reduction) - Daily energy drops from 11.7 to 3.7 mAh (sensor: 2.4, TX: 1.1, sleep: 0.24) - Battery life extends from 171 days to 541 days (3.1x improvement)
Other options (ESP8266, larger battery, reduced sampling) provide smaller improvements.
Question 3: Why must you configure a wake source BEFORE calling esp_deep_sleep_start()?
Answer: Without a configured wake source, the device sleeps forever and cannot recover without a manual power cycle.
Deep sleep disables the CPU and most peripherals. There is no automatic timeout - the device will remain in sleep mode indefinitely (consuming ~10uA) until a wake event occurs. If no wake source is configured, no wake event can ever occur, and the device is effectively bricked until physically reset.
Always configure at least one wake source (timer, GPIO interrupt, touchpad, or ULP coprocessor) before entering deep sleep.
The power management hierarchy for battery-powered sensor nodes is: (1) minimize transmissions first (buffering yields 3x+ improvement), (2) use deep sleep between readings (reduces idle current 10,000x from mA to uA), (3) then optimize active-period current (sensor selection, clock speed). Tackling these in wrong order – such as choosing a lower-power MCU before reducing transmission count – delivers marginal gains while ignoring the dominant power consumer.
Bella the Battery had a big problem. “I only have so much energy,” she said. “If everyone keeps talking all the time, I will run out in just a few months!”
Sammy the Sensor felt bad. “But I need to measure the temperature!” Max the Microcontroller had an idea: “What if Sammy takes his readings, but instead of shouting them to the cloud every single time, we save them up and send a big batch all at once?”
“Like saving up your drawings and mailing them all in one envelope instead of 8 separate letters!” Sammy the Sensor suggested.
“Exactly!” said Max. “The Wi-Fi radio uses the MOST energy – way more than Sammy reading the temperature. By sending one big message instead of eight small ones, Bella lasts THREE TIMES longer!”
Bella was relieved. “And between readings, everyone goes to DEEP SLEEP. That means I only use 10 microamps – that is like a tiny trickle instead of a fire hose!”
“But ALWAYS set an alarm before sleeping,” Max warned. “If you sleep without an alarm, you sleep FOREVER and someone has to unplug you and plug you back in!”
Scenario: You are deploying 50 environmental sensors across a 5 km² agricultural area. Each sensor reads temperature and soil moisture every 15 minutes. Should you use Wi-Fi or LoRaWAN?
System Specifications:
- ESP32 microcontroller
- BME280 temperature/humidity sensor
- Capacitive soil moisture sensor
- 3.7V 2000 mAh Li-ion battery
- Sensor reading interval: 15 minutes (96 readings/day)
Option A: Wi-Fi Connectivity (same analysis as the Power Budget Calculation section)
| State | Current (mA) | Duration per Cycle | Energy (mAh) |
|---|---|---|---|
| Deep Sleep | 0.01 | 14 min 55 sec (895 sec) | 0.0025 |
| Sensor Read | 30 | 3 sec | 0.025 |
| Wi-Fi Connect + TX | 170 | 2 sec | 0.094 |
| Total per cycle | 15 min | 0.12 mAh |
Daily consumption: 96 cycles × 0.12 mAh + 0.24 (sleep) = 11.7 mAh/day
Battery life: 2000 mAh / 11.7 mAh/day = 171 days (5.7 months)
Option B: LoRaWAN Connectivity
Note: At +14 to +20 dBm TX power (required for the 5-15 km range in this scenario), LoRaWAN modules such as the SX1276 draw 100-130 mA. We use 120 mA as a realistic value for long-range agricultural deployments.
| State | Current (mA) | Duration per Cycle | Energy (mAh) |
|---|---|---|---|
| Deep Sleep | 0.01 | 14 min 55 sec (895 sec) | 0.0025 |
| Sensor Read | 30 | 3 sec | 0.025 |
| LoRaWAN TX (+17 dBm) | 120 | 2 sec | 0.067 |
| Total per cycle | 15 min | 0.094 mAh |
Daily consumption: 96 cycles × 0.094 mAh + 0.24 (sleep) = 9.3 mAh/day
Battery life: 2000 mAh / 9.3 mAh/day = 215 days (7.1 months)
Comparison Table:
| Metric | Wi-Fi | LoRaWAN | Winner |
|---|---|---|---|
| Battery Life | 171 days | 215 days | LoRaWAN (1.3× longer) |
| TX Current | 170 mA | 120 mA | LoRaWAN (1.4× lower) |
| Range | 50-100m | 5-15 km | LoRaWAN (100× longer) |
| Infrastructure | Wi-Fi AP every 50m | 1 gateway for entire 5 km² | LoRaWAN (simpler) |
| Cost per Node | $5 (ESP32 only) | $13 (ESP32 + LoRa module) | Wi-Fi (cheaper) |
| Total Infrastructure Cost | 50× Wi-Fi APs @ $30 = $1,500 | 1× LoRaWAN gateway @ $200 = $200 | LoRaWAN (much cheaper) |
Decision: LoRaWAN wins for agricultural deployment due to: - 1.3× longer battery life (215 vs 171 days) with realistic TX power for 5+ km range - 100× longer range (15 km vs 100m) – covers entire 5 km2 farm with ONE gateway - $1,300 lower infrastructure cost ($200 vs $1,500) - Lower maintenance (fewer battery changes per year)
Note: At low TX power (+7 dBm, ~40 mA), LoRaWAN battery life extends to 400+ days, but range drops to 1-2 km. The advantage grows further with transmission buffering, since LoRaWAN’s lower per-TX energy cost compounds the savings.
When Wi-Fi Makes Sense:
- Indoor deployment with existing Wi-Fi infrastructure (no gateway cost)
- High data rate needs (>10 KB/transmission) – LoRaWAN limited to 242 bytes
- Real-time applications (<1 second latency) – LoRaWAN has 1-5 second latency
- Short range (<100m) with frequent communication (every minute)
Key Insight: For battery-powered outdoor IoT with infrequent small-payload transmissions, LoRaWAN’s lower TX current and vastly longer range make it the clear winner. Wi-Fi’s higher power consumption (170 mA) dominates the energy budget, and the infrastructure savings alone often justify LoRaWAN even before considering battery life.
21.12.1 Wi-Fi vs LoRaWAN Battery Life
21.13 Power, Accuracy, Field Hardening
The main chapter above builds the low-power sensing loop and radio budget. The companion page checks the accuracy side of the same design: self-heating, sensor warm-up, settling delays, adaptive sampling, and field-hardening evidence.
Continue with Power Accuracy and Field Hardening to verify that battery-life optimizations do not bias the measurement chain.
21.14 Summary
This chapter covered power management strategies for sensor networks:
- Multi-Sensor Aggregation: Structured data collection with JSON payloads
- Deep Sleep Modes: Reduce consumption from milliamps to microamps
- Power Budget Calculations: Estimate battery life for design decisions
- Transmission Buffering: Reduce Wi-Fi/LoRa usage by 80%+ for 3x battery life
- Sensor Fusion Tradeoffs: Complementary vs Kalman filters, smart vs raw sensors
- Wake Source Configuration: Critical for deep sleep recovery
21.15 What’s Next
The next chapter covers Sensor Applications, including smart home environmental monitoring, automated blinds control, and temperature-controlled relay systems with practical implementation examples.
- Sensor Data Processing - Filtering and calibration
- Sensor Communication Protocols - I2C, SPI interfaces
- Edge Computing - Edge processing patterns