Analyze power consumption across different device operating states
Calculate average current for duty-cycled IoT devices
Identify and quantify power consumption components
Explain radio power states and their impact on energy consumption
Create accurate power budgets for IoT system design
Key Concepts
Operating States: The discrete power modes a device transitions through: active sensing, radio transmit, radio receive, CPU active, and deep sleep — each with distinct current draw
Average Current: I_avg = Σ(I_state × t_state) / T_total — the time-weighted mean current that determines actual battery life
Radio Idle Current: Current drawn when the radio is initialized but not actively transmitting; often 10–100× higher than MCU sleep current and a common battery drain surprise
Pull-Up Resistor Leakage: Pull-up resistors on I2C, SPI, and GPIO pins create continuous current paths; a 10 kΩ pull-up to 3.3 V draws 330 µA constantly
Power Budget Spreadsheet: A tool listing all operating states with their current draw and duty cycle fraction, enabling calculation of average current and battery life estimate
Voltage Regulator Quiescent Current: LDO regulators draw 30–200 µA regardless of load; for low-current sleep modes, regulator quiescent current can dominate total sleep power
Debug Interface Leakage: JTAG/SWD debug interfaces can add 1–5 mA when active; always disable debug interfaces in production builds
In 60 Seconds
Power consumption analysis builds a complete picture of device energy use across all operating states — active sensing, radio transmission, idle, and sleep — then calculates the time-weighted average current that determines actual battery life in deployment.
For Beginners: Power Consumption Analysis
Energy and power management determines how long your IoT device can operate between battery changes or charges. Think of packing for a camping trip with limited battery packs – every bit of power must be used wisely. Since many IoT sensors need to run for months or years unattended, power management is often the single most important engineering decision.
Sensor Squad: Where Does All the Energy Go?
“Power analysis is like tracking where your allowance goes each week,” said Bella the Battery. “You list every state the device can be in – sleeping, sensing, processing, transmitting – and how much current each state draws. Then you calculate the average based on how long the device spends in each state.”
Max the Microcontroller showed the math: “A typical IoT device might draw 10 microamps sleeping, 5 milliamps sensing, 15 milliamps processing, and 120 milliamps transmitting. If it sleeps 99 percent of the time and only transmits for 0.01 percent, the average current is dominated by the sleep current. But if it transmits 1 percent of the time, radio becomes the biggest drain!”
Sammy the Sensor emphasized the radio: “The radio is almost always the biggest energy consumer. Transmitting data uses 10 to 100 times more power than anything else. That is why communication protocol choice matters so much – BLE uses far less than Wi-Fi, and LoRa uses less than cellular.” Lila the LED summarized, “Break down the power budget, find the biggest consumer, and optimize that first. You get the most savings by fixing the biggest problem!”
Interactive: IoT Power Consumption Calculator
Interactive: Power Profile Analyzer
4.2 Power Consumption Analysis
Understanding power consumption requires analyzing all device states and their duration. Most IoT devices cycle through multiple power modes:
Figure 4.1: IoT device power state machine showing typical current consumption for each state
4.2.1 Power State Definitions
State
Current Range
Wake Time
What’s Active
Deep Sleep
1-100 µA
100-500 µs
RTC only, RAM retained
Light Sleep
0.1-1 mA
10-100 µs
RTC + limited peripherals
Idle
1-10 mA
Immediate
CPU idle, peripherals on
Active
10-50 mA
N/A
CPU running, no radio
Sensing
5-50 mA
N/A
Sensors powered and sampling
Processing
20-80 mA
N/A
CPU compute-intensive
TX/RX
100-300 mA
N/A
Radio transmitting/receiving
4.2.2 The Idle Power Myth: Radio Idle ≈ Radio Receive
Critical Insight: “Idle” Radio Still Consumes Significant Power
Many developers assume a radio in “idle” mode consumes minimal power. This is FALSE for most wireless protocols:
Protocol
TX Power
RX Power
Idle Power
Deep Sleep
Wi-Fi
160-300 mA
80-120 mA
50-80 mA
10-20 µA
BLE
10-20 mA
10-15 mA
1-5 mA
<1 µA
LoRa
40-120 mA
10-15 mA
1-5 mA
0.2-1 µA
Zigbee
15-30 mA
15-25 mA
1-5 mA
<1 µA
Key insight: For Wi-Fi, idle mode (50-80 mA) is nearly as expensive as receiving (80-120 mA). The only way to save power is complete radio shutdown with deep sleep (10-20 µA).
For BLE and LoRa, idle is better than active but still consumes 1,000× more than deep sleep. Always completely disable radios when not in use.
4.2.3 Average Current Calculation
For duty-cycled devices, average current determines battery life:
Lesson: Wi-Fi connection consumes 62% of total energy despite being active for only 1.5 seconds per hour. Never keep Wi-Fi “connected” between transmissions—the idle power (50-80mA) would dominate. Always connect → transmit → disconnect for battery-powered devices.
4.2.4 Radio Power States as Energy Multipliers
Figure 4.2: Radio power states showing the dramatic difference between active and sleep modes
4.2.5 Protocol Energy Comparison
Different protocols have vastly different energy costs per transmission:
Protocol
Typical TX Time
TX Current
Energy per TX (at 3.3V)
BLE (1 packet)
1-3 ms
15 mA
50-150 µJ
Zigbee
5-10 ms
20 mA
330-660 µJ
LoRa SF7
50 ms
40 mA
6,600 µJ
LoRa SF12
1,500 ms
40 mA
198,000 µJ
Wi-Fi (short)
100 ms
180 mA
59,400 µJ
Wi-Fi (incl. connect)
3,000 ms
160 mA
1,584,000 µJ
LTE-M
500 ms
220 mA
363,000 µJ
NB-IoT
1,000 ms
200 mA
660,000 µJ
Key observation: BLE is 300-10,000× more efficient than Wi-Fi per transmission. Choose protocols carefully based on range and data requirements.
protocol_results = {const sleep_current =0.01;// 10 µA deep sleepconst tx_energy_mAs = protocol_params.current* protocol_params.time;// mAs per transmissionconst daily_tx_energy = tx_energy_mAs * tx_per_day;// mAs per day from TXconst daily_sleep_time =86400- (protocol_params.time* tx_per_day);// seconds sleepingconst daily_sleep_energy = (sleep_current /1000) * daily_sleep_time;// mAs per day from sleepconst daily_total_mAs = daily_tx_energy + daily_sleep_energy;const avg_current_mA = daily_total_mAs /86400;const battery_life_hours = (battery_capacity *0.7) / avg_current_mA;const battery_life_days = battery_life_hours /24;const battery_life_years = battery_life_days /365;const tx_percent = (daily_tx_energy / daily_total_mAs) *100;return {tx_energy_mAs: tx_energy_mAs,daily_total_mAs: daily_total_mAs,avg_current_mA: avg_current_mA,battery_life_days: battery_life_days,battery_life_years: battery_life_years,tx_percent: tx_percent };}
Show code
html`<div style="background: var(--bs-light, #f8f9fa); padding: 1.5rem; border-radius: 8px; border-left: 4px solid #16A085; margin-top: 0.5rem;"><h4 style="margin-top: 0; color: #2C3E50;">Protocol Energy Analysis: ${protocol_select}</h4><table style="width:100%; border-collapse:collapse; margin-top:1rem;"><tr style="background: #fff;"> <td style="padding:8px; border:1px solid #ddd;"><strong>Energy per transmission</strong></td> <td style="padding:8px; border:1px solid #ddd;">${protocol_results.tx_energy_mAs.toFixed(2)} mAs (${(protocol_results.tx_energy_mAs* protocol_params.voltage).toFixed(0)} µJ)</td></tr><tr style="background: #f8f9fa;"> <td style="padding:8px; border:1px solid #ddd;"><strong>Daily energy (${tx_per_day} TX/day)</strong></td> <td style="padding:8px; border:1px solid #ddd;">${protocol_results.daily_total_mAs.toFixed(1)} mAs</td></tr><tr style="background: #fff;"> <td style="padding:8px; border:1px solid #ddd;"><strong>Average current draw</strong></td> <td style="padding:8px; border:1px solid #ddd;">${protocol_results.avg_current_mA.toFixed(3)} mA (${(protocol_results.avg_current_mA*1000).toFixed(0)} µA)</td></tr><tr style="background: #f8f9fa;"> <td style="padding:8px; border:1px solid #ddd;"><strong>TX energy as % of total</strong></td> <td style="padding:8px; border:1px solid #ddd;">${protocol_results.tx_percent.toFixed(1)}%</td></tr><tr style="background: #fff;"> <td style="padding:8px; border:1px solid #ddd;"><strong>Battery life (${battery_capacity} mAh @ 70% eff.)</strong></td> <td style="padding:8px; border:1px solid #ddd; font-weight: bold; color: ${protocol_results.battery_life_years>=2?'#16A085': protocol_results.battery_life_years>=1?'#E67E22':'#E74C3C'};">${protocol_results.battery_life_days.toFixed(0)} days (${protocol_results.battery_life_years.toFixed(1)} years) </td></tr></table><p style="margin-top: 1rem; font-size: 0.9em; color: #7F8C8D;">${protocol_results.battery_life_years>=5?"✅ Excellent: 5+ year battery life!": protocol_results.battery_life_years>=2?"✅ Good: Meets 2-year deployment target.": protocol_results.battery_life_years>=1?"⚠️ Moderate: Consider reducing TX frequency or increasing battery.":"❌ Poor: Insufficient for battery deployment. Switch to lower-power protocol or add energy harvesting."}</p></div>`
4.3 Power Budget Worked Examples
4.3.1 Worked Example: Optimizing Power Budget for a Wildlife Tracking Collar
Scenario: You are designing a GPS tracking collar for deer monitoring in a wildlife research project. The collar must last 2 years on a single battery, transmit location every 4 hours, and weigh under 100g (including battery).
Theoretical: 1,200 mAh / 0.303 mAh/day = 3,960 days = 10.8 years
With 70% efficiency factor: 3,960 × 0.7 = 2,772 days = 7.6 years
Result: The design significantly exceeds the 2-year requirement. This margin can be used to:
Increase transmission frequency (every 2 hours → still 3.8 years)
Add activity detection with accelerometer
Use smaller/lighter battery (600 mAh still gives 3.8 years)
Key Insight: GPS acquisition dominates the power budget (82%). Optimizations should focus on keeping GPS in hot-start mode (preserve ephemeris data) or using A-GPS for faster acquisition.
4.3.2 Worked Example: Comparing Protocol Energy Costs for a Smart Agriculture Sensor
Scenario: A soil moisture sensor transmits 100-byte readings every 30 minutes. Compare Wi-Fi, BLE, and LoRa for a 2-year battery life target.
Given:
Sensor reading: 5mA × 0.5s = 2.5 mAs per reading
MCU (nRF52840): 5.5mA active, 1.5µA deep sleep
Processing: 10ms per reading
Readings per day: 48
Protocol Comparison:
Protocol
Connection Time
TX Time
Total Energy/TX
Wi-Fi
3s @ 160mA = 480 mAs
100ms @ 200mA = 20 mAs
500 mAs
BLE
0ms (advertising)
5ms @ 15mA = 0.075 mAs
0.075 mAs
LoRa SF7
0ms
100ms @ 40mA = 4 mAs
4 mAs
Daily Energy Consumption:
Component
Wi-Fi
BLE
LoRa
Radio (48 TX)
24,000 mAs
3.6 mAs
192 mAs
Sensor
120 mAs
120 mAs
120 mAs
MCU Active
26.4 mAs
26.4 mAs
26.4 mAs
MCU Sleep
130 mAs
130 mAs
130 mAs
Daily Total
24,276 mAs
280 mAs
468 mAs
Battery Life (2000 mAh @ 70% efficiency):
Protocol
Daily (mAh)
Life (days)
Life (years)
Wi-Fi
6.74
208
0.57
BLE
0.078
17,949
49.2
LoRa
0.130
10,769
29.5
Conclusion: Wi-Fi gives only 7 months of battery life, making it unsuitable without energy harvesting. BLE achieves 49 years (theoretical), allowing for smaller batteries or higher transmission rates. LoRa provides excellent range with 29 years life. For this application, BLE is optimal for short-range or LoRa for long-range.
Worked Example: Diagnosing Power Budget Failure in a Smart Agriculture Sensor
Scenario: A farm monitoring company deployed 200 soil moisture sensors powered by 2× AA alkaline batteries (3000 mAh total). The design target was 1-year battery life, but field reports show batteries dying after only 3 months.
Given Initial Design:
ESP8266 MCU with Wi-Fi
Soil moisture sensor: 30 mA active
Transmission every 15 minutes to cloud server
Expected deep sleep current: 10 µA
Investigation Steps:
Check baseline sleep current: Used ammeter on lab device → measured 15 mA idle, NOT 10 µA
Root cause: Code never entered deep sleep mode due to missing ESP.deepSleep() call
Fix: Add proper sleep call after data transmission
Measure actual Wi-Fi connection time: Expected 2s, measured 8s average
Root cause: Weak Wi-Fi signal in field required multiple connection retries
Fix: Add fixed IP configuration to avoid DHCP delay (reduces connection time to 3s)
Calculate corrected power budget:
State
Current
Duration
Energy (mAs)
Deep Sleep
0.010 mA
885 s
8.85
Wake + Init
80 mA
0.5 s
40
Sensor Read
30 mA
1 s
30
Wi-Fi Connect
160 mA
3 s
480
Wi-Fi TX
200 mA
0.5 s
100
Total per cycle
900 s
658.85
Average current: 658.85 / 900 = 0.732 mA Battery life: 3000 mAh / 0.732 mA = 4,098 hours = 5.7 months
Compare to BROKEN design (no deep sleep):
Average: (160×11 + 15×889) / 900 = 16.73 mA
Battery life: 3000 / 16.73 = 179 hours = 7.5 days
Field reports showed 3 months → likely some devices entering sleep intermittently
Final Optimizations:
Switch from Wi-Fi to LoRa: 40 mA TX for 0.1s = 4 mAs (vs 580 mAs for Wi-Fi)
Increase interval to 30 minutes
New average: 0.041 mA → 7.3 years battery life
Key Lesson: Measure actual hardware, never trust datasheets alone. The difference between 10 µA sleep (spec) and 15 mA idle (reality) destroyed the power budget.
Decision Framework: Choosing Communication Protocol for Battery-Powered Sensors
Before designing your power budget, choose the right communication technology based on these factors:
Factor
Wi-Fi
BLE
LoRa
Cellular (NB-IoT)
TX Energy/packet
1.58 mJ (high)
100 µJ (very low)
6.6 mJ (low)
660 mJ (high)
Range
50-100m
10-50m
2-15km
Unlimited (tower)
Data Rate
1-100 Mbps
1 Mbps
0.3-50 kbps
10-100 kbps
Infrastructure
Wi-Fi router needed
Gateway within 50m
Gateway within 15km
Cellular subscription
Best For
Mains-powered, high data
Wearables, short range
Agricultural, remote
Mobile assets, wide area
Battery Life (1 reading/hour)
6 months
5+ years
3+ years
1 year
Decision Process:
Range requirement → Rules out some options (BLE can’t reach 500m farm)
Data volume → Sending images? Need Wi-Fi/Cellular. Sensor value? Any works.
Power budget → Battery-powered? Avoid Wi-Fi/Cellular unless solar-powered
Infrastructure → Have existing Wi-Fi? May reuse it despite power cost
Total Cost → LoRa needs gateway ($200-500) but saves battery replacements
Example: For a parking lot sensor (100m from building, 1 status update/minute, 2-year battery target): - Wi-Fi: NO (too power-hungry, 6 month battery) - BLE: NO (range insufficient) - LoRa: YES (if gateway available) - NB-IoT: MAYBE (if cellular coverage and monthly fees acceptable)
Common Mistake: Forgetting Development/Debug Power Drains
The Problem: Your production power budget looks perfect on paper, but devices die fast in the field.
Hidden Power Drains During Development:
USB serial connection: Keeps MCU from entering deep sleep (USB peripheral active)
Solution: Disable USB before measuring, or use hardware serial instead
Debug LEDs: A single red LED at 20 mA × 1% duty cycle = 0.2 mA average
This alone can halve battery life on a 0.1 mA budget device
Solution: Disable all LEDs in production firmware, or use high-value resistors
Pull-up resistors on unused GPIOs: 10kΩ at 3.3V = 330 µA EACH
Solution: Configure unused pins as outputs or use input with internal pull-down
Voltage regulator quiescent current: Many LDOs draw 50-100 µA even with no load
External peripherals: Sensor breakout boards often have power LEDs and regulators
Solution: Power sensors through a transistor switch controlled by MCU
Real Example: ESP32 deep sleep spec says 10 µA, but: - With USB connected: 15,000 µA (USB keeps chip awake) - With blue LED on GPIO: 20,000 µA - With external sensor board: 5,000 µA (board’s regulator + LED) - Properly configured: 12 µA (close to spec!)
Verification Protocol:
Measure current with ammeter in series with battery
Verify deep sleep is actually reached (should drop to µA range within seconds)
If current high, disconnect peripherals one by one to find culprit
Document actual measured current, not datasheet values
4.7 Knowledge Check
## How It Works
Power analysis breaks device operation into discrete states, measures each, then calculates weighted average:
State identification process:
Map all states: Deep sleep, wake/init, sensor read, processing, radio TX, radio RX, shutdown
Measure each state: Use power profiler to capture current draw and duration
Calculate state energy: Energy = Current × Voltage × Time (mAs or mAh)
Weight by frequency: Average current = Σ(State energy × Cycles per day) / 24 hours
Example calculation (environmental sensor, 1-hour cycle):
Deep sleep: 10µA × 3595s = 35.95 mAs
Sensor read: 5mA × 2s = 10 mAs
WiFi connect: 160mA × 1.5s = 240 mAs
WiFi TX: 200mA × 0.3s = 60 mAs
Total per cycle: 345.95 mAs
Average current: 345.95 mAs / 3600s = 0.096 mA = 96µA
Battery life (2000mAh): 2000 / 0.096 = 20,833 hours = 2.4 years
Hidden drains exposed: Pull-up resistors (10kΩ at 3.3V = 330µA each), voltage regulator quiescent current (50-100µA), peripheral standby current (sensors “off” but still powered). These continuous drains dominate low-duty-cycle devices.
4.8 Concept Check
## Concept Relationships
Power analysis provides the quantitative foundation for all energy optimization:
html`<div style="background: var(--bs-light, #f8f9fa); padding: 1.5rem; border-radius: 8px; border-left: 4px solid #E67E22; margin-top: 0.5rem;"><h4 style="margin-top: 0; color: #2C3E50;">Transmission Frequency Results</h4><table style="width:100%; border-collapse:collapse; margin-top:1rem;"><tr style="background: #fff;"> <td style="padding:8px; border:1px solid #ddd;"><strong>Target average current</strong></td> <td style="padding:8px; border:1px solid #ddd;">${ex_results.target_avg_ua.toFixed(1)} µA (${(ex_results.target_avg_ua/1000).toFixed(3)} mA)</td></tr><tr style="background: #f8f9fa;"> <td style="padding:8px; border:1px solid #ddd;"><strong>Energy per reading</strong></td> <td style="padding:8px; border:1px solid #ddd;">${ex_results.per_reading_mas.toFixed(2)} mAs</td></tr><tr style="background: #fff;"> <td style="padding:8px; border:1px solid #ddd;"><strong>Maximum readings per day</strong></td> <td style="padding:8px; border:1px solid #ddd; font-weight: bold; color: #16A085;">${ex_results.max_readings_per_day} readings</td></tr><tr style="background: #f8f9fa;"> <td style="padding:8px; border:1px solid #ddd;"><strong>Minimum interval between readings</strong></td> <td style="padding:8px; border:1px solid #ddd; font-weight: bold; color: #E67E22;">${ex_results.min_interval_sec} seconds (${(ex_results.min_interval_sec/60).toFixed(1)} minutes) </td></tr><tr style="background: #fff;"> <td style="padding:8px; border:1px solid #ddd;"><strong>Energy budget breakdown</strong></td> <td style="padding:8px; border:1px solid #ddd;"> Sleep: ${ex_results.sleep_percent.toFixed(1)}%, Readings: ${ex_results.reading_percent.toFixed(1)}% </td></tr></table><p style="margin-top: 1rem; font-size: 0.9em; color: #7F8C8D;">${ex_results.reading_percent>90?"⚠️ Readings dominate energy budget (>90%). Sleep current has minimal impact - focus on reducing TX frequency or energy per reading.": ex_results.sleep_percent>50?"⚠️ Sleep current dominates (>50%). Optimize sleep current before worrying about TX frequency.":"✅ Balanced budget. Both sleep and active states contribute significantly."}</p></div>`
Matching Quiz: Match Power Analysis Concepts
Ordering Quiz: Order the Power Budget Creation Process
Label the Diagram
💻 Code Challenge
Order the Steps
Match the Concepts
4.11 Summary
Key takeaways from power consumption analysis:
Sleep Dominates: For duty-cycled devices, sleep current × time often exceeds active consumption
Radio Idle is Expensive: Radio idle mode can consume 1,000-10,000× more than deep sleep
Calculate Average Current: Use the duty cycle formula to determine realistic battery life
Watch for Hidden Drains: Pull-ups, LEDs, debug interfaces, and regulators all consume power
Measure Real Hardware: Datasheet values are best-case; always measure actual consumption
Common Pitfalls
1. Not Measuring Radio Idle Current Separately
Many power budgets count only transmit current for the radio, but an idle radio waiting to transmit can draw 5–20 mA — comparable to or exceeding transmit current for short messages. Always add radio idle time to your current budget.
2. Using Average Current from a Single Measurement Instant
Measuring current with a multimeter gives the average over the meter’s response time (typically 100 ms–1 s). For devices with sub-second duty cycles, this misses the actual peak-and-sleep waveform. Use an oscilloscope with current probe or a dedicated power profiler.
3. Ignoring Pull-Up and Pull-Down Resistor Current
A 10 kΩ pull-up resistor on a GPIO pin held low continuously draws 330 µA — more than a sleeping MCU. On boards with multiple communication interfaces (I2C, SPI, UART), total pull-up leakage can exceed 1 mA during sleep.
4. Extrapolating Short-Term Measurements to Long Lifetimes
Measuring current for 10 minutes and extrapolating to 5 years misses infrequent high-current events (OTA updates, error retries, flash writes) that significantly affect average current. Profile across all operational states including exceptional cases.
4.12 What’s Next
If you want to…
Read this
Understand how individual operations contribute to energy