diff --git a/51-rooftop-hvac-predictive-maintenance/README.md b/51-rooftop-hvac-predictive-maintenance/README.md
index 6dd631b0..c50a4420 100644
--- a/51-rooftop-hvac-predictive-maintenance/README.md
+++ b/51-rooftop-hvac-predictive-maintenance/README.md
@@ -16,39 +16,43 @@ This project is a retrofit [downtime prevention](https://blues.com/downtime-prev
**The problem.** In HVAC, an **RTU** (rooftop unit) is a self-contained packaged HVAC system — compressor, condenser, evaporator, blower, and controls all in one box — mounted on the roof of a commercial building. It's the workhorse of light commercial cooling: the vast majority of grocery stores, restaurants, strip-mall tenants, and small warehouses are conditioned by one or more RTUs sitting above the suspended ceiling.
-A commercial RTU sits on a roof, cannot see building WiFi, and when it fails a grocery store or restaurant loses cooling and goes dark. The HVAC failures that cause most unplanned downtime aren't dramatic — they're gradual. A refrigerant leak slowly narrows the cooling delta-T over weeks. A tired contactor starts chattering, and the compressor short-cycles several times an hour instead of running in long, steady pulls. A neglected filter chokes airflow across the coil. None of these are invisible, but they're all easy to miss from inside the building — especially when nobody's looking. Each one is an impending failure detectable hours to days before the actual outage, *if* someone (or something) happens to be watching.
+A commercial RTU sits on a roof, cannot see building WiFi, and when it fails a grocery store or restaurant loses cooling and goes dark. The HVAC failures that cause most unplanned downtime aren't dramatic — they're gradual. A refrigerant leak slowly reduces cooling capabilities over weeks. A tired contactor starts chattering, and the compressor short-cycles several times an hour instead of running in long, steady pulls. A neglected filter chokes airflow across the coil. None of these are invisible, but they're all easy to miss from inside the building — especially when nobody's looking. Each one is an impending failure detectable hours to days before the actual outage, *if* someone (or something) happens to be watching.
-This project is that watcher. It's a retrofit sidecar that gets strapped to the RTU chassis on the roof, samples four sensors a minute, and pages the service technician *before* the walk-in cooler hits 50°F on a Saturday night. In Blues terms, it's a downtime-prevention device-to-cloud system: continuous remote monitoring on the edge, rule-based failure detection in firmware, and proactive-service alerts routed through Notehub to whatever on-call system the fleet owner already uses. The detection is heuristic — three scalar threshold checks, not a trained model, but it catches the impending-failure patterns HVAC technicians already look for on a service call.
+This project is that watcher. It's a retrofit sidecar that gets strapped to the RTU chassis on the roof, samples four sensors a minute, and pages the service technician *before* the walk-in cooler hits 50°F on a Saturday night. In Blues terms, it's a downtime-prevention device-to-cloud system: continuous remote monitoring on the edge, rule-based failure detection in firmware, and proactive-service alerts routed through [Blues Notehub](https://blues.com/notehub/) to whatever on-call system the fleet owner already uses. The detection includes three scalar threshold checks and catches impending-failure patterns HVAC technicians already look for on a service call.
**Why Notecard.** RTUs have no line-of-sight to indoor WiFi access points, and HVAC OEMs and service companies need a single SKU that works identically in a strip mall and in a warehouse. Cellular removes the per-site IT involvement entirely — there's no network form to fill out, no AP to pair to, and no IT ticket to chase. The Notecard Cell+WiFi variant keeps WiFi as an optional fallback for the occasional site that happens to have a rooftop-accessible AP, without compromising the cellular-first deployment model.
-**Deployment scenario.** A weatherproof enclosure strapped to the RTU frame, powered from 120VAC line at the RTU service disconnect (or from the 24VAC control transformer with an alternate supply. See [Limitations](#11-limitations-and-next-steps)), with four pigtails running into the unit: two thermistors (supply and return ducts), one clamp-on current transformer on the compressor hot leg, and one differential-pressure sensor with silicone tubes tapped across the filter. No RTU modification, no OEM cooperation, and no site IT coordination required.
-
## 2. System Architecture

-**Device-side responsibilities.** Inside the sidecar, the Cygnet STM32 host on the Notecarrier CX wakes once a minute, sweeps the four sensors, and runs the three failure-mode checks before the rooftop unit has time to make a meaningful change. When it's done, it hands the resulting Note to the Notecard over I²C and uses [`card.attn`](https://dev.blues.io/api-reference/notecard-api/card-requests/#card-attn) to cut its own power until the next interval. No JSON marshaling, no AT commands, no serial buffers to babysit — the host is asleep more than 99% of the time it sits on the roof.
+**Device-side responsibilities.** Inside the sidecar, the Cygnet STM32 host on the Notecarrier CX wakes once a minute, sweeps the four sensors, and runs the three failure-mode checks before the rooftop unit has time to make a meaningful change. When it's done, it hands the resulting Note (i.e. a JSON payload) to the Notecard over I²C and uses [`card.attn`](https://dev.blues.io/api-reference/notecard-api/card-requests/#card-attn) to cut its own power until the next interval. No JSON marshaling, no AT commands, no serial buffers to babysit — the host is asleep more than 99% of the time it sits on the roof.
-**Notecard responsibilities.** Everything the host queues up lands in the Notecard's on-device [Notes](https://dev.blues.io/api-reference/glossary/#note) store. Summary records ride out on the configured [`hub.set`](https://dev.blues.io/api-reference/notecard-api/hub-requests/#hub-set) `outbound` cadence (default 60 minutes); any alert tagged `sync:true` skips the queue and the radio comes up immediately to ship it. The same Notecard also handles one-time GNSS site geolocation autonomously and pulls [environment variables](https://dev.blues.io/guides-and-tutorials/notecard-guides/understanding-environment-variables/) on every inbound sync, which is how a fleet operator retunes thresholds across a thousand rooftops without anyone touching firmware.
+**Notecard responsibilities.** Everything the host queues up lands in the Notecard's on-device [Notes](https://dev.blues.io/api-reference/glossary/#note) store. Summary records ride out on the configured [`hub.set`](https://dev.blues.io/api-reference/notecard-api/hub-requests/#hub-set) `outbound` cadence (default 60 minutes); any alert tagged `sync:true` skips the queue and the cellular radio comes up immediately to ship it. The same Notecard also handles one-time GNSS site geolocation autonomously and pulls [environment variables](https://dev.blues.io/guides-and-tutorials/notecard-guides/understanding-environment-variables/) (i.e. cloud variables) on every inbound sync, which is how a fleet operator re-tunes thresholds across a thousand rooftops without anyone touching firmware.
-**Notehub responsibilities.** The Notecard's embedded global SIM gets it onto whichever carrier covers the rooftop, and from there events flow into [Notehub](https://notehub.io), which ingests them, stores every one, and applies the project's routes. Alerts and summaries land in separate [Notefiles](https://dev.blues.io/api-reference/glossary/#notefile) on purpose — that lets you route `rtu_alert.qo` straight to an on-call paging service or CMMS (computerized maintenance management system) while `rtu_summary.qo` flows to a long-term analytics store without any filtering logic in the route itself.
+**Notehub responsibilities.** The Notecard's embedded global SIM gets it onto whichever carrier covers the rooftop, and from there events flow into [Notehub](https://notehub.io), which ingests them, stores every one, and applies the project's routes to optionally sync data to your cloud platform of choice. Alerts and summaries land in separate [Notefiles](https://dev.blues.io/api-reference/glossary/#notefile) on purpose — that lets you route `rtu_alert.qo` JSON-based Notes straight to an on-call paging service or CMMS (computerized maintenance management system) while `rtu_summary.qo` flows to a long-term analytics store without any filtering logic in the route itself.
-**Routing to the cloud (high level only).** Notehub supports HTTP, MQTT, AWS, Azure, GCP, Snowflake, and several other destinations; route setup is project-specific. See the [Notehub routing docs](https://dev.blues.io/notehub/notehub-walkthrough/#routing-data-with-notehub) — this project doesn't ship any specific downstream endpoint.
+**Routing to the cloud (high level only).** Notehub supports HTTP, MQTT, AWS, Azure, GCP, Snowflake, Twilio, and several other destinations; route setup is project-specific. See the [Notehub routing docs](https://dev.blues.io/notehub/notehub-walkthrough/#routing-data-with-notehub) — this project doesn't ship any specific downstream endpoint, but it is trivial to route data to your selected cloud endpoint.
## 3. Technical Summary
If you want the fastest path from "parts on the bench" to "first event in Notehub":
-1. **Notehub** — create a [Notehub project](https://notehub.io), copy its ProductUID.
+1. **Notehub** — create a free [Notehub project](https://notehub.io), copy its ProductUID.
2. **Wire the bench rig** — [Notecarrier CX](https://shop.blues.com/products/notecarrier-cx?utm_source=dev-blues&utm_medium=web&utm_campaign=store-link) + [Notecard MBGLW](https://dev.blues.io/datasheets/notecard-datasheet/note-mbglw/) + two thermistor dividers on A0/A1 + CT bias network on A2 + SDP810 on I²C. Full pinout is in [§5](#5-wiring-and-assembly).
3. **Edit one line** of [`firmware/rtu_predictive_maintenance/rtu_predictive_maintenance.ino`](firmware/rtu_predictive_maintenance/rtu_predictive_maintenance.ino) — set `PRODUCT_UID` to your project's value (line 24).
4. **Flash** — `arduino-cli compile -b STMicroelectronics:stm32:Cygnet` then `arduino-cli upload`. Full instructions in [§7.1](#71-installing-and-flashing).
-5. **Watch** — open Notehub → your project → **Events** tab. You should see a `_session.qo` immediately, an `rtu_summary.qo` within an hour, and any threshold trips as `rtu_alert.qo` in real time.
+5. **Watch** — open Notehub → your project → **Events** tab. You should see a `_session.qo` within minutes, an `rtu_summary.qo` within an hour, and any threshold trips as `rtu_alert.qo` in real time.
+
+The rest of this document expands each step and explains why the firmware is shaped the way it is.
+
+
-The rest of this README expands each step and explains why the firmware is shaped the way it is. If you're doing a real rooftop install rather than a bench bring-up, also read [§11 Limitations](#11-limitations-and-next-steps) before you commit to a power topology.
+If you're doing a real rooftop install rather than a bench bring-up, also read [§11 Limitations](#11-limitations-and-next-steps) before you commit to a power topology.
+
+
Here is a sample Note this device emits:
@@ -68,9 +72,9 @@ Here is a sample Note this device emits:
| Part | Qty | Rationale |
|------|-----|-----------|
-| [Notecarrier CX](https://shop.blues.com/products/notecarrier-cx?utm_source=dev-blues&utm_medium=web&utm_campaign=store-link) | 1 | Integrated carrier with an embedded Cygnet STM32 host — no separate MCU needed for this sensor mix. |
+| [Notecarrier CX](https://shop.blues.com/products/notecarrier-cx?utm_source=dev-blues&utm_medium=web&utm_campaign=store-link) | 1 | Integrated carrier board with an embedded Cygnet STM32 host — no separate MCU needed for this sensor mix. |
| [Notecard Cell+WiFi (MBGLW)](https://shop.blues.com/products/notecard-cell-wifi?utm_source=dev-blues&utm_medium=web&utm_campaign=store-link) / [datasheet](https://dev.blues.io/datasheets/notecard-datasheet/note-mbglw/) | 1 | Cellular removes per-site IT involvement; WiFi fallback is available for sites that happen to have it. |
-| [Blues Mojo](https://shop.blues.com/products/mojo?utm_source=dev-blues&utm_medium=web&utm_campaign=store-link) *(optional, bench-only)* | 0–1 | Coulomb counter on the power rail for ground-truth energy validation during bench bring-up. **Not required for production deployment**. See [§9](#9-validation-and-testing) and [§11](#11-limitations-and-next-steps). |
+| [Blues Mojo](https://shop.blues.com/products/mojo?utm_source=dev-blues&utm_medium=web&utm_campaign=store-link) *(optional, bench-only)* | 0–1 | Coulomb counter on the power rail for ground-truth energy validation during bench bring-up. See [§9](#9-validation-and-testing) and [§11](#11-limitations-and-next-steps). |
| 10 kΩ NTC thermistor, β=3950, waterproof duct probe | 2 | Duct-mount supply and return air temperature for cooling delta-T. |
| 10 kΩ 1% resistor (divider series leg) | 2 | Pull-up for each thermistor divider. |
| SCT-013-030 split-core CT, 30A / 1V AC (e.g. [SparkFun SEN-11005](https://www.sparkfun.com/products/11005)) (current-output CT; add external burden resistor for 1 V_rms scaling) | 1 | Non-invasive compressor current sensing; 30A matches single-phase light-commercial RTU compressors. |
@@ -82,7 +86,7 @@ Here is a sample Note this device emits:
| AC/DC supply, 5V/2A output (e.g. [MeanWell IRM-03-5](https://www.meanwell.com/Upload/PDF/IRM-03/IRM-03-SPEC.PDF)) | 1 | Derives 5V DC from 120VAC line power at the RTU service disconnect for permanent grid-tied power. See [Limitations](#11-limitations-and-next-steps) for the 24VAC-input alternative. |
| NEMA 4X enclosure, ~6×4×2″ | 1 | Rooftop-rated housing. |
-All Blues parts ship with an active SIM including 500 MB of data and 10 years of service — no activation fees, no monthly commitment.
+All Blues parts ship with an embedded SIM including 500 MB of data and 10 years of service — no activation fees, no monthly commitment.
## 5. Wiring and Assembly
@@ -127,6 +131,12 @@ Mount probes inside the unit: supply thermistor ~12″ past the evaporator coil
6. **Configure routes.** At a minimum, add one [route](https://dev.blues.io/notehub/notehub-walkthrough/#routing-data-with-notehub) for `rtu_alert.qo` (to an on-call or CMMS endpoint) and a second for `rtu_summary.qo` (to a long-term store). Separating the two Notefiles at the source means you can fan them out to different destinations at different urgencies without any filtering in the route itself.
+
+
+Consult the guide on [configuring a Twilio route](https://dev.blues.io/notehub/messaging-and-data-pipelines/configuring-a-twilio-route/) to set up SMS messaging.
+
+
+
### What you should see in Notehub
Within a minute of first power-on, the **Events** tab in your project should start populating. Three event kinds matter for this project:
@@ -215,7 +225,7 @@ Example alert body:
### 7.5 Low-power strategy
-Even with grid-tied power available, we still keep the host asleep most of the time — less heat in the enclosure, less wear on the supply, and a firmware pattern that ports directly to battery- or solar-powered variants without a rewrite. After each sample cycle the host calls `NotePayloadSaveAndSleep`, a `note-arduino` helper that serializes the in-RAM `PersistState` struct into Notecard flash and then issues a [`card.attn`](https://dev.blues.io/api-reference/notecard-api/card-requests/#card-attn) request configured to cut host power entirely for `sample_interval_sec` seconds. When ATTN re-fires, the Notecarrier re-applies host power, the MCU enters `setup()` from cold, and `NotePayloadRetrieveAfterSleep` pulls the saved struct back. From the firmware author's perspective, the sleep call looks like a single line — the Notecard does the rest.
+Even with line power available, we still keep the host asleep most of the time — less heat in the enclosure, less wear on the supply, and a firmware pattern that ports directly to battery- or solar-powered variants without a rewrite. After each sample cycle the host calls `NotePayloadSaveAndSleep`, a `note-arduino` helper that serializes the in-RAM `PersistState` struct into Notecard flash and then issues a [`card.attn`](https://dev.blues.io/api-reference/notecard-api/card-requests/#card-attn) request configured to cut host power entirely for `sample_interval_sec` seconds. When ATTN re-fires, the Notecarrier re-applies host power, the MCU enters `setup()` from cold, and `NotePayloadRetrieveAfterSleep` pulls the saved struct back. From the firmware author's perspective, the sleep call looks like a single line — the Notecard does the rest.
The Notecard itself sits in its own [low-power idle](https://dev.blues.io/notecard/notecard-walkthrough/low-power-firmware-design/) (~8 µA @ 5V) between cellular wakes. Sample rate and transmit rate are deliberately decoupled: we sample every 60 seconds but only transmit once an hour — alerts are the only thing that bypass the transmit timer.
@@ -306,15 +316,13 @@ The [Mojo](https://dev.blues.io/datasheets/mojo-datasheet/) reports cumulative m
Because the deployed RTU is grid-tied through the 120VAC service-disconnect supply, the absolute mAh number matters less in production than the *shape* of the trace. The bench measurement is still worth doing once per firmware revision — it's the cheapest way to catch a regression that silently keeps the host awake.
-Mojo is **not required for production deployment** — it's a bring-up and CI-style regression tool. Once a firmware revision passes the trace check, the deployed units don't need it.
-
## 10. Troubleshooting
A short field guide for the things that actually go wrong on first bring-up.
| Symptom | Likely cause | What to check |
|---|---|---|
-| Device never appears in Notehub's **Devices** tab. | `PRODUCT_UID` is empty or wrong, or the cellular antenna is disconnected / indoors. | Re-verify `PRODUCT_UID` matches the Notehub project exactly. Move the unit outside or near a window. Check `_session.qo` events — none means no cellular connection. |
+| Device never appears in Notehub's **Devices** tab. | `PRODUCT_UID` is empty or wrong, or the cellular antenna is disconnected. | Re-verify `PRODUCT_UID` matches the Notehub project exactly. Move the unit outside or near a window. Check `_session.qo` events — none means no cellular connection. |
| Device appears, `_session.qo` events arrive, but no `rtu_summary.qo` ever shows up. | All sensor reads are returning `NaN`, so `sendSummary` short-circuits via the `any_valid` guard. | Open the serial monitor at 115200 baud and watch the `[sample]` lines. Any field reading `nan` indicates an unplugged or miswired sensor. |
| Thermistor reads pegged at one extreme. | Probe is open (reads near `+3V3`) or shorted (reads near 0 V). | The firmware returns `NaN` outside the valid divider range, so you'll see `nan` rather than misleading numbers. Check the divider wiring at A0 / A1. |
| `compressor_amps` always 0 even with the compressor running. | CT is on the neutral leg or both hot legs (currents cancel), or the bias network is missing the 10 µF cap. | Re-clamp the CT on **one** hot leg only. Verify the A2 bias node sits at ~Vref/2 (1.65 V) at idle. |
@@ -322,8 +330,12 @@ A short field guide for the things that actually go wrong on first bring-up.
| Alerts firing constantly on a healthy unit. | Thresholds aren't tuned for this unit yet. | Raise `delta_t_min_f` toward 14–15 °F if the supply duct runs short, and watch one `rtu_summary.qo` per hour to see what the actual operating envelope looks like. |
| Mojo bench trace shows continuous tens of mA. | Host isn't sleeping — `card.attn` isn't gating power. | Confirm you're on a Notecarrier CX (which supports ATTN host gating); see [§9](#9-validation-and-testing) for trace shapes. |
+
+
If a problem isn't on this list, the [Blues community forum](https://discuss.blues.com) is generally the fastest place to get a second pair of eyes on a Notecard + sensor setup.
+
+
## 11. Limitations and Next Steps
This pack is deliberately a starting point — small, retrofittable, and aimed at the failure modes a single technician already knows how to recognize. A handful of things are out of scope on purpose, and a longer list of extensions makes sense once the basic detector is paying for itself.