Measurement conditions: USB CDC disabled on boot. WOR preamble detection via CAD (Channel Activity Detection, Interrupt) — the project's current method, superseding the earlier autoDutyCycle approach used in the original Hackster write-up. Values pulled from the PPK2 windowed Selection box, except Image 1 (power-on), which has no selection box and reflects the full 1-second WINDOW capture.
Story arc: Power-on → Active spike → Average (active + sleep) → Sleep duration → WOR wake (manually triggered) → Continuous duty-cycle stream.
Path: Images/New/ on Tech500/Heating-System-Monitor-IV (all 6 URLs verified live)
Click image to enlarge.
Caption: EoRa-S3-900TB, power-on transient — 33.08 mA average, 91.08 mA max, over 1.000 s (33.08 mC charge). Full-window reading; no Selection box used.
Caption: Active current spike, segment — 7.43 mA average, 14.23 mA max, over 11.22 ms (83.34 µC charge).
Caption: Deep Sleep, active+sleep duty cycle average — Selection: 38.19 µA average, 11.71 mA max, over 5.087 s (194.27 µC charge).
Caption: Sleep-duration segment — Selection: 21.93 µA average, 23.06 µA max, over 5.057 s (110.91 µC charge).
Caption: LoRa WOR wake, manually triggered — 40.64 mA average, 105.44 mA max, 3.259 s (132.45 µC charge). EoRa-S3-900TB waking and running setup.
Caption: Continuous stream of duty cycle events over a 1-minute window — 37.19 µA average, 15.17 mA max, 2.23 mC charge (full WINDOW, no selection made). Illustrates cycle-to-cycle consistency of the CAD-based Interrupt, duty cycle; not intended as a new headline current figure, but as corroborating evidence for Image 3's Selection-box average.
Observations from this capture:
- Peak spike amplitude was confirmed zoom-invariant — checked at 10ms, 100ms, and 1-minute scales, with each spike reading the same true peak regardless of view. This rules out chart downsampling as the source of amplitude variation between individual spikes.
- The modest amplitude spread seen between spikes (~10–15 mA peak in this WINDOW view) is therefore a real characteristic, consistent with expected CAD detection-timing variance — how far into a CAD scan window the preamble happens to be detected can affect how much settle-time is captured before steady-state RX current is reached.
- The µA-scale average was observed to vary continuously between a high of ~40 µA and a low of ~21 µA during live viewing — closely matching Image 3's Selection average (38.19 µA, active-adjacent) and Image 4's Sleep Portion average (21.93 µA, sleep floor). This is good corroboration that the individual snapshot captures (Images 3 and 4) are representative of the node's real operating range, not outliers.
| # | Description | Avg | Max | Duration | Charge |
|---|---|---|---|---|---|
| 1 | Power-on (full window) | 33.08 mA | 91.08 mA | 1.000 s | 33.08 mC |
| 2 | Active spike | 7.43 mA | 14.23 mA | 11.22 ms | 83.34 µC |
| 3 | Average (active + sleep, selection) | 38.19 µA | 11.71 mA | 5.087 s | 194.27 µC |
| 4 | Sleep duration (selection) | 21.93 µA | 23.06 µA | 5.057 s | 110.91 µC |
| 5 | WOR manually triggered | 40.64 mA | 105.44 mA | 3.259 s | 132.45 µC |
| 6 | CAD duty cycle stream (1-min window) | 37.19 µA | 15.17 mA | 60.0 s | 2.23 mC |
Self-discharge rate is one of the biggest levers on real-world battery life for a low-draw, multi-year outdoor deployment — at these µA-scale currents, the battery's own internal leakage can rival or exceed the node's active power draw over time.
| Chemistry | Typical Self-Discharge | Cold-Temp Performance | Rechargeable | Notes |
|---|---|---|---|---|
| LiPo (Li-ion polymer) — current choice | ~2–3%/month | Degrades below ~0°C; capacity drops noticeably in freezing conditions | Yes | Good energy density, widely available, but needs protection circuitry and isn't ideal for an unheated outdoor enclosure through winter |
| LiFePO4 (LFP) | ~1–3%/month | Better cold tolerance than standard LiPo (usable to roughly -20°C) | Yes | Lower energy density (more physical volume for same mAh), but longer cycle life and better thermal/safety margin — a strong candidate for the outdoor node |
| Li-SOCl2 (Lithium Thionyl Chloride, primary) | <1% per year | Excellent — rated to -40°C in many parts | No (primary/disposable) | Very low self-discharge makes it well-suited to multi-year, low-duty-cycle deployments like this one; tradeoff is you replace rather than recharge the cell |
| NiMH (standard) | ~20–30%/month | Moderate; capacity drops in cold | Yes | Self-discharge alone would likely dominate your battery-life budget at these current levels — not a good fit here |
| NiMH (low self-discharge, e.g. Eneloop-style) | ~0.1–1%/month | Better than standard NiMH | Yes | Viable, but still generally lower energy density than LiPo/LFP for the same size |
| Alkaline (primary) | ~2–3% per year | Poor below freezing — voltage sags significantly | No | Low self-discharge, but cold-weather voltage sag is a real risk for an outdoor node through winter |
For this project specifically: given the outside node sits in a Stevenson screen exposed to real seasonal temperature swings, the two standouts are:
- LiFePO4 — if you want to stay rechargeable, this trades a bit of energy density for meaningfully better cold-weather behavior and self-discharge than standard LiPo, without changing your overall power budget much.
- Li-SOCl2 primary cell — if you're willing to give up rechargeability, the near-negligible self-discharge (<1%/year) means the CAD-based ~38.19 µA draw would dominate the battery-life calculation almost entirely, with self-discharge becoming a rounding error rather than a meaningful derating factor. Given your CAD-based numbers already put theoretical life in the 8–9 year range, a Li-SOCl2 primary cell could realistically make self-discharge nearly irrelevant to the final field-life number.
Worth weighing against your maintenance model — a primary cell means a physical swap eventually, while LiPo/LFP means periodic recharge access (relevant given the node's outdoor mounting).
The HSM IV outside node has two separate power components:
- Background CAD/WOR listening current
- Event-driven WOR wake energy
The battery-life calculation must include both.
The important distinction:
The CAD duty-cycle measurement does not include a full ESP32-S3 wake and
setup()execution. A WOR wake event only occurs when an actual blower OFF event is transmitted.
The SX1262 remains available for wake detection using:
- Channel Activity Detection (CAD)
- Interrupt wake
- ESP32-S3 deep sleep between CAD checks
Measured PPK2 value:
CAD duty-cycle average = 38.19 µA
This measurement already includes:
- CAD active periods
- SX1262 sleep periods
- ESP32-S3 deep sleep intervals
This represents the normal waiting state of the node.
A WOR wake occurs only when the blower OFF transmitter sends a valid WOR preamble.
The wake sequence includes:
- SX1262 detects preamble
- DIO1 interrupt wakes ESP32-S3
- ESP32-S3 boots
- Arduino framework starts
setup()executes- Sensors initialize
- ESP-NOW message is transmitted
- Node returns to sleep
PPK2 Image 5:
Average current = 40.64 mA
Duration = 3.259 seconds
Formula:
Charge = Current × Time
Calculation:
Charge = 40.64 mA × (3.259 seconds / 3600)
= 0.0368 mAh per event
Each complete blower-triggered WOR wake consumes approximately:
0.0368 mAh/event
Measured field activity:
Blower OFF events = 17 per day
0.0368 mAh/event × 17 events/day
= 0.6256 mAh/day
Convert daily event consumption to average current:
0.6256 mAh/day ÷ 24 hours
= 0.0261 mA
= 26.1 µA
Add the background CAD duty-cycle current:
CAD standby current = 38.19 µA
WOR event contribution = 26.10 µA
Total average current:
38.19 + 26.10
= 64.29 µA
Formula:
Battery Life (hours) = Battery Capacity / Average Current
Calculation:
Battery Life = 3000 mAh / 0.06429 mA
= 46,664 hours
= 1,944 days
≈ 5.3 years
This is the theoretical battery life assuming:
- 3000 mAh usable capacity
- no battery self-discharge
- no temperature losses
- no regulator losses
The actual battery life depends on HVAC activity.
The calculation model is:
Average Current =
CAD standby current
+
(WOR wake charge × blower events/day ÷ 24 hours)
Examples:
| Blower OFF Events/Day | Average Current |
|---|---|
| 0 | 38.19 µA |
| 1 | ~39.7 µA |
| 10 | ~53.5 µA |
| 17 | ~64.3 µA |
| 25 | ~76.5 µA |
| 50 | ~114.8 µA |
The earlier battery estimate using only 38.19 µA represented the maximum theoretical life of the node while waiting for a wake event.
The real-world value is lower because blower activity causes complete ESP32-S3 wake cycles.
The final battery-life estimate should therefore always include:
- measured CAD standby current
- measured WOR wake charge
- actual blower event frequency
This makes the battery estimate representative of the real HSM IV operating environment.
The HSM IV outside node battery life is not determined only by the low-power CAD listening current.
The actual field life is a combination of:
- SX1262 CAD/WOR duty-cycle consumption
- ESP32-S3 deep sleep current
- complete WOR wake and
setup()execution - number of blower OFF events per day
Using measured PPK2 values:
- CAD duty-cycle current: 38.19 µA
- WOR wake energy: 0.0368 mAh/event
- Example activity: 17 events/day
The calculated average current is:
64.29 µA
For a 3000 mAh battery:
≈ 5.3 years theoretical life
Actual field life will depend on battery chemistry, temperature, self-discharge, and HVAC operating conditions.
** Derate for real-world losses.** Theoretical figures assume 100% usable capacity and zero self-discharge, which never holds in practice. Typical derating factors for a 3000mAh LiPo:
| Factor | Typical Loss |
|---|---|
| LiPo self-discharge (~2–3%/month) | 15–25% over multi-year life |
| Voltage regulator/LDO quiescent draw | 5–15% |
| Cold-weather capacity reduction (outdoor node) | 10–20% seasonal |
| Cell aging / capacity fade over years | 10–20% by year 2–3 |
| Safety margin (don't run cells to 0%) | ~10% reserved |
Applying a combined 40–55% derating range to the theoretical figure gives a realistic 46–67 month estimate — consistent with the range already published in the Hackster write-up.
This project was the result of a collaborative engineering effort involving both hands-on experimentation and AI-assisted development. Each AI assistant contributed in different ways throughout the project.
-
Claude – Lead AI for all aspects of the project. Helped maintain technical focus, reviewed the evolving documentation for clarity and consistency, and provided extensive assistance in coding, organizing, and refining the final Markdown document.
-
Google Gemini – Provided valuable guidance during the migration to ESP32 Arduino Core 3.3.10, helping identify and avoid legacy code patterns from earlier ESP32 core releases. Gemini also contributed to development discussions involving SX1262 Channel Activity Detection (CAD), Wake-on-Radio (WOR), and ESP32-S3 Deep Sleep integration.
-
ChatGPT – Assisted throughout firmware development, debugging, architecture discussions, RadioLib integration, power optimization, Nordic PPK2 measurement interpretation, battery-life analysis, and technical review of the final documentation.
-
GitHub Copilot – Assisted with firmware implementation, code completion, and day-to-day development within the programming environment.
-
Jan Gromeš – Special thanks for the outstanding RadioLib library!
The successful implementation of an ESP32-S3 Deep Sleeping Wake-on-Radio node using the SX1262 and RadioLib was made possible through this collaborative process. While the hardware design, firmware integration, measurements, testing, and final engineering decisions were performed by the author, the insights provided by each AI assistant significantly accelerated development and helped improve the quality and accuracy of the final project.
"Project not possible without everyone's help."
Note: Two-WOR-trigger timing capture excluded — suspected variance from manual push-button hold time made the measurement unreliable. Five images kept the narrative focused on a single clean duty-cycle story.





