From 5baf56108ab9122d9e92b8917a2e99c0b463ffcb Mon Sep 17 00:00:00 2001 From: Rob Lauer Date: Fri, 12 Jun 2026 14:50:00 -0500 Subject: [PATCH 1/2] 63-66 review --- .../README.md | 14 +++++++------- .../README.md | 6 +++--- 66-remote-apiary-hive-health-monitor/README.md | 16 ++++++++-------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/63-construction-equipment-anti-theft-tracker-with-immobilizer/README.md b/63-construction-equipment-anti-theft-tracker-with-immobilizer/README.md index d8a199aa..625c5b0e 100644 --- a/63-construction-equipment-anti-theft-tracker-with-immobilizer/README.md +++ b/63-construction-equipment-anti-theft-tracker-with-immobilizer/README.md @@ -8,17 +8,17 @@ This reference application is intended to provide inspiration and help you get s -This project is a [loss prevention](https://blues.com/loss-prevention/) reference design for construction equipment fleets. The system turns any skid steer, light tower, portable compressor, or generator into a hardened asset that reports its own location continuously, fires alerts on geofence breach and after-hours motion, and accepts a remotely-staged ignition immobilizer command — all on a self-contained cellular-plus-satellite link with a small solar-trickled battery for power, no job-site WiFi or IT coordination required. Specific Blues hardware, sensors, and the wiring path into the ignition circuit are in §4 and §5. +This project is a [loss prevention](https://blues.com/loss-prevention/) reference design for construction equipment fleets. The system turns any skid steer, light tower, portable compressor, or generator into a hardened asset that reports its own location continuously, fires alerts on geofence breach and after-hours motion, and accepts a remotely-staged ignition immobilizer command. It runs on a self-contained cellular-plus-satellite link with a small solar-trickled battery, requiring no job-site WiFi or IT coordination. ## 1. Project Overview -**The problem.** Construction equipment theft is a serious, costly, and chronically underreported problem. A skid steer that costs $60,000 to replace can be driven onto a flatbed and hauled off in under ten minutes. A light tower or portable generator can be gone before the morning crew arrives. These aren't smash-and-grab events — the equipment is large, identifiable, and completely exposed on a site that often goes unwatched overnight. Law enforcement recovery rates for heavy equipment are low; the stolen unit frequently ends up at a rural stash yard, stripped, or loaded into a shipping container for export. Neither scenario is good for cellular telemetry that depends on urban coverage. +**The problem.** Construction equipment theft is a serious, costly, and chronically underreported problem. A skid steer that costs $60,000 to replace can be driven onto a flatbed and hauled off in under ten minutes. A light tower or portable generator can be gone before the morning crew arrives. These aren't smash-and-grab events — the equipment is large, identifiable, and completely exposed on a site that often goes unwatched overnight. Law enforcement recovery rates for heavy equipment are low; the stolen unit frequently ends up at a rural stash yard, stripped, or loaded into a shipping container for export. A rural stash yard or a shipping container is exactly where cellular telemetry that depends on urban coverage goes dark. The result is an industry that leans heavily on equipment marking, insurance claims, and post-theft police reports. What's mostly missing is a device that provides real-time location during a theft in progress *and* can physically disable the equipment before it leaves the region — all without depending on an infrastructure that may not exist at the job site or at the final stash location. This project is that device. It monitors GPS location against a configurable job-site geofence, watches for unexpected after-hours motion, and accepts a remote immobilizer command from the [Blues Notehub](https://blues.com/notehub/) cloud service that stages a relay to cut the ignition circuit on the thief's next key-on attempt — a polled, staged proof-of-concept immobilizer rather than a continuously-held cut, with the limitations that implies (see §11). The whole stack — GPS, cellular, and satellite fallback — is contained in a single Blues Notecard for Skylo installed in a weatherproof enclosure that runs indefinitely on a LiPo battery topped off by a small solar panel. -**Why Notecard.** Construction sites have no WiFi. Even if a site happens to have a hotspot, requiring site IT coordination for a security device defeats the purpose. Cellular works for the vast majority of scenarios, but a stolen skid steer doesn't stay parked in a well-covered urban area. It ends up in a rural equipment yard, a metal barn, or a shipping container at a port. That's the scenario where cellular alone fails and satellite becomes the difference between a recovered asset and a total write-off. Notecard for Skylo ([NOTE-NBGLWX](https://dev.blues.io/datasheets/notecard-datasheet/note-nbglwx/)) handles all three radio paths — LTE-M/NB-IoT cellular, WiFi (where available), and Skylo satellite — in a single M.2 module, without any firmware branching. Planetary roaming and satellite fallover are not optional extras for this use case; they are the core differentiators. +**Why Notecard.** Construction sites have no WiFi. Even if a site happens to have a hotspot, requiring site IT coordination for a security device defeats the purpose. Cellular works for the vast majority of scenarios, but a stolen skid steer doesn't stay parked in a well-covered urban area. It ends up in a rural equipment yard, a metal barn, or a shipping container at a port. That's the scenario where cellular alone fails and satellite becomes the difference between a recovered asset and a total write-off. Notecard for Skylo ([NOTE-NBGLWX](https://dev.blues.io/datasheets/notecard-datasheet/note-nbglwx/)) handles all three radio paths — LTE-M/NB-IoT cellular, WiFi (where available), and Skylo satellite — in a single M.2 module, without any firmware branching. Global roaming and satellite failover are not optional extras for this use case; they are the core differentiators. @@ -114,7 +114,7 @@ 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) ([datasheet](https://dev.blues.io/datasheets/notecarrier-datasheet/notecarrier-cx-v1-7/)) | 1 | Compact carrier with embedded Cygnet STM32 host MCU — no separate Swan or Feather needed. ATTN pin is wired to control the Cygnet's power rail, enabling deep sleep via `card.attn`. | -| [Notecard for Skylo (NOTE-NBGLWX)](https://shop.blues.com/products/notecard-for-skylo?utm_source=dev-blues&utm_medium=web&utm_campaign=store-link) ([datasheet](https://dev.blues.io/datasheets/notecard-datasheet/note-nbglwx/)) | 1 | All-in-one LTE-M/NB-IoT/GPRS + WiFi + Skylo satellite in a single M.2 module. Automatic cellular-to-satellite fallover with no firmware changes. Ships with its Skylo-certified `MAIN` cellular/satellite antenna (see antenna row below). Includes 500 MB cellular data and 10 KB/month Skylo data. | +| [Notecard for Skylo (NOTE-NBGLWX)](https://shop.blues.com/products/notecard-for-skylo?utm_source=dev-blues&utm_medium=web&utm_campaign=store-link) ([datasheet](https://dev.blues.io/datasheets/notecard-datasheet/note-nbglwx/)) | 1 | All-in-one LTE-M/NB-IoT/GPRS + WiFi + Skylo satellite in a single M.2 module. Automatic cellular-to-satellite failover with no firmware changes. Ships with its Skylo-certified `MAIN` cellular/satellite antenna (see antenna row below). Includes 500 MB cellular data and 10 KB/month Skylo data. | | [Blues Mojo](https://shop.blues.com/products/mojo?utm_source=dev-blues&utm_medium=web&utm_campaign=store-link) ([datasheet](https://dev.blues.io/datasheets/mojo-datasheet/)) | 1 | Bench-only coulomb counter for energy validation during commissioning. Placed inline on the +VBAT rail to measure current draw across sleep, active, and transmit phases. Not deployed in the field (see §11). | | 3.7 V LiPo battery, 2000 mAh, JST-PH 2.0 mm (e.g. [Adafruit 2011](https://www.adafruit.com/product/2011), or equivalent 2000–4000 mAh cell) | 1 | Primary energy storage. Size capacity against expected solar availability and desired dark-sky reserve; see §9 for a phase-by-phase current-draw breakdown to inform your sizing. | | 6 V, 10 W solar panel, ~110×70 mm (e.g. [Voltaic Systems P110](https://voltaicsystems.com/p110/)) | 1 | Trickle-charges the LiPo during daylight hours. Construction equipment typically lives outdoors; the 10 W panel provides ample headroom even for sites with limited direct sun or extended overcast periods. | @@ -313,7 +313,7 @@ Alert types: The Cygnet host and the Notecard are both put to sleep between sensing cycles. At the end of each wake, the firmware calls `NotePayloadSaveAndSleep`, which serializes the `AppState` struct to Notecard flash as a base64 payload and then issues [`card.attn`](https://dev.blues.io/api-reference/notecard-api/card-requests/#card-attn) with `mode:sleep` — physically cutting the Cygnet's power via the Notecarrier CX's ATTN-controlled power rail. The Notecard itself enters its own [low-power idle state](https://dev.blues.io/notecard/notecard-walkthrough/low-power-firmware-design/) (~8–18 µA @ 5V) between cellular sync windows. After `sleep_sec` seconds, the ATTN pin goes HIGH and the Cygnet's power is restored; `setup()` runs fresh and `NotePayloadRetrieveAfterSleep` rehydrates the state struct. -The sleep duration adapts to context: 2 minutes during after-hours (fast theft detection), 5 minutes while moving (active tracking), 1 hour during business hours at rest (background monitoring, and worst-case geofence-detection latency while parked). The after-hours wake interval is intentionally shorter than the heartbeat emission interval — the device wakes every 2 minutes to check for alerts and inbound commands, but heartbeat Notes queue at the stationary or moving rate regardless of time of day. This keeps the overnight Note volume consistent with daytime operation while still catching a theft event within the scan window. **Sampling/queuing cadence and transmission cadence are always distinct.** Heartbeat Notes are queued by the host into the Notecard's local flash, then transmitted to Notehub on the next outbound sync session — which fires at the `hub.set outbound` interval (set by `outbound_min`, default 240 minutes). A 5-minute moving sample rate means the Notecard accumulates a heartbeat every 5 minutes while in motion, but those records are batch-transmitted on the next outbound session unless an alert happens to force a `sync:true` flush first. Only `alert.qo` Notes (with `sync:true`) bypass the outbound window and trigger an immediate uplink sync. Separately, the Notecard independently manages its own **inbound sync sessions** — these are cellular connections the Notecard initiates on its own schedule to pull queued commands and updated environment variables from Notehub. The inbound cadence is context-aware: when the equipment is parked and daytime, the interval matches `heartbeat_stopped_min` (default 60 minutes, set via `hub.set inbound`); when after-hours or moving, it shortens to `inbound_min` (default 4 minutes). These inbound sessions are Notecard-driven and occur regardless of whether the Cygnet host is currently awake. The host's 2-minute after-hours wake cycle and the Notecard's inbound cellular cadence are independent of each other and tuned via separate parameters (`heartbeat_afterhours_min` and `inbound_min`, respectively). The Notecard's inbound cadence is context-aware: short (`inbound_min`, default 4 minutes) when after-hours or moving, and long (`heartbeat_stopped_min`, default 60 minutes) when parked and daytime, so daytime inbound sessions match the host wake cadence rather than running dozens of times per hour against a parked asset. Both must be accounted for when sizing the energy budget (see §9). +The sleep duration adapts to context: 2 minutes during after-hours (fast theft detection), 5 minutes while moving (active tracking), 1 hour during business hours at rest (background monitoring, and worst-case geofence-detection latency while parked). The after-hours wake interval is intentionally shorter than the heartbeat emission interval — the device wakes every 2 minutes to check for alerts and inbound commands, but heartbeat Notes queue at the stationary or moving rate regardless of time of day. This keeps the overnight Note volume consistent with daytime operation while still catching a theft event within the scan window. **Sampling/queuing cadence and transmission cadence are always distinct.** Heartbeat Notes are queued by the host into the Notecard's local flash, then transmitted to Notehub on the next outbound sync session — which fires at the `hub.set outbound` interval (set by `outbound_min`, default 240 minutes). A 5-minute moving sample rate means the Notecard accumulates a heartbeat every 5 minutes while in motion, but those records are batch-transmitted on the next outbound session unless an alert happens to force a `sync:true` flush first. Only `alert.qo` Notes (with `sync:true`) bypass the outbound window and trigger an immediate uplink sync. Separately, the Notecard independently manages its own **inbound sync sessions** — these are cellular connections the Notecard initiates on its own schedule to pull queued commands and updated environment variables from Notehub. The inbound cadence is context-aware: when the equipment is parked and daytime, the interval matches `heartbeat_stopped_min` (default 60 minutes, set via `hub.set inbound`); when after-hours or moving, it shortens to `inbound_min` (default 4 minutes). These inbound sessions are Notecard-driven and occur regardless of whether the Cygnet host is currently awake. The host's 2-minute after-hours wake cycle and the Notecard's inbound cellular cadence are independent of each other and tuned via separate parameters (`heartbeat_afterhours_min` and `inbound_min`, respectively), so daytime inbound sessions match the host wake cadence rather than running dozens of times per hour against a parked asset. Both cadences must be accounted for when sizing the energy budget (see §9). **Env-var cadence retuning scope.** When an operator changes any cadence variable (`heartbeat_moving_min`, `heartbeat_stopped_min`, `heartbeat_afterhours_min`, `inbound_min`, or `outbound_min`) via Notehub, the firmware detects the change via the `env.get` delta check and calls `applyHubCadence()`, which reissues `hub.set` (outbound and inbound windows) and `card.location.mode` (GNSS acquisition seconds, set to `heartbeat_moving_s`). `applyHubCadence()` is also called immediately when the motion or after-hours context transitions, so the Notecard's inbound window switches between the short active-monitoring interval (`inbound_min`) and the long parked interval (`heartbeat_stopped_min`) without waiting for a future env-var change. The outbound window uses `outbound_s` (set by `outbound_min`, default 240 minutes) — decoupled from the host wake interval. Env-var changes do not affect `card.motion.mode` (accelerometer sensitivity and bucket size) — those are set at cold boot only and require a firmware update to change. @@ -398,7 +398,7 @@ NotePayloadSaveAndSleep(&save, sleep_sec, NULL); ![Data flow: ignition/motion/GPS/battery → Cygnet edge rules → alert.qo (sync:true, immediate) and tracker.qo (queued, batch outbound) → Notehub → routes; immobilize.qi inbound from Notehub to Cygnet → relay](diagrams/03-data-flow.svg) -**Collected every wake cycle.** Ignition state (12V voltage divider), motion status (Notecard accelerometer, read via `card.motion`), GPS fix (Notecard GNSS, read via `card.location`), battery voltage (`card.voltage`), UTC epoch (`card.time`). No I²C sensors external to the Notecard are used — all sensing is built into Notecard for Skylo module. +**Collected every wake cycle.** Ignition state (12V voltage divider), motion status (Notecard accelerometer, read via `card.motion`), GPS fix (Notecard GNSS, read via `card.location`), battery voltage (`card.voltage`), UTC epoch (`card.time`). No I²C sensors external to the Notecard are used — all sensing is built into the Notecard for Skylo module. **Transmitted:** @@ -546,4 +546,4 @@ The engineering work that turns this into a production security device follows, ## 12. Summary -The fleet manager who used to learn about a stolen skid steer when the morning crew arrived now learns about it within minutes of the wheels moving — and has a staged immobilizer command ready to fire on the thief's next key-on. A Notecarrier CX and Notecard for Skylo, a solar-trickled LiPo, and two wires into the ignition circuit turn the equipment into a recoverable asset. Hourly heartbeats during the business day, rapid two-minute after-hours scans that fire immediate alerts on motion, and a staged relay that blocks ignition on the next key cycle the Cygnet observes — that's the loop, with a production latching relay as the clear next step. And when the equipment ends up exactly where stolen equipment ends up — rural stash yard, shipping container, metal barn — Skylo satellite carries the location and alert Notes skyward when cellular has long since gone dark. That's the difference between a recovered skid steer and one that's already been exported. +The fleet manager who used to learn about a stolen skid steer when the morning crew arrived now learns about it within minutes of the wheels moving, and has a staged immobilizer command ready to fire on the thief's next key-on. A Notecarrier CX and Notecard for Skylo, a solar-trickled LiPo, and two wires into the ignition circuit turn the equipment into a recoverable asset. Hourly heartbeats during the business day, rapid two-minute after-hours scans that fire immediate alerts on motion, and a staged relay that blocks ignition on the next key cycle the Cygnet observes — that's the loop, with a production latching relay as the clear next step. And when the equipment ends up exactly where stolen equipment ends up — rural stash yard, shipping container, metal barn — Skylo satellite carries the location and alert Notes skyward when cellular has long since gone dark. That's the difference between a recovered skid steer and one that's already been exported. diff --git a/65-off-grid-livestock-water-tank-monitor/README.md b/65-off-grid-livestock-water-tank-monitor/README.md index 1754a25d..fab8c95f 100644 --- a/65-off-grid-livestock-water-tank-monitor/README.md +++ b/65-off-grid-livestock-water-tank-monitor/README.md @@ -8,7 +8,7 @@ This reference application is intended to provide inspiration and help you get s -This project is a solar-powered [remote monitoring](https://blues.com/solutions-remote-monitoring/) system for off-grid livestock water tanks. The system tells a rancher when a stock tank is going dry without driving the pasture roads — measuring the water level, the pump's current draw, and the solar system's own battery voltage, then reporting all three to a phone or dispatch system over cellular wherever a tower is reachable and over satellite via [Skylo](https://www.skylo.tech/)'s non-terrestrial network (NTN) where it isn't. The radio stays off between an immediate alert and a 4-hour summary, so the device runs indefinitely on a modest solar panel and a single battery. +This project is a solar-powered [remote monitoring](https://blues.com/solutions-remote-monitoring/) system for off-grid livestock water tanks. It tells a rancher when a stock tank is going dry — without anyone driving the pasture roads to check. The device measures the water level, the pump's current draw, and the solar system's own battery voltage, then reports all three to a phone or dispatch system over cellular wherever a tower is reachable and over satellite via [Skylo](https://www.skylo.tech/)'s non-terrestrial network (NTN) where it isn't. The radio stays off between an immediate alert and a 4-hour summary, so the device runs indefinitely on a modest solar panel and a single battery. ## What You'll Build @@ -23,7 +23,7 @@ Expected data consumption: ~6 KB/month on the 500 MB included prepaid Blues data ## 1. Project Overview -**The problem.** Stock tanks in remote pastures are one of agriculture's oldest and most persistent operational problems. A rancher managing a spread across multiple pastures — each with its own poly or galvanized stock tank and a submersible pump pulling from a well — has to physically drive every road to verify that every tank is full. On a working ranch with pastures spread over thousands of acres, that inspection loop can take several hours and still miss a dry tank that empties between visits. The consequences aren't just inconvenience: cattle deprived of water for even a few hours in summer heat suffer rapid decline in health, and emergency water delivery is expensive before factoring in animal losses at all. +**The problem.** Stock tanks in remote pastures are one of agriculture's oldest and most persistent operational problems. A rancher managing a spread across multiple pastures — each with its own poly or galvanized stock tank and a submersible pump pulling from a well — has to physically drive every road to verify that every tank is full. On a working ranch with pastures spread over thousands of acres, that inspection loop can take several hours and still miss a dry tank that empties between visits. The consequences aren't just inconvenience: cattle deprived of water for even a few hours in summer heat suffer rapid decline in health, and emergency water delivery is expensive even before factoring in animal losses. The failure modes are simple and repeatable. Tanks go dry because a float valve sticks or fails and the tank drains down, because the pump's supply well drops below the intake (the pump keeps running but moves no water), or because the pump motor fails entirely and nothing moves even when the float calls for it. None of these require sophisticated modeling — they are observable conditions that nobody happens to be watching. The sensor suite here measures exactly the two signals a rancher or hired hand would check on a physical inspection: how high is the water, and is the pump drawing current? The third measurement — solar battery voltage — tells you whether the monitoring system itself is healthy and likely to keep reporting through a run of cloudy days. @@ -495,4 +495,4 @@ Once a rancher is running the basic tank monitor, the following extensions are t ## 12. Summary -A Notecarrier CX and Notecard for Skylo — paired with a weatherproof ultrasonic level sensor, a clamp-on current transformer, and a handful of passive components — give a rancher continuous visibility into every stock tank on the property without driving the pasture roads. Notecard for Skylo uses cellular where a tower is reachable and falls back to the Skylo satellite network where terrestrial coverage ends, so tanks in covered valleys and tanks on remote ridges both report through the same firmware and the same Notehub project. Sampling happens locally every 15 minutes with the host MCU asleep between measurements; the radio wakes only for the 4-hour summary or an immediate alert. That duty cycle makes the system comfortable running indefinitely on a modest solar setup, with built-in power-aware sleep extension to handle extended overcast stretches in northern winters. Dry-tank alerts and solar fault alerts reach the rancher's phone before cattle suffer from dehydration; pump current is captured as observational telemetry in every summary and alert payload so operators can correlate it with tank levels after the fact. It's a simple problem — know when the tank is low, and the Blues stack is a proportionately simple solution: a sensor, a Notecard, and a network path that follows the asset wherever it lives. +A Notecarrier CX and Notecard for Skylo — paired with a weatherproof ultrasonic level sensor, a clamp-on current transformer, and a handful of passive components — give a rancher continuous visibility into every stock tank on the property without driving the pasture roads. Notecard for Skylo uses cellular where a tower is reachable and falls back to the Skylo satellite network where terrestrial coverage ends, so tanks in covered valleys and tanks on remote ridges both report through the same firmware and the same Notehub project. Sampling happens locally every 15 minutes with the host MCU asleep between measurements; the radio wakes only for the 4-hour summary or an immediate alert. That duty cycle makes the system comfortable running indefinitely on a modest solar setup, with built-in power-aware sleep extension to handle extended overcast stretches in northern winters. Dry-tank alerts and solar fault alerts reach the rancher's phone before cattle suffer from dehydration; pump current is captured as observational telemetry in every summary and alert payload so operators can correlate it with tank levels after the fact. It's a simple problem — knowing when the tank is low — and the Blues stack is a proportionately simple solution: a sensor, a Notecard, and a network path that follows the asset wherever it lives. diff --git a/66-remote-apiary-hive-health-monitor/README.md b/66-remote-apiary-hive-health-monitor/README.md index 162f2c7a..46eda9a8 100644 --- a/66-remote-apiary-hive-health-monitor/README.md +++ b/66-remote-apiary-hive-health-monitor/README.md @@ -13,9 +13,9 @@ This project is a solar-powered hive monitor that turns each hive into a [remote ## 1. Project Overview -**The problem.** Commercial beekeepers run apiary yards in orchards, fields, and forest edges where there is no electrical infrastructure and no cellular signal worth depending on. A full-sized Langstroth hive in production can weigh 40–80 kg, and the difference between a thriving colony and a dead one, or a hive that has just swarmed and taken 10,000 bees with it — is measured in kilograms, degrees, and the subtle shift in pitch of the colony's acoustic hum. None of those signals are observable from a distance without instrumentation, and traditional hive inspection — opening the box, smoking the bees, physically weighing the stand — takes time, disturbs the colony, and simply can't happen every 15 minutes. The result is that hive collapse, swarm departure, and queen loss are routinely discovered days after the fact, when the economic damage is already done. +**The problem.** Commercial beekeepers run apiary yards in orchards, fields, and forest edges where there is no electrical infrastructure and no cellular signal worth depending on. A full-sized Langstroth hive in production can weigh 40–80 kg, and the signs that separate a thriving colony from a dead one — or from a hive that has just swarmed and taken 10,000 bees with it — are measured in kilograms, degrees, and the subtle shift in pitch of the colony's acoustic hum. None of those signals are observable from a distance without instrumentation, and traditional hive inspection — opening the box, smoking the bees, physically weighing the stand — takes time, disturbs the colony, and simply can't happen every 15 minutes. The result is that hive collapse, swarm departure, and queen loss are routinely discovered days after the fact, when the economic damage is already done. -This project is the remote set of eyes and ears that a beekeeper wants but cannot afford to physically station at every yard. A single weatherproof enclosure mounted on the hive stand reads three independent signals: weight (colony biomass and honey stores), temperature and humidity inside the brood box (brood viability), and acoustic features sampled from an analog microphone inside the hive (behavioral state). Those three signals are processed locally — weight and temperature sampled every 15 minutes, audio captured once per day — aggregated into a daily summary, and pushed to Notehub over cellular where a tower is in reach, and over the [Skylo](https://www.skylo.tech/) satellite network where one isn't — Notecard for Skylo selects the path automatically. The beekeeper gets one notification per day in steady state and an immediate alert when any signal crosses a threshold. +This project is the remote set of eyes and ears that a beekeeper wants but cannot afford to physically station at every yard. A single weatherproof enclosure mounted on the hive stand reads three independent signals: weight (colony biomass and honey stores), temperature and humidity inside the brood box (brood viability), and acoustic features sampled from an analog microphone inside the hive (behavioral state). Those three signals are processed locally — weight and temperature sampled every 15 minutes, audio captured once per day — then aggregated into a daily summary and pushed to Notehub: over cellular where a tower is in reach, and over the [Skylo](https://www.skylo.tech/) satellite network where one isn't. Notecard for Skylo selects the path automatically. The beekeeper gets one notification per day in steady state and an immediate alert when any signal crosses a threshold. @@ -23,7 +23,7 @@ This project is the remote set of eyes and ears that a beekeeper wants but canno -**Why Notecard for Skylo.** Apiaries are deliberately sited away from human infrastructure — the whole point is to place bees near crops, meadows, or forest edges where forage is available and human disturbance is minimal. Those sites have no AC power and often marginal or absent cellular coverage. Every one of those constraints rules out the conventional IoT stack: a gateway-plus-cloud-SIM architecture requires months of site negotiation per yard, and a device that only works in strong cellular signal will fail at exactly the locations where bees are most productive. [Notecard for Skylo](https://shop.blues.com/products/notecard-for-skylo?utm_source=dev-blues&utm_medium=web&utm_campaign=store-link) (NOTE-NBGLWX) carries three radios on one M.2 module — cellular (LTE-M / NB-IoT / GPRS) with its own prepaid global SIM, WiFi, and satellite over the [Skylo](https://www.skylo.tech/) non-terrestrial network (**NTN**) — and selects among them automatically. There is no per-site IT negotiation and no carrier contract, and no second device or part-number decision for the yards that sit in coverage gaps: the firmware sets a single [`card.transport`](https://dev.blues.io/api-reference/notecard-api/card-requests/#card-transport) preference of `wifi-cell-ntn` (prefer WiFi, fall back to cellular, fall back again to Skylo satellite) and the failover is handled inside the Notecard — the host firmware never branches on which network is live. Skylo's geostationary (GEO) network provides good coverage across open-sky terrain, which is exactly what a hive stand in an open orchard or meadow provides. **Skylo coverage is geography- and service-region-dependent; verify current coverage for your deployment region and review the [satellite best practices guide](https://dev.blues.io/starnote/satellite-best-practices/) before relying on satellite as the sole backhaul.** The combination of low-power cellular with automatic satellite fallover is not a belt-and-suspenders add-on here; it is the architecture that makes this deployable in the real operating environment of commercial apiculture. +**Why Notecard for Skylo.** Apiaries are deliberately sited away from human infrastructure — the whole point is to place bees near crops, meadows, or forest edges where forage is available and human disturbance is minimal. Those sites have no AC power and often marginal or absent cellular coverage. Every one of those constraints rules out the conventional IoT stack: a gateway-plus-cloud-SIM architecture requires months of site negotiation per yard, and a device that only works in strong cellular signal will fail at exactly the locations where bees are most productive. [Notecard for Skylo](https://shop.blues.com/products/notecard-for-skylo?utm_source=dev-blues&utm_medium=web&utm_campaign=store-link) (NOTE-NBGLWX) carries three radios on one M.2 module — cellular (LTE-M / NB-IoT / GPRS) with its own prepaid global SIM, WiFi, and satellite over the [Skylo](https://www.skylo.tech/) non-terrestrial network (**NTN**) — and selects among them automatically. There is no per-site IT negotiation and no carrier contract, and no second device or part-number decision for the yards that sit in coverage gaps: the firmware sets a single [`card.transport`](https://dev.blues.io/api-reference/notecard-api/card-requests/#card-transport) preference of `wifi-cell-ntn` (prefer WiFi, fall back to cellular, fall back again to Skylo satellite) and the failover is handled inside the Notecard — the host firmware never branches on which network is live. Skylo's geostationary (GEO) network provides good coverage across open-sky terrain, which is exactly what a hive stand in an open orchard or meadow provides. **Skylo coverage is geography- and service-region-dependent; verify current coverage for your deployment region and review the [satellite best practices guide](https://dev.blues.io/starnote/satellite-best-practices/) before relying on satellite as the sole backhaul.** The combination of low-power cellular with automatic satellite failover is not a belt-and-suspenders add-on here; it is the architecture that makes this deployable in the real operating environment of commercial apiculture. @@ -204,7 +204,7 @@ Because the satellite link uses the same `MAIN` antenna as cellular, the placeme 4. **Set environment variables.** In Notehub, navigate **Fleet → Environment** and set any values below (all are optional; firmware defaults are shown in the table). Any value set at fleet or device level overrides the compile-time default on the device's next inbound sync. Use [Smart Fleets](https://dev.blues.io/notehub/notehub-walkthrough/#using-smart-fleet-rules) to automate fleet assignment based on device metadata. - > **Commissioning Note — inbound cadence.** The firmware configures `inbound: 10080` (one week) to minimise satellite session costs. This means env var changes pushed from Notehub will not be pulled by the device until the next scheduled inbound, which may be up to seven days away. During bench commissioning, **force an immediate inbound sync** after each env var change by sending `{"req":"hub.sync"}` from the **blues.dev In-Browser Terminal** (upper right of the Notehub console). Alternatively, temporarily shorten the inbound interval for the bench session by sending `{"req":"hub.set","mode":"periodic","outbound":1440,"inbound":15}` from the terminal, and restore the weekly inbound (`"inbound":10080`) before field deployment. + > **Commissioning Note — inbound cadence.** The firmware configures `inbound: 10080` (one week) to minimize satellite session costs. This means env var changes pushed from Notehub will not be pulled by the device until the next scheduled inbound, which may be up to seven days away. During bench commissioning, **force an immediate inbound sync** after each env var change by sending `{"req":"hub.sync"}` from the **blues.dev In-Browser Terminal** (upper right of the Notehub console). Alternatively, temporarily shorten the inbound interval for the bench session by sending `{"req":"hub.set","mode":"periodic","outbound":1440,"inbound":15}` from the terminal, and restore the weekly inbound (`"inbound":10080`) before field deployment. | Variable | Default | Purpose | |---|---|---| @@ -258,7 +258,7 @@ To open in Arduino IDE: **File → Open** and navigate to `firmware/apiary_hive_ **Temperature and humidity.** A single SHT31-D measurement takes roughly 15 milliseconds; the library manages the I2C transaction and CRC check internally. Values are accumulated into running sums for the daily average; if the I2C read fails (returns NaN), the sample is excluded from the sum so a wired-off sensor does not bias the average to zero. -**Audio feature extraction.** Audio is captured **once per summary window** (by default, once per day). The firmware checks the `audio_sampled` flag after evaluating window expiry, not before. On a successful rollover the flag is cleared before the audio check fires, so audio is captured on the rollover wake itself, making that wake the true first wake of the new window for all three sensor paths. On all subsequent wakes of the same window `audio_sampled` is set and the microphone is not re-sampled. On a failed rollover (`sendSummary()` returned false), `audio_sampled` is still true from the previous window and the block is skipped — consistent with the frozen-snapshot retry behaviour for weight and temperature. +**Audio feature extraction.** Audio is captured **once per summary window** (by default, once per day). The firmware checks the `audio_sampled` flag after evaluating window expiry, not before. On a successful rollover the flag is cleared before the audio check fires, so audio is captured on the rollover wake itself, making that wake the true first wake of the new window for all three sensor paths. On all subsequent wakes of the same window `audio_sampled` is set and the microphone is not re-sampled. On a failed rollover (`sendSummary()` returned false), `audio_sampled` is still true from the previous window and the block is skipped — consistent with the frozen-snapshot retry behavior for weight and temperature. When audio is attempted, `readAudioFeatures()` runs 12 consecutive 256-sample windows on A0 at approximately 4 kHz (`AUDIO_SAMPLE_PERIOD_US = 225 µs`), giving a ~0.75-second snippet total. Features are computed without storing the full audio buffer — which would require 32 KB at 16-bit resolution, a meaningful fraction of the Cygnet's 64 KB SRAM. `readAudioFeatures()` returns a validity flag: if the signal is implausible (DC offset outside the expected mid-rail band indicating a floating or disconnected A0, more than 30 % of samples within 32 LSB of the ADC rail indicating clipping, or normalized RMS below a minimum threshold indicating a dead or shorted microphone), the read is rejected. On an invalid read, `audio_anomaly` is not evaluated, `audio_sampled` is still set to prevent per-wake retries, and `zcr_avg`, `rms_avg`, and `peak_avg` emit `−9999` — the same sentinel convention used for weight timeouts and temperature NaN reads. Only the three computed features are stored or transmitted; no raw audio is recorded. @@ -353,7 +353,7 @@ notecard.sendRequest(req); Each 256-sample window is processed in two passes so that the per-window DC operating point is computed from the actual samples rather than assumed to be the ADC midpoint (2048). The MAX9814's AGC shifts the quiescent DC level across installations; measuring it directly makes the ZCR threshold portable without per-board recalibration. ZCR is also derived from the measured wall-clock window duration (`t1 − t0`) rather than a nominal sample rate, so it is accurate regardless of MCU speed or `analogRead()` latency. ```cpp -analogReadResolution(12); // 0–4095 range; 2048 is the normalisation half-range +analogReadResolution(12); // 0–4095 range; 2048 is the normalization half-range // Pass 1: collect raw samples and sum for DC mean; bracket with micros() for // accurate ZCR (counts/second derived from actual elapsed time, not nominal rate) @@ -378,7 +378,7 @@ int32_t prev = (int32_t)samples[0] - dc_offset; for (int i = 1; i < AUDIO_WINDOW_SAMPLES; i++) { int32_t cur = (int32_t)samples[i] - dc_offset; if ((prev < 0 && cur >= 0) || (prev >= 0 && cur < 0)) crossings++; - float norm = (float)cur / 2048.0f; // normalise to [-1, 1] + float norm = (float)cur / 2048.0f; // normalize to [-1, 1] sum_sq += norm * norm; if (norm < 0.0f) norm = -norm; if (norm > peak_abs) peak_abs = norm; @@ -439,7 +439,7 @@ delay((uint32_t)sampleMin * 60000UL); 1. **Scale-factor calibration.** - a. **Shorten the window.** In Notehub, set `report_interval_hr` to `1`. Force an immediate inbound sync by sending `{"req":"hub.sync"}` from the blues.dev In-Browser Terminal (see §6 step 4, without this, the weekly `inbound: 10080` setting means the env var may not arrive for up to seven days). Wait for the Notecard to confirm the sync; the new interval takes effect on the next wake after the env var is applied. + a. **Shorten the window.** In Notehub, set `report_interval_hr` to `1`. Force an immediate inbound sync by sending `{"req":"hub.sync"}` from the blues.dev In-Browser Terminal (see §6 step 4; without this, the weekly `inbound: 10080` setting means the env var may not arrive for up to seven days). Wait for the Notecard to confirm the sync; the new interval takes effect on the next wake after the env var is applied. b. **Clear any partial window in progress.** The firmware restores persisted state across reboots via `NotePayloadRetrieveAfterSleep`, so a power-cycle alone does not reset the summary window. To start from a known-clean boundary: in Notehub set `reset_state` to `1` (see §6) and force an immediate inbound sync (`{"req":"hub.sync"}`). On the next wake the firmware clears all accumulators and sets `last_report_epoch = 0`; the window is re-anchored when the next valid `card.time` response arrives. The reset is one-shot — subsequent wakes that still read `reset_state=1` (before the next inbound sync delivers the updated value) are silently skipped by the firmware. After confirming that the first 1-hour summary has been received (indicating that a complete clean window elapsed), you may leave `reset_state=1` in Notehub or remove it; the window will not reset again. From f5d1c3e057be424b14cbdde603ac976f7fead9cf Mon Sep 17 00:00:00 2001 From: Rob Lauer Date: Fri, 12 Jun 2026 15:02:58 -0500 Subject: [PATCH 2/2] claude review --- 52-vfd-pump-predictive-maintenance/README.md | 6 +- .../README.md | 4 +- .../README.md | 6 +- .../README.md | 6 +- .../README.md | 8 +-- 57-propane-lpg-tank-fill-telemetry/README.md | 56 +++++++++---------- .../README.md | 2 +- .../README.md | 2 +- .../README.md | 2 +- .../README.md | 24 ++++---- .../README.md | 36 ++++++------ 11 files changed, 76 insertions(+), 76 deletions(-) diff --git a/52-vfd-pump-predictive-maintenance/README.md b/52-vfd-pump-predictive-maintenance/README.md index d213f0f6..e3a11d56 100644 --- a/52-vfd-pump-predictive-maintenance/README.md +++ b/52-vfd-pump-predictive-maintenance/README.md @@ -12,7 +12,7 @@ This project is a [downtime prevention](https://blues.com/downtime-prevention/) ## 1. Project Overview -**The problem.** Industrial centrifugal pumps almost universally run behind a VFD. Modern drives from ABB, Yaskawa, Danfoss, and Schneider all expose the pump's operating telemetry through Modbus holding registers — motor current, output frequency, output torque, drive temperature, runtime hours, active fault code, and almost nobody reads them. The VFD is sitting in the cabinet doing the work; the data is right there. What's missing is the network path off the plant floor. +**The problem.** Industrial centrifugal pumps almost universally run behind a VFD. Modern drives from ABB, Yaskawa, Danfoss, and Schneider all expose the pump's operating telemetry through Modbus holding registers — motor current, output frequency, output torque, drive temperature, runtime hours, active fault code. Almost nobody reads them. The VFD is sitting in the cabinet doing the work; the data is right there. What's missing is the network path off the plant floor. A failing pump rarely just stops. It signals first: motor current can shift at constant frequency as bearing drag, fouling, valve position, fluid viscosity, or impeller condition change the load on the drive. Transient electrical faults can cluster on a stressed contactor or in a cavitating hydraulic regime. Actual runtime can drift above expected duty cycle as a downstream valve fouls and the pump runs longer to do the same work. *None of these telemetry shifts are diagnostic by themselves*, but they are leading indicators a maintenance team would happily act on a week early. This project is the device that catches those anomalies and routes them out, before a tank runs dry on a Saturday night. See the [Signal limitations](#12-limitations-and-next-steps) note for what this telemetry can and cannot conclude. @@ -165,7 +165,7 @@ Dependencies: Six holding registers are pulled in a single Modbus transaction (`requestFrom` with `HOLDING_REGISTERS`, quantity 6, starting address taken from `reg_freq`). Reading all six in one transaction is roughly 8× cheaper in time and bus utilization than six individual reads. The firmware assumes the six registers are contiguous; on drives where they aren't, override `reg_*` variables individually and the firmware falls back to per-register reads. -Polling cadence is `sample_minutes` (default 1 minutes). For each sample, `accumulate` updates the rolling hourly windows for current, frequency, torque, and drive temperature — separately tracking samples taken while the pump is *running* (frequency > 1 Hz) versus *stopped*, since a hot drive at 0 Hz is a different signal than a hot drive under load. +Polling cadence is `sample_minutes` (default 1 minute). For each sample, `accumulate` updates the rolling hourly windows for current, frequency, torque, and drive temperature — separately tracking samples taken while the pump is *running* (frequency > 1 Hz) versus *stopped*, since a hot drive at 0 Hz is a different signal than a hot drive under load. ### Event payload design @@ -226,7 +226,7 @@ The OPTA + expansion is line-powered (24 VDC), so MCU sleep is not the goal — ### Retry and error handling - The first `hub.set` uses `notecard.sendRequestWithRetry()` with a 5-second window — there is a known cold-boot race condition where the host comes up before the Notecard is ready to receive I²C transactions. -- Modbus reads are retried up to 3× per cycle on `lastError() != 0`. If all three fail, the firmware skips that sample (no NaN ever appears in any payload, JSON has no valid `NaN` literal and templated Notes validate field types) and emits a separate `modbus_unreachable` event Note. The event is rate-limited to once per hour to avoid alarm fatigue when the drive itself is powered off for service. +- Modbus reads are retried up to 3× per cycle on `lastError() != 0`. If all three fail, the firmware skips that sample (no NaN ever appears in any payload: JSON has no valid `NaN` literal, and templated Notes validate field types) and emits a separate `modbus_unreachable` event Note. The event is rate-limited to once per hour to avoid alarm fatigue when the drive itself is powered off for service. - Notecard requests use `notecard.requestAndResponse()` and check both `NULL` return and the `err` field on the response object before trusting the data. ### Key code snippets diff --git a/53-municipal-wastewater-lift-station-monitor/README.md b/53-municipal-wastewater-lift-station-monitor/README.md index 53613f3f..523d2f85 100644 --- a/53-municipal-wastewater-lift-station-monitor/README.md +++ b/53-municipal-wastewater-lift-station-monitor/README.md @@ -14,11 +14,11 @@ This project is a [downtime prevention](https://blues.com/downtime-prevention/) **The problem.** A **lift station** (also called a pump station) is a below-grade concrete vault or roadside cabinet that collects raw sewage from the surrounding gravity sewer system and pumps it uphill toward the treatment plant. Every municipality has dozens of them, often scattered across low-lying neighborhoods, industrial zones, and rural road shoulders — most with no onsite staff and no way to know what's happening inside until a citizen calls to report a smell or, worse, a spill. -When a lift station fails, the **wet well** — the collection basin that feeds the pumps — fills up and overflows. The result is a **SSO**: a sanitary sewer overflow. SSOs draw immediate regulatory attention; they trigger EPA reporting obligations, risk consent decree violations, and require expensive emergency cleanups. A station that fails on a Friday evening and isn't discovered until Monday morning is a public health event, a PR crisis, and a significant unplanned expense all at once. The failure modes are rarely dramatic: a pump fails to start because its float control sticks, a discharge check valve fails and allows backflow that clogged the impeller, or a wet-well float switch trips but no one receives the alarm because the SCADA dial-up modem lost its phone line. Each of these is detectable minutes after it starts — if someone is watching. +When a lift station fails, the **wet well** — the collection basin that feeds the pumps — fills up and overflows. The result is an **SSO**: a sanitary sewer overflow. SSOs draw immediate regulatory attention; they trigger EPA reporting obligations, risk consent decree violations, and require expensive emergency cleanups. A station that fails on a Friday evening and isn't discovered until Monday morning is a public health event, a PR crisis, and a significant unplanned expense all at once. The failure modes are rarely dramatic: a pump fails to start because its float control sticks, a discharge check valve fails and allows backflow that clogs the impeller, or a wet-well float switch trips but no one receives the alarm because the SCADA dial-up modem lost its phone line. Each of these is detectable minutes after it starts — if someone is watching. This project is that watcher. It straps to the inside of the station, samples the wet-well level every 60 seconds, measures current draw on each pump, and monitors the high-water float switch — four sensing points across three sensor types. Onboard edge logic on the STM32-based host MCU evaluates three fault rules every 60 seconds and routes alerts to the [Blues Notehub](https://blues.com/notehub/) cloud service the instant any rule trips — over cellular where a tower is in reach, and over the Skylo satellite network where one isn't. The on-call crew gets paged before the wet well overflows, not after. -**Why Notecard for Skylo.** The wireless-first architecture here isn't a convenience — it's a necessity. Lift stations sit in concrete vaults underground, often with no AC power outlet in the vault itself (power runs to the pump control panel, not a wall socket). They're geographically distributed across a municipality in a pattern that matches the sewer network, not the municipal network — there's no fiber running to a roadside pump cabinet, and there's no corporate WiFi AP that can reach through a concrete lid to a sensor inside. Utility supervisors would need to deploy and maintain a WiFi access point at every single station to achieve what one Notecard covers automatically. +**Why Notecard for Skylo.** The wireless-first architecture here isn't a convenience — it's a necessity. Lift stations sit in concrete vaults underground, often with no AC power outlet in the vault itself (power runs to the pump control panel, not a wall socket). They're geographically distributed across a municipality in a pattern that matches the sewer network, not the municipal network: there's no fiber running to a roadside pump cabinet, and there's no corporate WiFi AP that can reach through a concrete lid to a sensor inside. Utility supervisors would need to deploy and maintain a WiFi access point at every single station to achieve what one Notecard covers automatically. [Notecard for Skylo](https://shop.blues.com/products/notecard-for-skylo?utm_source=dev-blues&utm_medium=web&utm_campaign=store-link) (NOTE-NBGLWX) carries three radios on one M.2 module — cellular (LTE-M / NB-IoT / GPRS), WiFi, and satellite over the [Skylo](https://www.skylo.tech/) non-terrestrial network (NTN) — and selects among them automatically. The firmware sets a single [`card.transport`](https://dev.blues.io/api-reference/notecard-api/card-requests/#card-transport) preference of `wifi-cell-ntn`: prefer WiFi where an accessible AP happens to be in range (rare for a sealed vault), fall back to cellular (the de-facto primary at the vast majority of municipal infrastructure), and fall back again to Skylo satellite at stations on the fringe of the service territory, beyond the reach of any cellular carrier. Failover is handled inside the Notecard; the host firmware never branches on which network is live. That collapses what used to be a two-SKU decision — a cellular Notecard for in-coverage stations, a satellite device for the rest — into a single part number, a single antenna kit, and a single firmware image that deploys unchanged across the entire fleet. There is nothing to swap when a station turns out to have weaker coverage than the survey suggested: the same board that runs on cellular downtown automatically reaches the Skylo network at the rural lift station. diff --git a/54-multi-site-walk-in-cooler-energy-setpoint-monitor/README.md b/54-multi-site-walk-in-cooler-energy-setpoint-monitor/README.md index 6eea23f7..e232ee53 100644 --- a/54-multi-site-walk-in-cooler-energy-setpoint-monitor/README.md +++ b/54-multi-site-walk-in-cooler-energy-setpoint-monitor/README.md @@ -8,7 +8,7 @@ This reference application is intended to provide inspiration and help you get s -This project is a cellular [energy savings](https://blues.com/energy-savings/) reference design that gives corporate operations teams a live view into the temperature, compressor runtime, and door behavior of every walk-in cooler in their fleet — without touching a single franchisee or operator's WiFi network. +This project is a cellular [energy savings](https://blues.com/energy-savings/) reference design that gives corporate operations teams a live view into the temperature, compressor runtime, and door behavior of every walk-in cooler in their fleet, without touching a single franchisee or operator's WiFi network. ## 1. Project Overview @@ -154,7 +154,7 @@ Pin-by-pin connections: - **SDA / SCL** → Notecard I²C (Notecarrier CX routes these to the M.2 slot internally; no external wiring needed). - **+VBAT** → Mojo `LOAD` output (bench use only); Mojo `BAT` input ← 5V DC output of the MeanWell IRM-10-5 (or equivalent 5V/2A AC/DC supply), which is wired to the AC service conductors in the NEMA 4X enclosure. -**CT installation Note.** The SCT-013-030 is a split-core clamp; open the clamp, pass it over *one* hot leg of the compressor's circuit (not both, clamping both legs cancels the magnetic fields and you'll read zero). Route the TRRS lead back to the NEMA 4X enclosure through a cable gland. The compressor circuit is line-voltage; installation must be performed by a qualified electrician following applicable codes and lockout/tagout procedures. The CT itself is entirely non-contact and electrically isolated once clamped. +**CT installation Note.** The SCT-013-030 is a split-core clamp; open the clamp, pass it over *one* hot leg of the compressor's circuit (not both; clamping both legs cancels the magnetic fields and you'll read zero). Route the TRRS lead back to the NEMA 4X enclosure through a cable gland. The compressor circuit is line-voltage; installation must be performed by a qualified electrician following applicable codes and lockout/tagout procedures. The CT itself is entirely non-contact and electrically isolated once clamped. **DS18B20 placement.** For accurate air temperature monitoring, position the stainless probe tip in open box air at mid-box height or along the return-air path, away from both the evaporator fan discharge and the door. This location gives the most representative reading of box air temperature, which is a useful proxy for stored-product conditions but is not a direct product core-temperature measurement. Avoid the evaporator fan discharge — it is the coldest zone in the box and reads several degrees below true representative air temperature; placing the probe there biases temperature-to-target deviation calculations low and will delay `temp_high` alerts. Avoid the door zone, which sees warm infiltration air on every open cycle. Keep the probe away from direct coil contact for the same reason. @@ -425,4 +425,4 @@ Once the basic fleet visibility is established, the following extensions are the ## 12. Summary -The corporate energy team that used to stall at the 50-store pilot now has a fleet-wide view: compressor apparent kWh per window, door-open seconds, temperature drift against a setpoint they configure from a browser. One cellular SKU, three sensors, and a field tech who never has to ask anyone for a WiFi password — and the outlier box running double the compressor-hours of its peers shows up on a dashboard instead of in next month's utility bill. +The corporate energy team that used to stall at the 50-store pilot now has a fleet-wide view: compressor apparent kWh per window, door-open seconds, temperature drift against a setpoint they configure from a browser. One cellular SKU, three sensors, and a field tech who never has to ask anyone for a WiFi password. And the outlier box running double the compressor-hours of its peers shows up on a dashboard instead of in next month's utility bill. diff --git a/55-demand-response-solar-battery-dispatcher/README.md b/55-demand-response-solar-battery-dispatcher/README.md index cdb4723b..74da7301 100644 --- a/55-demand-response-solar-battery-dispatcher/README.md +++ b/55-demand-response-solar-battery-dispatcher/README.md @@ -8,7 +8,7 @@ This reference application is intended to provide inspiration and help you get s -This project is an [energy savings](https://blues.com/energy-savings/) reference design that gives a commercial solar + battery installation an independent cellular control channel, so the asset owner can dispatch the battery to discharge during expensive peak-rate hours, charge during cheap overnight hours, and curtail grid export when the utility calls a demand-response (DR) event, without depending on the building's IT network or a vendor's proprietary cloud portal. The device reads live operating state from the inverter and the battery's management system (BMS) over the industrial bus they already share, and signals each one to enter the right mode at the right time — driven by a schedule or by live commands routed through the the [Blues Notehub](https://blues.com/notehub/) cloud service. +This project is an [energy savings](https://blues.com/energy-savings/) reference design that gives a commercial solar + battery installation an independent cellular control channel, so the asset owner can dispatch the battery to discharge during expensive peak-rate hours, charge during cheap overnight hours, and curtail grid export when the utility calls a demand-response (DR) event, without depending on the building's IT network or a vendor's proprietary cloud portal. The device reads live operating state from the inverter and the battery's management system (BMS) over the industrial bus they already share, and signals each one to enter the right mode at the right time, driven by a schedule or by live commands routed through the [Blues Notehub](https://blues.com/notehub/) cloud service. **Scope.** This is a *mode enable / curtail* controller, not a power dispatcher. It closes and opens four dry-contact relays wired to digital control inputs the inverter and battery already expose; the field devices' own firmware then decides the actual charge, discharge, and export behavior — ramp rates, power limits, setpoints — based on their pre-commissioning configuration. The controller does not command power setpoints, verify that a requested dispatch profile was executed, or close any control loop around site load. @@ -16,7 +16,7 @@ This project is an [energy savings](https://blues.com/energy-savings/) reference **The problem.** Commercial solar-plus-storage systems are a compelling economics story on paper: sell excess solar generation at peak rates, cover load from the battery so you don't draw from the grid during expensive peak windows, and participate in utility DR programs that pay you to curtail export or reduce load on short notice. The value is real, but realizing it requires a reliable, low-latency control channel between the utility signal and the physical system sitting on the roof or in the equipment yard. -That's where most deployments hit the wall. The inverter and BMS speak Modbus — an industrial serial protocol developed in 1979 that remains the lingua franca of commercial power electronics, and that bus sits in an outdoor equipment cabinet or a rooftop shed with no direct connection to the building's IT network. Even when WiFi does reach the equipment, the solar asset is often owned by a third-party power purchase agreement provider who has no credentials on the building's network and no relationship with the building's IT team. The control channel that does exist — the inverter's local display, a proprietary cloud portal, or a laptop plugged in at the cabinet — isn't a control channel you can reliably automate, audit, or integrate with a utility DR program. +That's where most deployments hit the wall. The inverter and BMS speak Modbus, an industrial serial protocol developed in 1979 that remains the lingua franca of commercial power electronics. That bus sits in an outdoor equipment cabinet or a rooftop shed with no direct connection to the building's IT network. Even when WiFi does reach the equipment, the solar asset is often owned by a third-party power purchase agreement provider who has no credentials on the building's network and no relationship with the building's IT team. The control channel that does exist — the inverter's local display, a proprietary cloud portal, or a laptop plugged in at the cabinet — isn't a control channel you can reliably automate, audit, or integrate with a utility DR program. This project closes that gap. A [Blues Wireless for OPTA](https://blues.com/products/wireless-for-opta/) expansion snapped onto an Arduino OPTA RS485 PLC (programmable logic controller) sits on the DIN rail inside the equipment cabinet. The OPTA reads the inverter and BMS over the RS-485 Modbus bus already present in every commercial solar installation, while the Notecard inside the Blues expansion provides a cellular uplink that is completely independent of the building network and requires no IT coordination. When the utility issues a DR event, or when the local time-of-use peak window opens, the cloud-side system routes a dispatch command to the device through Notehub. The OPTA closes or opens four relay outputs: grid export enable, battery discharge, battery charge, and a DR-active indicator, typically within one to six minutes of the command arriving at Notehub (bounded by the 5-minute inbound sync cadence plus the next 1-minute sample cycle), then reports what it did and why. @@ -28,7 +28,7 @@ This project closes that gap. A [Blues Wireless for OPTA](https://blues.com/prod -**⚠ Commissioning safety — TOU windows are disabled by default.** Both the peak window (`peak_start_utc` / `peak_end_utc`) and the off-peak charge window (`charge_start_utc` / `charge_end_utc`) ship with start and end hours equal (both `0`), which disables autonomous TOU dispatch. The controller stays in `normal` mode until an operator explicitly configures non-equal window hours in the Notehub fleet environment variables. **Enable and tune the TOU windows only after confirming wiring, Modbus addressing, and SOC thresholds are correct for the site.** Cloud `dispatch.qi` commands are honoured immediately regardless of TOU configuration. See [Section 5](#6-notehub-setup) for the full environment variable reference. +**⚠ Commissioning safety — TOU windows are disabled by default.** Both the peak window (`peak_start_utc` / `peak_end_utc`) and the off-peak charge window (`charge_start_utc` / `charge_end_utc`) ship with start and end hours equal (both `0`), which disables autonomous TOU dispatch. The controller stays in `normal` mode until an operator explicitly configures non-equal window hours in the Notehub fleet environment variables. **Enable and tune the TOU windows only after confirming wiring, Modbus addressing, and SOC thresholds are correct for the site.** Cloud `dispatch.qi` commands are honored immediately regardless of TOU configuration. See [Section 5](#6-notehub-setup) for the full environment variable reference. diff --git a/56-commercial-plug-load-after-hours-waste-dashboard/README.md b/56-commercial-plug-load-after-hours-waste-dashboard/README.md index 64828159..4d66fa92 100644 --- a/56-commercial-plug-load-after-hours-waste-dashboard/README.md +++ b/56-commercial-plug-load-after-hours-waste-dashboard/README.md @@ -8,7 +8,7 @@ This reference application is intended to provide inspiration and help you get s -This project is a cellular-connected [energy savings](https://blues.com/energy-savings/) monitor that clips non-invasive CT (current transformer) clamps onto branch circuits in a commercial sub-panel, samples RMS current once a minute, and transmits hourly per-circuit profiles to the [Blues Notehub](https://blues.com/notehub/) cloud service — giving energy consultants a view into which circuits are burning money at 2 AM, without ever touching the building's corporate network. +This project is a cellular-connected [energy savings](https://blues.com/energy-savings/) monitor that clips non-invasive CT (current transformer) clamps onto branch circuits in a commercial sub-panel, samples RMS current once a minute, and transmits hourly per-circuit profiles to the [Blues Notehub](https://blues.com/notehub/) cloud service, giving energy consultants a view into which circuits are burning money at 2 AM without ever touching the building's corporate network. ## 1. Project Overview @@ -23,7 +23,7 @@ An **ESCO** (Energy Service Company) or independent energy consultant is usually The Notecard Cell+WiFi variant also retains WiFi as a fallback, so a site that does offer accessible WiFi can use it — without compromising the cellular-first deployment model for sites that don't. -**Deployment scenario.** A small weatherproof enclosure mounted inside or adjacent to the target sub-panel. CT clamps clip around individual branch-circuit hot wires at the sub-panel — no wire cutting, no circuit interruption. The enclosure draws 5V DC from a compact AC/DC supply tapped at the panel feed. All panel work, including placing CT clamps inside the panel enclosure and landing the AC/DC supply on panel power — must be performed by a qualified person following site lockout/tagout procedures and applicable electrical codes. Once the enclosure is powered and in place, the CT clamps themselves clip on and off the circuit conductors without any further contact with live conductors, but the initial installation is not a DIY task. A typical engagement deploys one unit per sub-panel, leaving it in place for two to four weeks to capture enough time-of-day variation for the cloud classifier to build a reliable load profile per circuit. +**Deployment scenario.** A small weatherproof enclosure mounted inside or adjacent to the target sub-panel. CT clamps clip around individual branch-circuit hot wires at the sub-panel — no wire cutting, no circuit interruption. The enclosure draws 5V DC from a compact AC/DC supply tapped at the panel feed. All panel work — including placing CT clamps inside the panel enclosure and landing the AC/DC supply on panel power — must be performed by a qualified person following site lockout/tagout procedures and applicable electrical codes. Once the enclosure is powered and in place, the CT clamps themselves clip on and off the circuit conductors without any further contact with live conductors, but the initial installation is not a DIY task. A typical engagement deploys one unit per sub-panel, leaving it in place for two to four weeks to capture enough time-of-day variation for the cloud classifier to build a reliable load profile per circuit. ## 2. System Architecture @@ -101,11 +101,11 @@ Here is a sample Note this device emits: | [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 STM32L433 host — no separate MCU required. Exposes six analog inputs (A0–A5) on its dual 16-pin headers, four of which are used for CT channels. | | [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-first connectivity removes any dependency on site WiFi or LAN. The onboard WiFi radio is available as an opportunistic fallback. Ships with an active global SIM including 500 MB and 10 years of service. | | External cellular antenna, SMA, ~1 m lead (e.g. [SparkFun CEL-16432](https://www.sparkfun.com/lte-hinged-external-antenna-698mhz-2-7ghz-sma-male.html)) | 1 | Required whenever the enclosure is mounted inside or adjacent to a metal sub-panel. A chip or flexible antenna left inside metalwork will not sustain reliable cellular connectivity. The SMA connector threads onto a bulkhead fitting threaded through a cable gland so the antenna element sits outside the metal. | -| u.FL to SMA-female bulkhead pigtail, ~10–15 cm | 1 | Routes the Notecard's `MAIN` u.FL cellular port to the SMA bulkhead fitting on the enclosure wall. Keep as short as practical to minimise cable loss. | +| u.FL to SMA-female bulkhead pigtail, ~10–15 cm | 1 | Routes the Notecard's `MAIN` u.FL cellular port to the SMA bulkhead fitting on the enclosure wall. Keep as short as practical to minimize cable loss. | | [Blues Mojo](https://shop.blues.com/products/mojo?utm_source=dev-blues&utm_medium=web&utm_campaign=store-link) | 1 | Coulomb counter for bench-level power validation; confirms the sleep/wake pattern is behaving as designed before field deployment. | | SCT-013-030 split-core CT, 30 A / 1 V (e.g. [SparkFun SEN-11005](https://www.sparkfun.com/products/11005)) | 4 | Non-invasive clamp-on current sensing — clips around the hot wire without breaking the circuit. The `-030` (1 V) variant has an internal burden resistor, so no external burden components are needed. 30 A rating covers standard 15 A and 20 A branch circuits with headroom; the `ct_full_scale_amps` env var re-scales if a different CT model is used. | | TRRS 3.5 mm breakout (e.g. [SparkFun BOB-11570](https://www.sparkfun.com/products/11570)) | 4 | The SCT-013-030 output cable terminates in a 3.5 mm TRRS plug. One breakout per CT brings the tip (signal) and sleeve (return) to screw-terminal connections. | -| 10 kΩ 1% resistor (bias divider) | 2 | A two-resistor voltage divider between +3V3 and GND creates the shared bias mid-point (≈1.65 V) that all four CT channels reference. Deriving the bias from on-board 3.3 V keeps the signal centred in the ADC input range. | +| 10 kΩ 1% resistor (bias divider) | 2 | A two-resistor voltage divider between +3V3 and GND creates the shared bias mid-point (≈1.65 V) that all four CT channels reference. Deriving the bias from on-board 3.3 V keeps the signal centered in the ADC input range. | | 10 µF electrolytic capacitor | 1 | Decoupling on the shared bias node; suppresses divider noise that would otherwise add a low-frequency artifact to every RMS measurement. | | AC/DC supply, 5 V / 2 A (e.g. [MeanWell IRM-10-5](https://www.meanwell.com/Upload/PDF/IRM-10/IRM-10-SPEC.PDF)) | 1 | Derives 5 V DC from the 120 VAC panel feed for permanent, grid-tied power. A 2 A (10 W) rating is appropriate for a cellular design: the MBGLW's LTE Cat-1 bis modem (Quectel EG915 family) draws ~250 mA average during a session, and modem attach plus brief 2G/GSM-fallback transmit bursts in marginal-coverage areas can pull current well above that average from the 5 V rail during radio warm-up. An undersized supply that cannot source those peaks risks a brownout that aborts the cellular session. The IRM-10-5's 10 W output provides adequate headroom for the Notecard's peak draw, the host MCU active phase, and installation-environment margin. | | NEMA 4X enclosure, ~6×4×2″ | 1 | Encloses the electronics near the sub-panel; NEMA 4X rating handles the occasional humidity and spray found in mechanical rooms and utility corridors. | diff --git a/57-propane-lpg-tank-fill-telemetry/README.md b/57-propane-lpg-tank-fill-telemetry/README.md index 4897fac7..2f6c45c9 100644 --- a/57-propane-lpg-tank-fill-telemetry/README.md +++ b/57-propane-lpg-tank-fill-telemetry/README.md @@ -8,31 +8,31 @@ This reference application is intended to provide inspiration and help you get s -This project is a [truck roll reduction](https://blues.com/truck-roll-reduction/) reference design that gives propane dealers per-tank fill telemetry across their entire delivery territory — replacing fixed-schedule routes with demand-driven dispatch and projecting days-until-empty for every tank in the fleet. A level sensor at the tank's existing gauge port and a temperature probe on the tank shell turn each tank into a self-reporting asset; a single [Notecard for Skylo](https://shop.blues.com/products/notecard-for-skylo?utm_source=dev-blues&utm_medium=web&utm_campaign=store-link) (one module carrying cellular, WiFi, and Skylo satellite radios that fails over between them automatically) carries the data from the tank three minutes outside town just as readily as from the remote mountain cabin beyond any cell tower. One SKU and one firmware image cover every site type in the territory. +This project is a [truck roll reduction](https://blues.com/truck-roll-reduction/) reference design that gives propane dealers per-tank fill telemetry across their entire delivery territory, replacing fixed-schedule routes with demand-driven dispatch and projecting days-until-empty for every tank in the fleet. A level sensor at the tank's existing gauge port and a temperature probe on the tank shell turn each tank into a self-reporting asset; a single [Notecard for Skylo](https://shop.blues.com/products/notecard-for-skylo?utm_source=dev-blues&utm_medium=web&utm_campaign=store-link) (one module carrying cellular, WiFi, and Skylo satellite radios that fails over between them automatically) carries the data from the tank three minutes outside town just as readily as from the remote mountain cabin beyond any cell tower. One SKU and one firmware image cover every site type in the territory. ## 1. Project Overview -**The problem.** Most propane dealers still run their delivery routes on a fixed calendar: every six weeks, every tank gets a truck. That schedule exists not because it matches demand, but because dealers have no way to know which tanks actually need filling. The result is trucks rolling to tanks that are at 60% and tanks at remote farm properties that run dry between scheduled visits. Neither failure is exotic — they're structural consequences of not having fill-level data. +**The problem.** Most propane dealers still run their delivery routes on a fixed calendar: every six weeks, every tank gets a truck. That schedule exists not because it matches demand, but because dealers have no way to know which tanks actually need filling. The result is trucks rolling to tanks that are at 60% and tanks at remote farm properties that run dry between scheduled visits. Neither failure is exotic; they're structural consequences of not having fill-level data. -The root cause is infrastructure. A propane tank sits in a field, on a farm, at a cabin, at a rural business — almost never near a WiFi access point the dealer can use, and often in areas where cellular is marginal to nonexistent. The tank itself is a sealed pressure vessel with no native communication capability. Retrofitting telemetry means solving a connectivity problem that varies by site, a sensor problem specific to LP (liquefied petroleum) gas vessels, and a data problem — turning raw fill readings into actionable dispatch intelligence. +The root cause is infrastructure. A propane tank sits in a field, on a farm, at a cabin, at a rural business, almost never near a WiFi access point the dealer can use, and often in areas where cellular is marginal to nonexistent. The tank itself is a sealed pressure vessel with no native communication capability. Retrofitting telemetry means solving a connectivity problem that varies by site, a sensor problem specific to LP (liquefied petroleum) gas vessels, and a data problem of turning raw fill readings into actionable dispatch intelligence. -This project solves all three. **A weatherproof electronics enclosure mounted on a post or bracket outside the AHJ-defined classified area**, connected by field wiring to a 4-20 mA LP gauge-port float transmitter at the tank's existing dip-tube gauge port and a DS18B20 temperature probe strapped to the tank shell. The device wakes every 15 minutes, reads the transmitter current and tank temperature, converts the transmitter's linear 4–20 mA output directly to fill percentage, updates a smoothed daily consumption rate, and reports a daily summary to the [Blues Notehub](https://blues.com/notehub/) cloud service. When fill drops below a configurable low-fill threshold, an alert fires immediately. The dealer's dispatch system sees fill %, gallons remaining, and projected days-until-empty for every tank in the fleet — enough to replace the calendar with a demand-driven route that only rolls a truck when a tank actually needs it. +This project solves all three. **A weatherproof electronics enclosure mounted on a post or bracket outside the AHJ-defined classified area**, connected by field wiring to a 4-20 mA LP gauge-port float transmitter at the tank's existing dip-tube gauge port and a DS18B20 temperature probe strapped to the tank shell. The device wakes every 15 minutes, reads the transmitter current and tank temperature, converts the transmitter's linear 4–20 mA output directly to fill percentage, updates a smoothed daily consumption rate, and reports a daily summary to the [Blues Notehub](https://blues.com/notehub/) cloud service. When fill drops below a configurable low-fill threshold, an alert fires immediately. The dealer's dispatch system sees fill %, gallons remaining, and projected days-until-empty for every tank in the fleet. That's enough to replace the calendar with a demand-driven route that only rolls a truck when a tank actually needs it. -**Why Notecard for Skylo.** Propane tanks are at farms, cabins, rural businesses, and residential properties — most with no customer WiFi the dealer can use, and many in areas where cellular coverage is spotty to nonexistent. A dealer network spans all of these site types and can't afford a different hardware solution for each one. [Notecard for Skylo](https://shop.blues.com/products/notecard-for-skylo?utm_source=dev-blues&utm_medium=web&utm_campaign=store-link) (NOTE-NBGLWX) carries three radios on one M.2 module — cellular (LTE-M / NB-IoT / GPRS), WiFi, and satellite over the [Skylo](https://www.skylo.tech/) non-terrestrial network (NTN) — and selects among them automatically. The firmware sets a single [`card.transport`](https://dev.blues.io/api-reference/notecard-api/card-requests/#card-transport) preference of `wifi-cell-ntn`: prefer WiFi where a provisioned AP happens to be in range (the rare residential tank), fall back to cellular (the de-facto primary across the bulk of the territory), and fall back again to Skylo satellite at remote sites. Failover is handled by the Notecard; the host firmware never branches on which network is live. That collapses what used to be a two-device decision — a cellular Notecard for in-coverage tanks plus a separate satellite add-on for the rest — into a single part number, a single antenna kit, and a single firmware image that deploys unchanged across the entire fleet. Notecard for Skylo ships with an active global SIM including 500 MB of cellular data and 10 years of service, plus 10 KB of bundled Skylo satellite data — no activation fees and no monthly per-SIM commitment. There is nothing to swap when a site turns out to have weaker coverage than the survey suggested: the same board that runs on cellular near town automatically reaches the Skylo network at the cabin. +**Why Notecard for Skylo.** Propane tanks are at farms, cabins, rural businesses, and residential properties — most with no customer WiFi the dealer can use, and many in areas where cellular coverage is spotty to nonexistent. A dealer network spans all of these site types and can't afford a different hardware solution for each one. [Notecard for Skylo](https://shop.blues.com/products/notecard-for-skylo?utm_source=dev-blues&utm_medium=web&utm_campaign=store-link) (NOTE-NBGLWX) carries three radios on one M.2 module — cellular (LTE-M / NB-IoT / GPRS), WiFi, and satellite over the [Skylo](https://www.skylo.tech/) non-terrestrial network (NTN) — and selects among them automatically. The firmware sets a single [`card.transport`](https://dev.blues.io/api-reference/notecard-api/card-requests/#card-transport) preference of `wifi-cell-ntn`: prefer WiFi where a provisioned AP happens to be in range (the rare residential tank), fall back to cellular (the de-facto primary across the bulk of the territory), and fall back again to Skylo satellite at remote sites. Failover is handled by the Notecard; the host firmware never branches on which network is live. That collapses what used to be a two-device decision — a cellular Notecard for in-coverage tanks plus a separate satellite add-on for the rest — into a single part number, a single antenna kit, and a single firmware image that deploys unchanged across the entire fleet. Notecard for Skylo ships with an active global SIM including 500 MB of cellular data and 10 years of service, plus 10 KB of bundled Skylo satellite data, with no activation fees and no monthly per-SIM commitment. There is nothing to swap when a site turns out to have weaker coverage than the survey suggested: the same board that runs on cellular near town automatically reaches the Skylo network at the cabin. -**Deployment scenario.** A weatherproof NEMA 4X enclosure mounted on a separate post, wall, or bracket **outside the AHJ-defined classified area** (see the safety notice in §4), powered by a solar-charged 12 V sealed lead-acid battery. A 4-20 mA LP gauge-port float transmitter (Rochester Sensors M6300-LP Magnetel® gauge + R6315-12 transmitter, or equivalent) connects at the tank's existing 1¼″ NPT dip-tube gauge port; field wiring from the transmitter runs to the electronics enclosure outside the hazardous boundary. A waterproof DS18B20 temperature probe is clamped to the tank shell and logged in daily summary Notes for seasonal demand analytics. Notecard for Skylo's antenna cables exit the enclosure to outdoor-mounted antennas with a clear sky view — the same Skylo-certified antenna carries both cellular and satellite, so where cellular coverage is absent the board falls back to the Skylo NTN satellite network automatically over the same Notehub project, with no antenna swap and no firmware changes. No modifications to the tank itself, no on-site internet infrastructure, and no OEM cooperation required. +**Deployment scenario.** A weatherproof NEMA 4X enclosure mounted on a separate post, wall, or bracket **outside the AHJ-defined classified area** (see the safety notice in §4), powered by a solar-charged 12 V sealed lead-acid battery. A 4-20 mA LP gauge-port float transmitter (Rochester Sensors M6300-LP Magnetel® gauge + R6315-12 transmitter, or equivalent) connects at the tank's existing 1¼″ NPT dip-tube gauge port; field wiring from the transmitter runs to the electronics enclosure outside the hazardous boundary. A waterproof DS18B20 temperature probe is clamped to the tank shell and logged in daily summary Notes for seasonal demand analytics. Notecard for Skylo's antenna cables exit the enclosure to outdoor-mounted antennas with a clear sky view. The same Skylo-certified antenna carries both cellular and satellite, so where cellular coverage is absent the board falls back to the Skylo NTN satellite network automatically over the same Notehub project, with no antenna swap and no firmware changes. No modifications to the tank itself, no on-site internet infrastructure, and no OEM cooperation required. ## 2. System Architecture ![System architecture: propane tank with 4–20 mA float transmitter and DS18B20 → edge enclosure outside hazardous area → Notecard for Skylo (cellular / WiFi / satellite) → Notehub → dispatch / ERP / time-series DB](diagrams/01-system-architecture.svg) -**Device-side responsibilities.** Inside the post-mounted enclosure, the Cygnet STM32 host on the Notecarrier CX wakes every `sample_interval_min` (default 15 minutes), reads the 4-20 mA float transmitter and the DS18B20 shell probe, converts the linear current straight to fill percentage and gallons remaining, and updates a smoothed consumption-rate estimate. If a threshold trips, it queues an alert Note right then; otherwise it just goes back to sleep. Once per `report_interval_hr` (default 24 hours) it ships a templated summary carrying current fill %, fill gallons, minimum fill seen in the window, window-averaged temperature, daily consumption rate, and projected days-until-empty. Between wakes the host is cut entirely via [`card.attn`](https://dev.blues.io/api-reference/notecard-api/card-requests/#card-attn) and Notecard for Skylo idles at ~8 µA — every queued [Note](https://dev.blues.io/api-reference/glossary/#note) travels over I²C with no JSON hand-rolling and no AT commands. +**Device-side responsibilities.** Inside the post-mounted enclosure, the Cygnet STM32 host on the Notecarrier CX wakes every `sample_interval_min` (default 15 minutes), reads the 4-20 mA float transmitter and the DS18B20 shell probe, converts the linear current straight to fill percentage and gallons remaining, and updates a smoothed consumption-rate estimate. If a threshold trips, it queues an alert Note right then; otherwise it just goes back to sleep. Once per `report_interval_hr` (default 24 hours) it ships a templated summary carrying current fill %, fill gallons, minimum fill seen in the window, window-averaged temperature, daily consumption rate, and projected days-until-empty. Between wakes the host is cut entirely via [`card.attn`](https://dev.blues.io/api-reference/notecard-api/card-requests/#card-attn) and Notecard for Skylo idles at ~8 µA. Every queued [Note](https://dev.blues.io/api-reference/glossary/#note) travels over I²C with no JSON hand-rolling and no AT commands. **Notecard responsibilities.** Notecard for Skylo runs the same playbook regardless of which radio is live: hold Notes in its on-device queue, open a session on the [`hub.set`](https://dev.blues.io/api-reference/notecard-api/hub-requests/#hub-set) `outbound` cadence, and push any `sync:true` alert through immediately. The `card.transport` `wifi-cell-ntn` preference set at boot decides the path automatically — WiFi where a provisioned AP is reachable, cellular at the bulk of sites, and Skylo satellite at remote sites — with no firmware branching. Either way, the same module pulls [environment variables](https://dev.blues.io/guides-and-tutorials/notecard-guides/understanding-environment-variables/) from Notehub on every inbound sync, so a dispatcher can retune transmitter calibration or alert thresholds for any tank in the fleet without anyone driving out to it. -**Notehub responsibilities.** Events land in [Notehub](https://dev.blues.io/notehub/notehub-walkthrough/) from whatever transport carried them, where they're ingested, stored, and fanned out through project-level routes. Per-fleet [environment variables](https://dev.blues.io/guides-and-tutorials/notecard-guides/understanding-environment-variables/) are how a single firmware image services tanks of every capacity — the tank size and sensor calibration live in Notehub, not in compiled constants. [Smart Fleets](https://dev.blues.io/notehub/notehub-walkthrough/#using-smart-fleet-rules) make it easy to group tanks by territory, capacity class, or customer type so the right calibration values flow to the right tanks automatically. +**Notehub responsibilities.** Events land in [Notehub](https://dev.blues.io/notehub/notehub-walkthrough/) from whatever transport carried them, where they're ingested, stored, and fanned out through project-level routes. Per-fleet [environment variables](https://dev.blues.io/guides-and-tutorials/notecard-guides/understanding-environment-variables/) are how a single firmware image services tanks of every capacity: the tank size and sensor calibration live in Notehub, not in compiled constants. [Smart Fleets](https://dev.blues.io/notehub/notehub-walkthrough/#using-smart-fleet-rules) make it easy to group tanks by territory, capacity class, or customer type so the right calibration values flow to the right tanks automatically. **Routing to the cloud (high level).** 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 reference design does not ship any specific downstream endpoint. The natural downstream targets for a propane dealer are a route-optimization or ERP system (routed via HTTP webhook) and a time-series database for trend analysis (routed to a cloud data store of the dealer's choosing). @@ -124,7 +124,7 @@ All Notecarrier CX host I/O lands on its dual 16-pin header. Notecard for Skylo -**Step 1 — Enclosure and cable-gland assignment.** Install the NEMA 4X polycarbonate enclosure at the chosen mounting location. Drill and install one cable gland for each field-cable penetration before pulling cables. Assign glands as follows: +**Step 1: Enclosure and cable-gland assignment.** Install the NEMA 4X polycarbonate enclosure at the chosen mounting location. Drill and install one cable gland for each field-cable penetration before pulling cables. Assign glands as follows: | Gland | Cable / penetration | |---|---| @@ -135,28 +135,28 @@ All Notecarrier CX host I/O lands on its dual 16-pin header. Notecard for Skylo Match each gland's cable-OD clamp range to the actual cable outer diameter. Tighten all glands to the manufacturer's torque spec after routing cables; leave no unused penetration open. -**Step 2 — Solar panel to charge controller (PV input).** +**Step 2: Solar panel to charge controller (PV input).** - **Solar panel PV+** → charge controller **PV+** terminal. - **Solar panel PV−** → charge controller **PV−** terminal. Mount the panel in an unobstructed location with good sky view — not against the tank body or in the tank's shadow. Tilt angle should maximize winter sun exposure for the deployment latitude. Run the panel cable into the enclosure through an appropriately-sized cable gland (or use an MC4 weatherproof pass-through if the controller has external PV terminals). Keep the run as short as practical to minimize resistive loss. -**Step 3 — SLA battery to charge controller (battery terminals).** +**Step 3: SLA battery to charge controller (battery terminals).** - **Battery (+)** → charge controller **BATT+** terminal. - **Battery (−)** → charge controller **BATT−** terminal. Use wire rated for the battery's short-circuit current (14 AWG minimum for a 7–10 Ah SLA). Place the **inline fuse holder + 5 A fuse** from the BOM in the battery (+) lead, as close to the battery positive terminal as possible. Use a weatherproof fuse holder if the battery is positioned outside the NEMA 4X enclosure. -**Step 4 — Charge controller load output to step-down module.** +**Step 4: Charge controller load output to step-down module.** - **Charge controller LOAD+** → step-down module **Vin+**. - **Charge controller LOAD−** → step-down module **Vin−** / GND. The Victron SmartSolar MPPT 75/10 has dedicated **LOAD+ / LOAD−** terminals with built-in low-voltage disconnect (LVD); these terminals switch the 12 V supply on and off based on battery state to protect the SLA. **Only use this wiring with a controller that has LOAD terminals and LVD** — if a different controller is substituted, verify those features before following these steps. If the controller lacks LOAD terminals, wire from BATT terminals and use the controller's LVD relay or alarm output to interrupt the load circuit. -**Step 5 — 12 V step-down to Mojo and Notecarrier +VBAT (5 V rail).** +**Step 5: 12 V step-down to Mojo and Notecarrier +VBAT (5 V rail).** Set the step-down module output to **5.0 V** and verify with a meter before connecting any load. @@ -169,18 +169,18 @@ Mojo LOAD− → Notecarrier CX GND During bench validation the Mojo sits in this path to measure 5 V rail current. For field deployment, remove the Mojo and wire the step-down Vout+ directly to Notecarrier CX +VBAT. -**Step 6 — Notecard installation and antenna connections.** +**Step 6: Notecard installation and antenna connections.** Seat Notecard for Skylo (NOTE-NBGLWX) into the Notecarrier CX M.2 slot and secure the retaining screw. Notecard for Skylo exposes two antenna u.FL ports — **MAIN** and **GPS**. The single Skylo-certified antenna on the MAIN port carries **both** the cellular and the satellite signal; there is no separate satellite antenna to install. Connect antennas as follows: -- **MAIN port** — attach the included Skylo-certified antenna, routed through Gland 1 (connect it directly, or adapt it to an external SMA bulkhead with a u.FL-to-SMA-F pigtail). Mount the antenna outdoors with an unobstructed view of the sky (northern hemisphere: the southern sky) so the board can reach the Skylo satellite network wherever it falls back from cellular. Use only the Skylo-certified antenna; an uncertified part risks regulatory non-compliance and link failure. *Do not skip this connection — both cellular and satellite operation require this external antenna.* -- **GPS port** — attach the passive GPS/GNSS antenna, routed through Gland 2, and mount it outdoors with a clear sky view alongside the main antenna. +- **MAIN port:** attach the included Skylo-certified antenna, routed through Gland 1 (connect it directly, or adapt it to an external SMA bulkhead with a u.FL-to-SMA-F pigtail). Mount the antenna outdoors with an unobstructed view of the sky (northern hemisphere: the southern sky) so the board can reach the Skylo satellite network wherever it falls back from cellular. Use only the Skylo-certified antenna; an uncertified part risks regulatory non-compliance and link failure. *Do not skip this connection — both cellular and satellite operation require this external antenna.* +- **GPS port:** attach the passive GPS/GNSS antenna, routed through Gland 2, and mount it outdoors with a clear sky view alongside the main antenna. Select antenna cable lengths to suit the routing distance before ordering — most pre-terminated assemblies should not be cut or field-terminated. Secure any excess cable outside the enclosure with a gentle loop; do not coil cable inside the enclosure. -**Step 7 — 4–20 mA current loop (gauge-port level transmitter).** +**Step 7: 4–20 mA current loop (gauge-port level transmitter).** The Rochester Sensors M6300-LP + R6315-12 is a two-wire loop-powered instrument. A single 2-conductor cable runs from the transmitter (at the tank gauge port, outside or at the hazardous boundary) to the electronics enclosure. Route this cable through Gland 4. Wire the loop from the **dedicated 24 V boost converter output** — not the 12 V system rail and not the 5 V Notecarrier rail (see compliance Note below): @@ -208,7 +208,7 @@ The transmitter process connection is at the tank's **single 1¼″ NPT dip-tube Confirm that system GND (battery −), charge controller LOAD−, step-down Vin−, step-down Vout−, boost converter GND, and Notecarrier GND are all connected to the same node before applying power. -**Step 8 — DS18B20 temperature probe.** +**Step 8: DS18B20 temperature probe.** Route the DS18B20 cable through Gland 3. Mount the probe body against the tank shell — ideally under a layer of closed-cell foam tape to improve thermal contact and reduce ambient-air influence — and secure the cable with a zip tie to prevent mechanical strain at the gland. Inside the enclosure: @@ -217,7 +217,7 @@ Route the DS18B20 cable through Gland 3. Mount the probe body against the tank s - **DS18B20 yellow wire (data)** → **D2** on the Notecarrier CX header. - **4.7 kΩ pull-up resistor** between the data wire and **+3V3**. The Notecarrier CX does not include an onboard OneWire pull-up; this resistor is required. -**Step 9 — Satellite operation (automatic, no added hardware).** +**Step 9: Satellite operation (automatic, no added hardware).** No additional module or wiring is required for satellite operation — Notecard for Skylo's satellite radio is on the same M.2 board as cellular and WiFi, and the single Skylo-certified MAIN antenna (Step 6) carries the satellite link. The firmware enables cellular→satellite fallback by setting `card.transport` to `wifi-cell-ntn` at boot (see §7); the Notecard then routes queued Notes over the Skylo NTN satellite network automatically at any site where cellular is unavailable. To make satellite work in the field, the MAIN antenna must be mounted **outdoors with an unobstructed view of the sky** (northern hemisphere: the southern sky) — confirm a suitable mounting location at remote tank sites. The daily summary Note (~40 bytes) fits well within the NTN payload budget. Note that the board must complete at least one initial non-NTN (cellular or WiFi) sync to associate with Notehub and register Notefile templates before satellite can be used; commission each unit where it has terrestrial coverage even if it will routinely operate over satellite. Review the [Satellite Best Practices guide](https://dev.blues.io/starnote/satellite-best-practices/) for duty-cycle and data-budget considerations before deploying to a cellular-dark site. @@ -239,9 +239,9 @@ No additional module or wiring is required for satellite operation — Notecard 3. **Optional: configure WiFi credentials.** Notecard for Skylo supports WiFi as an optional secondary transport — the device operates normally on cellular (or satellite) alone if no WiFi credentials are set. Two reliable provisioning paths are available for this hardware stack: - - **Preferred — Notehub environment variables (works on deployed hardware).** Set the `wifi_ssid` and `wifi_password` environment variables in Notehub (see the env var table in step 5 below). Env vars are delivered to the device on the next **inbound sync**. Because `hubConfigure()` sets inbound at 2× the outbound period, the default 24-hour report cadence means inbound syncs occur every 48 hours — **WiFi credentials set in Notehub may take up to 48 hours to reach the device.** Once the inbound sync delivers the vars, the firmware issues `card.wifi` to store the credentials on the Notecard; the Notecard then connects over WiFi when it provides better or equivalent coverage to cellular. For faster credential rollout, temporarily lower `report_interval_hr` (e.g. set to 1 hour), confirm connectivity, then restore the original value. Credentials persist on the Notecard even if the env vars are later cleared. + - **Preferred: Notehub environment variables (works on deployed hardware).** Set the `wifi_ssid` and `wifi_password` environment variables in Notehub (see the env var table in step 5 below). Env vars are delivered to the device on the next **inbound sync**. Because `hubConfigure()` sets inbound at 2× the outbound period, the default 24-hour report cadence means inbound syncs occur every 48 hours — **WiFi credentials set in Notehub may take up to 48 hours to reach the device.** Once the inbound sync delivers the vars, the firmware issues `card.wifi` to store the credentials on the Notecard; the Notecard then connects over WiFi when it provides better or equivalent coverage to cellular. For faster credential rollout, temporarily lower `report_interval_hr` (e.g. set to 1 hour), confirm connectivity, then restore the original value. Credentials persist on the Notecard even if the env vars are later cleared. - - **Alternative — direct Notecard USB (bench setup before deployment).** Connect a USB cable to the **Notecard module's own USB port** (the small USB connector on the Notecard M.2 card itself — not the Notecarrier CX USB-C port, which connects to the Cygnet host MCU). With that connection active, open [Notecard Playground](https://dev.blues.io/terminal/) and issue: `{"req":"card.wifi","ssid":"","password":""}`. This is most practical to do at the bench before sealing the enclosure for field deployment. + - **Alternative: direct Notecard USB (bench setup before deployment).** Connect a USB cable to the **Notecard module's own USB port** (the small USB connector on the Notecard M.2 card itself — not the Notecarrier CX USB-C port, which connects to the Cygnet host MCU). With that connection active, open [Notecard Playground](https://dev.blues.io/terminal/) and issue: `{"req":"card.wifi","ssid":"","password":""}`. This is most practical to do at the bench before sealing the enclosure for field deployment. WiFi is not required for normal operation and does not need to be provisioned on every device. @@ -320,7 +320,7 @@ No density or temperature correction is applied to the fill reading — the floa ### Sensor selection rationale -The initial project specification called for a low-power ultrasonic or pressure level sensor with the DS18B20 temperature probe used for vapor-pressure compensation in the fill measurement path. After evaluating both sensing methods for LP gas tank duty, this design departs from that specification and uses a float-type 4–20 mA transmitter instead. The rationale is detailed in the table below and summarised in the firmware's top-of-file sensor model comment. +The initial project specification called for a low-power ultrasonic or pressure level sensor with the DS18B20 temperature probe used for vapor-pressure compensation in the fill measurement path. After evaluating both sensing methods for LP gas tank duty, this design departs from that specification and uses a float-type 4–20 mA transmitter instead. The rationale is detailed in the table below and summarized in the firmware's top-of-file sensor model comment. | Approach | Why evaluated | Why not selected for this design | |---|---|---| @@ -551,7 +551,7 @@ Note: the 4-20 mA transmitter loop is powered from the 24 V boost converter circ ## 11. Limitations and Next Steps -This reference design covers the common case of a dealer instrumenting a tank fleet for demand-driven dispatch — float transmitter at the gauge port, temperature probe on the shell, cellular (or satellite) backhaul. The trade-offs below are deliberate scope choices; each has a clear extension path for a production rollout. +This reference design covers the common case of a dealer instrumenting a tank fleet for demand-driven dispatch: a float transmitter at the gauge port, a temperature probe on the shell, cellular (or satellite) backhaul. The trade-offs below are deliberate scope choices; each has a clear extension path for a production rollout. ### Simplified for the POC @@ -559,23 +559,23 @@ This reference design covers the common case of a dealer instrumenting a tank fl **Fill-gallons calculation uses a linear scale.** `computeFillGal` computes `fill_gal = (fill_pct / 100) × tank_capacity_gal`. The horizontal-cylinder cross-section introduces a small nonlinearity between liquid height and volume (the relationship curves near the top and bottom of the tank). This nonlinearity is not corrected in firmware — an additional geometry correction table keyed to `tank_inner_diameter_in` could improve accuracy at fill levels below ~20 % or above ~80 %, at the cost of an additional environment variable and more complex calibration. For the typical operating range (20–80 % fill) the linear-scale error is small. -**Satellite (NTN) operation requires an unobstructed sky-view antenna and an initial non-NTN sync.** Notecard for Skylo adds satellite with no extra module, but to use the Skylo link the Skylo-certified MAIN antenna must be mounted outdoors with a clear view of the sky (northern hemisphere: the southern sky) — it cannot reach the satellite from beneath a metal obstruction. Satellite operation is also opt-in at the Notecard level: the firmware enables it by setting `card.transport` to `wifi-cell-ntn`, and the board must complete at least one initial non-NTN (cellular or WiFi) sync to associate with Notehub and register Notefile templates before NTN works — commission each unit where it has terrestrial coverage. Over satellite, expect alert latency in minutes (not seconds), keep each Note within the NTN payload budget, and remember that inbound syncs draw on the bundled 10 KB satellite allocation. At remote tank sites, confirm a suitable sky-view antenna location before relying on the satellite path. +**Satellite (NTN) operation requires an unobstructed sky-view antenna and an initial non-NTN sync.** Notecard for Skylo adds satellite with no extra module, but to use the Skylo link the Skylo-certified MAIN antenna must be mounted outdoors with a clear view of the sky (northern hemisphere: the southern sky); it cannot reach the satellite from beneath a metal obstruction. Satellite operation is also opt-in at the Notecard level: the firmware enables it by setting `card.transport` to `wifi-cell-ntn`, and the board must complete at least one initial non-NTN (cellular or WiFi) sync to associate with Notehub and register Notefile templates before NTN works — commission each unit where it has terrestrial coverage. Over satellite, expect alert latency in minutes (not seconds), keep each Note within the NTN payload budget, and remember that inbound syncs draw on the bundled 10 KB satellite allocation. At remote tank sites, confirm a suitable sky-view antenna location before relying on the satellite path. **Electronics must be outside the classified area; IS barrier may be required.** Blues Notecard and Notecarrier CX electronics are not rated for hazardous locations and must be installed outside the classified area boundary defined by NFPA 58 and the authority having jurisdiction. For 4–20 mA wiring that crosses the classified-area boundary, the AHJ may require a listed intrinsic-safety (IS) barrier in the loop circuit between the tank-side transmitter and the enclosure-side electronics. Transmitter selection, fitting compatibility, classified-area boundary determination, and any IS barrier requirement are outside the scope of the electronics design. Any connection to a propane pressure vessel must comply with NFPA 58, applicable codes, and be performed by a licensed LP gas technician. **Consumption rate requires stable readings over time.** The EWMA consumption rate is meaningful only after several days of operation. On first deployment, `days_until_empty` may be unreliable until the EWMA has converged. The firmware initializes consumption to zero and does not report `days_until_empty` until at least two consecutive valid fill readings exist. -**No flow meter.** Consumption rate is estimated from successive fill readings — a delta-volume over delta-time approximation. This is accurate enough for daily route planning but not for billing or leak detection at high precision. A turbine or ultrasonic flow meter at the regulator outlet would give direct consumption measurement; integration would require an additional pulse-counting or analog input channel. +**No flow meter.** Consumption rate is estimated from successive fill readings, a delta-volume over delta-time approximation. This is accurate enough for daily route planning but not for billing or leak detection at high precision. A turbine or ultrasonic flow meter at the regulator outlet would give direct consumption measurement; integration would require an additional pulse-counting or analog input channel. **Mojo is bench-validation equipment only.** The firmware does not read the Mojo's LTC2959 coulomb counter at runtime. Adding cumulative mAh to the daily summary is a straightforward extension if fleet-level power telemetry is useful for the dealer's operations team. ### Production Next Steps -- Transmitter calibration tool — a Notehub JSONata route transform that reads `transmitter_ma` from the first three Notes after provisioning and auto-suggests a `sensor_full_ma` correction, removing the manual commissioning step. +- Transmitter calibration tool: a Notehub JSONata route transform that reads `transmitter_ma` from the first three Notes after provisioning and auto-suggests a `sensor_full_ma` correction, removing the manual commissioning step. - Refill event detection: when `fill_pct` increases by more than 10 % in a single sample cycle, emit a `refill_detected` Note with the pre- and post-fill readings. This lets the dealer's billing system close the loop on deliveries without a separate ticket. - Per-tank consumption model: extend the EWMA with seasonal coefficients (summer vs. winter heating demand) so `days_until_empty` is corrected for known demand patterns, not just trailing-average consumption. -- Over-the-air host firmware updates via [Notecard Outboard DFU](https://dev.blues.io/notehub/host-firmware-updates/notecard-outboard-firmware-update/) once the fleet reaches scale — a threshold recalibration or a new alert type can be pushed fleet-wide without a site visit. +- Over-the-air host firmware updates via [Notecard Outboard DFU](https://dev.blues.io/notehub/host-firmware-updates/notecard-outboard-firmware-update/) once the fleet reaches scale. A threshold recalibration or a new alert type can be pushed fleet-wide without a site visit. ## 12. Summary -The dealer who used to roll a truck every six weeks because that's what the calendar said now rolls a truck because a specific tank is at 22% and trending toward empty in nine days. A float transmitter at the gauge port, a temperature probe on the shell, a single Notecard for Skylo that carries cellular, WiFi, and satellite on one module — reaching cellular near town and the Skylo satellite network at the remote cabin with nothing to swap — and a daily summary in Notehub turn every tank in the territory into a self-reporting asset — fewer miles, fewer emergency calls, and no more Friday-night apologies to the customer whose heat just went out. +The dealer who used to roll a truck every six weeks because that's what the calendar said now rolls a truck because a specific tank is at 22% and trending toward empty in nine days. A float transmitter at the gauge port, a temperature probe on the shell, a single Notecard for Skylo that carries cellular, WiFi, and satellite on one module — reaching cellular near town and the Skylo satellite network at the remote cabin with nothing to swap — and a daily summary in Notehub turn every tank in the territory into a self-reporting asset: fewer miles, fewer emergency calls, and no more Friday-night apologies to the customer whose heat just went out. diff --git a/58-commercial-grease-interceptor-level-monitor/README.md b/58-commercial-grease-interceptor-level-monitor/README.md index ae318098..4cc7cded 100644 --- a/58-commercial-grease-interceptor-level-monitor/README.md +++ b/58-commercial-grease-interceptor-level-monitor/README.md @@ -20,7 +20,7 @@ This project is a [truck-roll reduction](https://blues.com/truck-roll-reduction/ To stay compliant, **FSEs** (food service establishments, restaurants, cafeterias, ghost kitchens, institutional food service) hire a pumping provider who periodically vacuums the trap clean. The industry default is a fixed service cadence: the truck shows up every four weeks, or every two weeks, regardless of how full the trap actually is. In practice, a slow-season week produces far less grease than a holiday rush. Fixed cadence means the pumper sometimes arrives when the interceptor is only 30% full — a truck roll that did nothing for compliance, and sometimes arrives after the interceptor has already overflowed. Neither outcome is good, and the FSE pays for every dispatch. -A fill-level sensor changes the economics entirely. With a real-time reading, the pumping provider dispatches trucks on condition rather than on schedule. Interceptors that fill quickly (high-volume kitchens, fryer-heavy menus) get serviced before they overflow; interceptors that fill slowly get serviced less often without the compliance risk. The result is fewer unnecessary truck rolls, better route efficiency, and a condition-based service story the pumper can offer as a premium tier. **This reference design targets hydromechanical (HGI) and batch-collection interceptors without a fixed outlet weir — geometries where the top liquid surface rises predictably as FOG and wastewater accumulate, so a rising fill percentage is a meaningful proxy for pump-out urgency.** For deployments on conventional constant-level gravity interceptors — where an outlet weir holds the liquid surface nearly fixed regardless of FOG-layer depth. See the measurement-model Note below and §10. +A fill-level sensor changes the economics entirely. With a real-time reading, the pumping provider dispatches trucks on condition rather than on schedule. Interceptors that fill quickly (high-volume kitchens, fryer-heavy menus) get serviced before they overflow; interceptors that fill slowly get serviced less often without the compliance risk. The result is fewer unnecessary truck rolls, better route efficiency, and a condition-based service story the pumper can offer as a premium tier. **This reference design targets hydromechanical (HGI) and batch-collection interceptors without a fixed outlet weir — geometries where the top liquid surface rises predictably as FOG and wastewater accumulate, so a rising fill percentage is a meaningful proxy for pump-out urgency.** For deployments on conventional constant-level gravity interceptors, where an outlet weir holds the liquid surface nearly fixed regardless of FOG-layer depth, see the measurement-model Note below and §10. diff --git a/60-lone-worker-panic-fall-detection-beacon/README.md b/60-lone-worker-panic-fall-detection-beacon/README.md index b4611b49..04ba3c32 100644 --- a/60-lone-worker-panic-fall-detection-beacon/README.md +++ b/60-lone-worker-panic-fall-detection-beacon/README.md @@ -575,7 +575,7 @@ The forward-looking work that turns this into a deployable wearable follows, rou **LIS3DH hardware free-fall and shock detection** configured via the `INT1_CFG`, `INT1_THS`, and `INT1_DURATION` registers offloads Stage 1 detection entirely to the accelerometer silicon. -**A cancel-alert flow** gives the worker a way out of a false alarm: a post-panic confirmation cancel within N seconds, routed as a `cancel` event on `beacon_alert.qo` carrying the same `event_id` as the alert being cancelled. +**A cancel-alert flow** gives the worker a way out of a false alarm: a post-panic confirmation cancel within N seconds, routed as a `cancel` event on `beacon_alert.qo` carrying the same `event_id` as the alert being canceled. **Worker check-in acknowledgment** closes the loop back to the worker: a dispatcher can send a Notehub [Signal](https://dev.blues.io/api-reference/glossary/#signal) back to the device, triggering a distinctive haptic pattern so the worker knows their alert was received. diff --git a/61-regulatory-grade-pharmacy-lab-cold-storage-audit-monitor/README.md b/61-regulatory-grade-pharmacy-lab-cold-storage-audit-monitor/README.md index 92e7f2de..9a6983d4 100644 --- a/61-regulatory-grade-pharmacy-lab-cold-storage-audit-monitor/README.md +++ b/61-regulatory-grade-pharmacy-lab-cold-storage-audit-monitor/README.md @@ -270,7 +270,7 @@ Dependencies: | UTC epoch from Notecard RTC | `getEpochTime` | `_helpers.cpp` | | Per-sample reading Note | `sendReading` | `_helpers.cpp` | | Immediate-sync alert Note | `sendAlert` | `_helpers.cpp` | -| State serialisation and host power-down | `goToSleep` | `_helpers.cpp` | +| State serialization and host power-down | `goToSleep` | `_helpers.cpp` | ### Sensor reading strategy diff --git a/62-construction-site-environmental-noise-exposure-monitor/README.md b/62-construction-site-environmental-noise-exposure-monitor/README.md index 20e39733..3952078b 100644 --- a/62-construction-site-environmental-noise-exposure-monitor/README.md +++ b/62-construction-site-environmental-noise-exposure-monitor/README.md @@ -20,13 +20,13 @@ This project is a solar-powered cellular **area monitor** — a fixed, perimeter -**Deployment scenario.** A weatherproof NEMA 4X enclosure mounted on a temporary fence post, T-bar stake, or equipment cage near the active work area. For dust monitoring, position the sensor **downwind** of the dust-generating task so the plume passes through the sensor rather than away from it — upwind placement will miss the plume entirely. For noise monitoring, place the enclosure within 5–10 metres of the primary noise source. For **particulate** background subtraction, deploy a second unit upwind of the site as a baseline; the arithmetic difference between the two PM concentration readings (µg/m³) approximates the task-generated particulate contribution. A second sound monitor deployed upwind or in a quieter reference area is useful contextual information, but dB(A) values cannot be meaningfully background-subtracted by simple arithmetic. Decibel levels are logarithmic representations of acoustic energy, so isolating the task-generated contribution means working in the energy domain: convert to intensity in W/m², subtract, then convert back. Direct subtraction of dB numbers is acoustically incorrect. A 6V solar panel is surface-mounted on the enclosure lid. The LiPo battery inside provides overnight autonomy between solar charging sessions. No shore power, no network drops, and no daily downloads. +**Deployment scenario.** A weatherproof NEMA 4X enclosure mounted on a temporary fence post, T-bar stake, or equipment cage near the active work area. For dust monitoring, position the sensor **downwind** of the dust-generating task so the plume passes through the sensor rather than away from it — upwind placement will miss the plume entirely. For noise monitoring, place the enclosure within 5–10 meters of the primary noise source. For **particulate** background subtraction, deploy a second unit upwind of the site as a baseline; the arithmetic difference between the two PM concentration readings (µg/m³) approximates the task-generated particulate contribution. A second sound monitor deployed upwind or in a quieter reference area is useful contextual information, but dB(A) values cannot be meaningfully background-subtracted by simple arithmetic. Decibel levels are logarithmic representations of acoustic energy, so isolating the task-generated contribution means working in the energy domain: convert to intensity in W/m², subtract, then convert back. Direct subtraction of dB numbers is acoustically incorrect. A 6V solar panel is surface-mounted on the enclosure lid. The LiPo battery inside provides overnight autonomy between solar charging sessions. No shore power, no network drops, and no daily downloads. ## 2. System Architecture ![System architecture: PMSA003I + SEN0232 → Notecarrier CX (Cygnet host + Notecard MBGLW) → cellular → Notehub → safety alerts and compliance archive](diagrams/01-system-architecture.svg) -**Device-side responsibilities.** The order of operations on the Cygnet STM32 host matters because the PM sensor's fan would contaminate the sound measurement if it ran during the dB(A) window. Every 5 minutes the host wakes, samples sound for 15 seconds first — before any I²C traffic starts the PMSA003I — then initialises the PM sensor, waits 30 seconds for laser and fan to stabilise, and averages 10 readings over the next 10 seconds. Every sample folds into a rolling window kept in Notecard flash so it survives the sleep, and between cycles [`card.attn`](https://dev.blues.io/api-reference/notecard-api/card-requests/#card-attn) cuts Cygnet power entirely, dropping host current to essentially zero. Queued Notes ride from the Cygnet to the Notecard over I²C using the `note-arduino` library's `JAdd*` helpers — no JSON hand-marshaling, no modem AT commands. +**Device-side responsibilities.** The order of operations on the Cygnet STM32 host matters because the PM sensor's fan would contaminate the sound measurement if it ran during the dB(A) window. Every 5 minutes the host wakes, samples sound for 15 seconds first — before any I²C traffic starts the PMSA003I — then initializes the PM sensor, waits 30 seconds for laser and fan to stabilize, and averages 10 readings over the next 10 seconds. Every sample folds into a rolling window kept in Notecard flash so it survives the sleep, and between cycles [`card.attn`](https://dev.blues.io/api-reference/notecard-api/card-requests/#card-attn) cuts Cygnet power entirely, dropping host current to essentially zero. Queued Notes ride from the Cygnet to the Notecard over I²C using the `note-arduino` library's `JAdd*` helpers — no JSON hand-marshaling, no modem AT commands. **Notecard responsibilities.** The Notecard buffers each [Note](https://dev.blues.io/api-reference/glossary/#note) in its on-device queue, opens a cellular session on the configured [`hub.set`](https://dev.blues.io/api-reference/notecard-api/hub-requests/#hub-set) `outbound` cadence (default 30 minutes), and treats any `sync:true` alert Note as an immediate interrupt — a saw fires up near the sensor, and the alert leaves the device on a session opened in the next few seconds. The Notecard also owns GNSS: its built-in receiver acquires a site fix on first boot, re-acquires every 4 hours by default, and embeds the last-known fix in every outbound Note. Because the receiver retains a cached fix across power cycles, the first `card.location` response after the enclosure is moved to a new site can still return the previous site's coordinates — the firmware guards against that by treating the first non-zero response after boot as a baseline and flipping `location_valid` to `true` only when a subsequent response carries a newer `time` timestamp. See [Limitations](#10-limitations-and-next-steps). [Environment variables](https://dev.blues.io/guides-and-tutorials/notecard-guides/understanding-environment-variables/) flow back from the [Blues Notehub](https://blues.com/notehub/) cloud service on each inbound sync, so a GC can retune the dB(A) or PM thresholds on the fly without rolling a truck to the site. @@ -115,7 +115,7 @@ The Sunny Buddy is the sole battery charger in this design. Its `BAT` JST port c **PM sensor (Adafruit PMSA003I, I²C):** - Connect a 100 mm Qwiic cable from the Notecarrier CX's Qwiic port to the PMSA003I's STEMMA QT connector. The Qwiic bus carries 3.3V power, GND, SDA, and SCL in a single connector. The PMSA003I's onboard boost circuit handles the internal 5V requirement. -- The PMSA003I must have a clear airflow path to sample ambient air. Mount it near the **inlet vent** on the enclosure wall with its sensing aperture facing the vent opening. Cut a second opening on the opposite or adjacent wall for exhaust — the sensor's internal fan creates a pressure differential that requires both an inlet and an outlet. Fit both openings with IP-rated sintered-PE vent plugs (see BOM) to preserve the enclosure's weather rating. Position the inlet on a sheltered face (bottom or side, not the lid) to minimise direct rain exposure. +- The PMSA003I must have a clear airflow path to sample ambient air. Mount it near the **inlet vent** on the enclosure wall with its sensing aperture facing the vent opening. Cut a second opening on the opposite or adjacent wall for exhaust — the sensor's internal fan creates a pressure differential that requires both an inlet and an outlet. Fit both openings with IP-rated sintered-PE vent plugs (see BOM) to preserve the enclosure's weather rating. Position the inlet on a sheltered face (bottom or side, not the lid) to minimize direct rain exposure. **Sound level sensor (DFRobot SEN0232, analog):** @@ -140,7 +140,7 @@ The Hammond 1554CGY enclosure is ABS plastic, which is RF-transparent — cellul -**Metal enclosure substitution.** If you replace the ABS enclosure with a steel or aluminium alternative, the antennas must exit the box — route u.FL pigtails through IP-rated cable glands to externally mounted antennas, as metal fully blocks both cellular and GPS signals inside. +**Metal enclosure substitution.** If you replace the ABS enclosure with a steel or aluminum alternative, the antennas must exit the box — route u.FL pigtails through IP-rated cable glands to externally mounted antennas, as metal fully blocks both cellular and GPS signals inside. @@ -209,7 +209,7 @@ arduino-cli upload -p /dev/ttyUSB0 --fqbn STMicroelectronics:stm32:Blues:pnum=CY **Sound level — sampled first.** `analogReadResolution(12)` is called once in `setup()` to enable the Cygnet's 12-bit ADC. The SEN0232 output voltage maps linearly to dB(A). The firmware samples at 4 Hz for 15 seconds (60 samples) at the very start of the measurement phase — before `begin_I2C()` is called on the PMSA003I. By taking the dB(A) window before the PM sensor's 30-second warm-up phase begins, the fan's acoustic contribution is bounded to at most the host boot + `setup()` time (~5–15 seconds) in the case where the Qwiic rail is gated during ATTN sleep. Whether that rail is actually gated is carrier-implementation-specific — if it is not, the fan runs continuously and contaminates the measurement regardless of sampling order. For complete, guaranteed acoustic isolation, add a GPIO-controlled load switch to the PMSA003I power line so the fan is definitively off during the sound window. See [Limitations](#10-limitations-and-next-steps). For each of the 60 ADC samples, the firmware maps the output voltage to dB(A) via the SEN0232's linear Vout-to-dB transfer function, applies the `db_cal_offset` calibration bias, then converts to acoustic energy (`10^(dB/10)`) and accumulates the result in a running sum. At the end of the 15-second window the mean energy is converted back to dB(A) via `10·log10(meanEnergy)`, yielding the acoustically correct mean sound pressure level. Averaging in the energy domain matters: a brief 100 dB event carries 100× more intensity than 80 dB background; a simple arithmetic mean of the two dB values gives 90 dB, while the energy-domain mean correctly gives ~97 dB. The 15-second window also acts as a natural noise floor smoother, attenuating single-spike artefacts from vehicles or tools passing the sensor. -**PM sensor — sampled after the sound window.** The PMSA003I requires a 30-second warm-up delay (`PM_WARMUP_MS`) for its fan and laser to stabilise before readings are valid. Whether the Notecarrier CX ATTN sleep path cuts the Qwiic/3.3V rail between wakes is carrier-implementation-specific and not guaranteed — do not rely on implicit rail-gating to power-cycle the PMSA003I between samples. The firmware always applies the full `PM_WARMUP_MS` delay after every successful `begin_I2C()` call, ensuring valid readings regardless of whether the sensor cold-started or was already running. After warm-up, 10 consecutive readings are taken at 1 Hz and averaged. `data.pm25_standard` and `data.pm10_standard` (standard-atmosphere-corrected values) provide a stable, comparable PM metric for trend monitoring — they are more consistent than the `_env` variants, which apply an additional humidity-based environmental correction. Neither output is suited for silica-compliance reporting; see [Limitations](#10-limitations-and-next-steps). Use the Mojo to measure the actual idle current floor during ATTN sleep (§8): if the floor is elevated above the always-on SEN0232 quiescent draw, the PMSA003I is being supplied during sleep and drawing continuous fan current. +**PM sensor — sampled after the sound window.** The PMSA003I requires a 30-second warm-up delay (`PM_WARMUP_MS`) for its fan and laser to stabilize before readings are valid. Whether the Notecarrier CX ATTN sleep path cuts the Qwiic/3.3V rail between wakes is carrier-implementation-specific and not guaranteed — do not rely on implicit rail-gating to power-cycle the PMSA003I between samples. The firmware always applies the full `PM_WARMUP_MS` delay after every successful `begin_I2C()` call, ensuring valid readings regardless of whether the sensor cold-started or was already running. After warm-up, 10 consecutive readings are taken at 1 Hz and averaged. `data.pm25_standard` and `data.pm10_standard` (standard-atmosphere-corrected values) provide a stable, comparable PM metric for trend monitoring — they are more consistent than the `_env` variants, which apply an additional humidity-based environmental correction. Neither output is suited for silica-compliance reporting; see [Limitations](#10-limitations-and-next-steps). Use the Mojo to measure the actual idle current floor during ATTN sleep (§8): if the floor is elevated above the always-on SEN0232 quiescent draw, the PMSA003I is being supplied during sleep and drawing continuous fan current. ### Event payload design @@ -258,13 +258,13 @@ Notehub additionally appends `where_lat`, `where_lon`, `where_location`, and `wh ### Low-power strategy -Even on a solar-powered site, keeping the host asleep between samples reduces average current draw significantly and keeps the enclosure cooler in direct sun. After completing a sample cycle, the host calls `NotePayloadSaveAndSleep`, which serialises the runtime state into Notecard flash (preserving rolling window accumulators, countdown timers, and the last GPS fix) and then triggers `card.attn` to cut host power entirely for `sample_interval_sec` seconds. Between cellular sessions, the Notecard itself idles at ~8–18 µA @ 5V — effectively negligible. The host is awake for approximately 55 seconds per 5-minute cycle (~18% duty cycle), and the cellular session fires once per 30-minute report window. +Even on a solar-powered site, keeping the host asleep between samples reduces average current draw significantly and keeps the enclosure cooler in direct sun. After completing a sample cycle, the host calls `NotePayloadSaveAndSleep`, which serializes the runtime state into Notecard flash (preserving rolling window accumulators, countdown timers, and the last GPS fix) and then triggers `card.attn` to cut host power entirely for `sample_interval_sec` seconds. Between cellular sessions, the Notecard itself idles at ~8–18 µA @ 5V — effectively negligible. The host is awake for approximately 55 seconds per 5-minute cycle (~18% duty cycle), and the cellular session fires once per 30-minute report window. -Sampling cadence and transmit cadence are deliberately decoupled: the firmware samples every 5 minutes but only transmits once per 30 minutes. Actual data consumption depends on sync cadence, signal conditions, Notehub routing behaviour, and alert frequency; validate against Notehub's usage dashboard once the device is deployed in its target environment. +Sampling cadence and transmit cadence are deliberately decoupled: the firmware samples every 5 minutes but only transmits once per 30 minutes. Actual data consumption depends on sync cadence, signal conditions, Notehub routing behavior, and alert frequency; validate against Notehub's usage dashboard once the device is deployed in its target environment. ### Retry and error handling -- The first Notecard transaction in `notecardConfigure()` uses [`sendRequestWithRetry(req, 5)`](https://dev.blues.io/tools-and-sdks/firmware-libraries/arduino-library/) with a 5-second retry window to paper over the cold-boot I²C race between the Cygnet and the Notecard. Immediately after, `applyCardConfig()` re-issues `hub.set` with `requestAndResponse` because `state.lastReportMin` is initialised to 0 on first boot — this guarantees the outbound cadence is confirmed with a response-checked request even if `notecardConfigure()` suffered a transient failure. `product` is included in every `hub.set` from `applyCardConfig()` so the device can recover from a failed first-boot provisioning on any subsequent wake without a hard reset. +- The first Notecard transaction in `notecardConfigure()` uses [`sendRequestWithRetry(req, 5)`](https://dev.blues.io/tools-and-sdks/firmware-libraries/arduino-library/) with a 5-second retry window to paper over the cold-boot I²C race between the Cygnet and the Notecard. Immediately after, `applyCardConfig()` re-issues `hub.set` with `requestAndResponse` because `state.lastReportMin` is initialized to 0 on first boot — this guarantees the outbound cadence is confirmed with a response-checked request even if `notecardConfigure()` suffered a transient failure. `product` is included in every `hub.set` from `applyCardConfig()` so the device can recover from a failed first-boot provisioning on any subsequent wake without a hard reset. - `readPmSensor()` counts valid reads independently and returns `false` if zero valid readings are obtained (e.g., sensor not detected on I²C). The calling code in `setup()` guards against adding a -1.0 reading to the accumulators. - `env.get` and `card.location` responses are NULL-checked before use; a failed response is silently skipped so a transient I²C error on one wake doesn't corrupt the persistent state. - Alert de-duplication via a 30-minute per-type cooldown (`ALERT_COOLDOWN_SEC`) prevents a sustained high-dust or high-noise condition from generating continuous alerts. One alert per type per 30 minutes is enough to notify the safety officer; it's not enough to flood their inbox. @@ -296,7 +296,7 @@ notecard.sendRequest(req); ### Key code snippet 2 — immediate-sync alert -`sync:true` tells the Notecard to bypass the outbound window and open a cellular session right now. This is the mechanism that gets a dust spike off the device within seconds of the threshold crossing. `full:true` opts the Note out of the [omitempty rule](https://dev.blues.io/notecard/notecard-walkthrough/low-bandwidth-design/#use-of-in-templates) that templated Notefiles otherwise apply on Notehub serialisation — without it, `location_valid: false` (the explicit "GPS not yet confirmed at this site" signal) and any zero-valued `lat`/`lon` would be silently stripped from the body that downstream consumers receive. The same `full:true` flag is set on the `env_summary.qo` `note.add` so that `pm_samples: 0` (the companion sentinel to `pm25_avg/pm10_avg = -9999.0` when every PM read in the window failed) survives serialisation. +`sync:true` tells the Notecard to bypass the outbound window and open a cellular session right now. This is the mechanism that gets a dust spike off the device within seconds of the threshold crossing. `full:true` opts the Note out of the [omitempty rule](https://dev.blues.io/notecard/notecard-walkthrough/low-bandwidth-design/#use-of-in-templates) that templated Notefiles otherwise apply on Notehub serialization — without it, `location_valid: false` (the explicit "GPS not yet confirmed at this site" signal) and any zero-valued `lat`/`lon` would be silently stripped from the body that downstream consumers receive. The same `full:true` flag is set on the `env_summary.qo` `note.add` so that `pm_samples: 0` (the companion sentinel to `pm25_avg/pm10_avg = -9999.0` when every PM read in the window failed) survives serialization. ```cpp J *req = notecard.newRequest("note.add"); @@ -352,13 +352,13 @@ Every 5 minutes (default), the Cygnet wakes, reads both sensors (sound first, th **First-light sanity check — two phases.** -**Phase 1: USB bench (boot and I²C validation).** Connect the Notecarrier CX to a computer via USB-C, with no LiPo connected. In USB mode the Cygnet stays powered continuously; `card.attn` cannot cut the host rail because there is no ATTN-controlled LiPo path. `setup()` executes once, running one full sample cycle including the 30-second PM warm-up. Because `NotePayloadSaveAndSleep` cannot cut host power in USB-only mode, it returns without sleeping and `loop()` takes over. `loop()` repeats indefinitely, delaying between cycles and executing fresh sample cycles without any re-flashing. Open the serial monitor (115200 baud) to watch debug output. Expect to see: Notecard I²C init, `hub.set`, `note.template`, `env.get` requests, PM warm-up and sensor reads, and sound-level ADC samples. By default you will **not** see a summary `note.add` after the first cycle — the report countdown initialises to 1800 seconds (30 minutes). After approximately six cycles (~30 minutes of elapsed wall-clock time), the countdown fires and an `env_summary.qo` Note is queued. To verify the alert path: (a) Set `pm25_alert_ug_m3` to `1.0` in Notehub Fleet Environment Variables; (b) Wait for the device's next inbound sync (~30 minutes default, or force one with `{"req":"hub.sync"}` in the in-browser serial terminal); (c) The next sample cycle fires `pm25_high` immediately. Reset the variable to `35.0` afterward. +**Phase 1: USB bench (boot and I²C validation).** Connect the Notecarrier CX to a computer via USB-C, with no LiPo connected. In USB mode the Cygnet stays powered continuously; `card.attn` cannot cut the host rail because there is no ATTN-controlled LiPo path. `setup()` executes once, running one full sample cycle including the 30-second PM warm-up. Because `NotePayloadSaveAndSleep` cannot cut host power in USB-only mode, it returns without sleeping and `loop()` takes over. `loop()` repeats indefinitely, delaying between cycles and executing fresh sample cycles without any re-flashing. Open the serial monitor (115200 baud) to watch debug output. Expect to see: Notecard I²C init, `hub.set`, `note.template`, `env.get` requests, PM warm-up and sensor reads, and sound-level ADC samples. By default you will **not** see a summary `note.add` after the first cycle — the report countdown initializes to 1800 seconds (30 minutes). After approximately six cycles (~30 minutes of elapsed wall-clock time), the countdown fires and an `env_summary.qo` Note is queued. To verify the alert path: (a) Set `pm25_alert_ug_m3` to `1.0` in Notehub Fleet Environment Variables; (b) Wait for the device's next inbound sync (~30 minutes default, or force one with `{"req":"hub.sync"}` in the in-browser serial terminal); (c) The next sample cycle fires `pm25_high` immediately. Reset the variable to `35.0` afterward. **Phase 2: LiPo/solar (repeated-sampling validation).** Disconnect USB-C. Wire the Sunny Buddy LOAD to the Notecarrier CX LiPo JST and connect a charged LiPo (see §4 power chain). On Notecarrier CX, ATTN-controlled sleep is already wired to the Cygnet host power rail — no additional wiring is required. The host now wakes every `sample_interval_sec` (default 5 minutes), runs one full `setup()` sample cycle, saves state, and sleeps. Expect `env_summary.qo` to appear in Notehub approximately 30 minutes after first power-on (six 5-minute cycles). If the countdown fires but no Note appears, check `hub.status` in the blues.dev In-Browser Terminal for any cellular registration errors. **Simulating an alert.** Drop `pm25_alert_ug_m3` to `1.0` in the Fleet environment variables. The next inbound sync pulls the updated value, the next sample cycle fires `pm25_high`, and the alert should appear in Notehub within a cellular session establishment window (typically 15–60 seconds). Reset the variable to `35.0` after testing. -**Using Mojo to validate power behavior.** The Notecard's published idle figure is ~8–18 µA @ 5V between cellular sessions (see the [low-power design guide](https://dev.blues.io/notecard/notecard-walkthrough/low-power-firmware-design/) for the authoritative measured numbers). Active cellular transmit averages ~250 mA. The Cygnet, when powered off by `card.attn`, draws essentially zero from the LiPo rail. The SEN0232 is powered from the `V+` header pin (raw LiPo voltage), which is **not** gated by the ATTN sleep path — the sensor's op-amp circuitry draws a continuous quiescent current; measure this floor directly with the Mojo to characterise your specific build. +**Using Mojo to validate power behavior.** The Notecard's published idle figure is ~8–18 µA @ 5V between cellular sessions (see the [low-power design guide](https://dev.blues.io/notecard/notecard-walkthrough/low-power-firmware-design/) for the authoritative measured numbers). Active cellular transmit averages ~250 mA. The Cygnet, when powered off by `card.attn`, draws essentially zero from the LiPo rail. The SEN0232 is powered from the `V+` header pin (raw LiPo voltage), which is **not** gated by the ATTN sleep path — the sensor's op-amp circuitry draws a continuous quiescent current; measure this floor directly with the Mojo to characterize your specific build. The [Mojo](https://dev.blues.io/datasheets/mojo-datasheet/) sits inline between the Sunny Buddy `LOAD` output and the Notecarrier CX LiPo JST connector. Its LTC2959 coulomb counter (Analog Devices) accumulates the charge drawn from the LiPo regardless of whether anything is connected to its Qwiic port. To read the accumulated mAh, connect the second Qwiic cable from the PMSA003I's second STEMMA QT port to the Mojo's Qwiic port (the bench daisy-chain described in §4). With Notecard firmware v8.1.3 or later, the Notecard auto-detects the Mojo on the shared I²C bus and periodically logs energy data (including `milliamp_hours`) to `_log.qo` Notes; you can also issue `{"req":"card.power"}` from the Notecard's in-browser serial terminal for a one-shot bench reading. The firmware in this project does not call `card.power`. See the §9 extension Note for the path to include it in the summary payload. @@ -383,7 +383,7 @@ This reference design is an area monitor, deliberately — not a personal dosime The boundaries below come with the choice to build an area monitor rather than a personal dosimeter — they show exactly where this design complements existing compliance work and where a production deployment will need to bring more. -**PM sensor fan acoustic contamination.** The PMSA003I's fan runs whenever its Qwiic 3.3V supply is present. Whether that supply is cut during ATTN sleep is carrier-implementation-specific: if it is not cut, the fan runs continuously and contaminates the dB(A) channel throughout every measurement cycle. If it is cut, the fan restarts when the host wakes and has been running for the host boot + `setup()` time (~5–15 seconds) before the 15-second sound window begins. The firmware samples sound before `begin_I2C()` and the PM warm-up phase, minimising (but not eliminating) contamination in the gated-rail case. **Before deploying, measure the enclosure's self-noise floor with the PM sensor powered and spinning, using a calibrated reference sound-level meter placed at the acoustic vent opening. If the enclosure self-noise floor exceeds 5 dB(A) above the ambient floor, the enclosure design is contaminating the dB(A) channel.** The definitive fix — regardless of carrier topology — is to add a GPIO-controlled load switch to the PMSA003I's Qwiic power line so the fan is definitively off during the entire sound-sample window. A load switch also removes any PMSA003I fan current contribution from the ATTN sleep floor, making power budgeting unambiguous. +**PM sensor fan acoustic contamination.** The PMSA003I's fan runs whenever its Qwiic 3.3V supply is present. Whether that supply is cut during ATTN sleep is carrier-implementation-specific: if it is not cut, the fan runs continuously and contaminates the dB(A) channel throughout every measurement cycle. If it is cut, the fan restarts when the host wakes and has been running for the host boot + `setup()` time (~5–15 seconds) before the 15-second sound window begins. The firmware samples sound before `begin_I2C()` and the PM warm-up phase, minimizing (but not eliminating) contamination in the gated-rail case. **Before deploying, measure the enclosure's self-noise floor with the PM sensor powered and spinning, using a calibrated reference sound-level meter placed at the acoustic vent opening. If the enclosure self-noise floor exceeds 5 dB(A) above the ambient floor, the enclosure design is contaminating the dB(A) channel.** The definitive fix — regardless of carrier topology — is to add a GPIO-controlled load switch to the PMSA003I's Qwiic power line so the fan is definitively off during the entire sound-sample window. A load switch also removes any PMSA003I fan current contribution from the ATTN sleep floor, making power budgeting unambiguous. **5-minute sampling cadence can miss transient events.** The firmware wakes and samples once per `sample_interval_sec` (default 5 minutes). A high-dust burst or noise spike that begins and ends entirely between two consecutive sample windows is not captured — the sensor never sees it. During task-intensive operations such as concrete demolition, jackhammering, dry cutting, or grinding, consider reducing `sample_interval_sec` to 60–120 seconds via the Notehub environment variable to narrow the detection gap. Note that more frequent sampling reduces LiPo autonomy proportionally and increases data consumption. For tasks where any transient spike matters (e.g., a saw that only runs for 30 seconds), a wearable personal dosimeter worn by the worker is the only reliable capture method; the area monitor cannot substitute for it in those scenarios. diff --git a/63-construction-equipment-anti-theft-tracker-with-immobilizer/README.md b/63-construction-equipment-anti-theft-tracker-with-immobilizer/README.md index 625c5b0e..a39fbe45 100644 --- a/63-construction-equipment-anti-theft-tracker-with-immobilizer/README.md +++ b/63-construction-equipment-anti-theft-tracker-with-immobilizer/README.md @@ -12,11 +12,11 @@ This project is a [loss prevention](https://blues.com/loss-prevention/) referenc ## 1. Project Overview -**The problem.** Construction equipment theft is a serious, costly, and chronically underreported problem. A skid steer that costs $60,000 to replace can be driven onto a flatbed and hauled off in under ten minutes. A light tower or portable generator can be gone before the morning crew arrives. These aren't smash-and-grab events — the equipment is large, identifiable, and completely exposed on a site that often goes unwatched overnight. Law enforcement recovery rates for heavy equipment are low; the stolen unit frequently ends up at a rural stash yard, stripped, or loaded into a shipping container for export. A rural stash yard or a shipping container is exactly where cellular telemetry that depends on urban coverage goes dark. +**The problem.** Construction equipment theft is a serious, costly, and chronically underreported problem. A skid steer that costs $60,000 to replace can be driven onto a flatbed and hauled off in under ten minutes. A light tower or portable generator can be gone before the morning crew arrives. These aren't smash-and-grab events: the equipment is large, identifiable, and completely exposed on a site that often goes unwatched overnight. Law enforcement recovery rates for heavy equipment are low; the stolen unit frequently ends up at a rural stash yard, stripped, or loaded into a shipping container for export. A rural stash yard or a shipping container is exactly where cellular telemetry that depends on urban coverage goes dark. -The result is an industry that leans heavily on equipment marking, insurance claims, and post-theft police reports. What's mostly missing is a device that provides real-time location during a theft in progress *and* can physically disable the equipment before it leaves the region — all without depending on an infrastructure that may not exist at the job site or at the final stash location. +The result is an industry that leans heavily on equipment marking, insurance claims, and post-theft police reports. What's mostly missing is a device that provides real-time location during a theft in progress *and* can physically disable the equipment before it leaves the region, all without depending on an infrastructure that may not exist at the job site or at the final stash location. -This project is that device. It monitors GPS location against a configurable job-site geofence, watches for unexpected after-hours motion, and accepts a remote immobilizer command from the [Blues Notehub](https://blues.com/notehub/) cloud service that stages a relay to cut the ignition circuit on the thief's next key-on attempt — a polled, staged proof-of-concept immobilizer rather than a continuously-held cut, with the limitations that implies (see §11). The whole stack — GPS, cellular, and satellite fallback — is contained in a single Blues Notecard for Skylo installed in a weatherproof enclosure that runs indefinitely on a LiPo battery topped off by a small solar panel. +This project is that device. It monitors GPS location against a configurable job-site geofence, watches for unexpected after-hours motion, and accepts a remote immobilizer command from the [Blues Notehub](https://blues.com/notehub/) cloud service that stages a relay to cut the ignition circuit on the thief's next key-on attempt. This is a polled, staged proof-of-concept immobilizer rather than a continuously-held cut, with the limitations that implies (see §11). The whole stack — GPS, cellular, and satellite fallback — is contained in a single Blues Notecard for Skylo installed in a weatherproof enclosure that runs indefinitely on a LiPo battery topped off by a small solar panel. **Why Notecard.** Construction sites have no WiFi. Even if a site happens to have a hotspot, requiring site IT coordination for a security device defeats the purpose. Cellular works for the vast majority of scenarios, but a stolen skid steer doesn't stay parked in a well-covered urban area. It ends up in a rural equipment yard, a metal barn, or a shipping container at a port. That's the scenario where cellular alone fails and satellite becomes the difference between a recovered asset and a total write-off. Notecard for Skylo ([NOTE-NBGLWX](https://dev.blues.io/datasheets/notecard-datasheet/note-nbglwx/)) handles all three radio paths — LTE-M/NB-IoT cellular, WiFi (where available), and Skylo satellite — in a single M.2 module, without any firmware branching. Global roaming and satellite failover are not optional extras for this use case; they are the core differentiators. @@ -28,13 +28,13 @@ This project is that device. It monitors GPS location against a configurable job ![System architecture: equipment signals → Notecarrier CX with Cygnet host and Notecard for Skylo → LTE-M/NB-IoT + Skylo satellite → Notehub → security and fleet-management routes](diagrams/01-system-architecture.svg) -**Device-side responsibilities.** The Cygnet STM32 host in the [Notecarrier CX](https://dev.blues.io/datasheets/notecarrier-datasheet/notecarrier-cx-v1-7/) spends almost all of its time asleep — the whole power budget depends on it. When the configurable wake timer fires, the firmware reads ignition state from a voltage divider on the 12 V ignition line, polls the Notecard's built-in accelerometer via [`card.motion`](https://dev.blues.io/api-reference/notecard-api/card-requests/#card-motion), and pulls the most recent GPS fix via [`card.location`](https://dev.blues.io/api-reference/notecard-api/card-requests/#card-location). It then runs three checks in order: is the position outside the Haversine-evaluated job-site geofence; is this the after-hours window; and is there a fresh immobilize command sitting in the inbound queue? Any heartbeat or alert Notes ride to the Notecard over I²C using the `note-arduino` request helpers, and the runtime state — geofence center, immobilizer stage, cadence parameters — is serialized to Notecard flash before sleep and rehydrated on the next wake via [`NotePayloadSaveAndSleep`](https://dev.blues.io/guides-and-tutorials/notecard-guides/attention-pin-guide/) / `NotePayloadRetrieveAfterSleep`. +**Device-side responsibilities.** The Cygnet STM32 host in the [Notecarrier CX](https://dev.blues.io/datasheets/notecarrier-datasheet/notecarrier-cx-v1-7/) spends almost all of its time asleep. The whole power budget depends on it. When the configurable wake timer fires, the firmware reads ignition state from a voltage divider on the 12 V ignition line, polls the Notecard's built-in accelerometer via [`card.motion`](https://dev.blues.io/api-reference/notecard-api/card-requests/#card-motion), and pulls the most recent GPS fix via [`card.location`](https://dev.blues.io/api-reference/notecard-api/card-requests/#card-location). It then runs three checks in order: is the position outside the Haversine-evaluated job-site geofence; is this the after-hours window; and is there a fresh immobilize command sitting in the inbound queue? Any heartbeat or alert Notes ride to the Notecard over I²C using the `note-arduino` request helpers, and the runtime state — geofence center, immobilizer stage, cadence parameters — is serialized to Notecard flash before sleep and rehydrated on the next wake via [`NotePayloadSaveAndSleep`](https://dev.blues.io/guides-and-tutorials/notecard-guides/attention-pin-guide/) / `NotePayloadRetrieveAfterSleep`. -**Notecard responsibilities.** Notecard for Skylo is doing most of the connectivity work behind the scenes. It buffers queued [Notes](https://dev.blues.io/api-reference/glossary/#note) in on-device flash, opens a cellular or satellite session on the [`hub.set`](https://dev.blues.io/api-reference/notecard-api/hub-requests/#hub-set) `outbound` cadence, and treats any `sync:true` alert Note as an immediate uplink — the difference between an alert reaching the operator in seconds and the equipment crossing a county line. The same module also owns the GPS receiver, the accelerometer, the real-time clock, and the battery-voltage ADC, so no external sensors are needed. [Environment variables](https://dev.blues.io/guides-and-tutorials/notecard-guides/understanding-environment-variables/) flow back from Notehub on each inbound sync — a fleet manager can retune the geofence radius or the after-hours window from a browser, and the firmware automatically reissues `hub.set` and `card.location.mode` so all three Notecard cadences stay aligned with the new wake interval. +**Notecard responsibilities.** Notecard for Skylo is doing most of the connectivity work behind the scenes. It buffers queued [Notes](https://dev.blues.io/api-reference/glossary/#note) in on-device flash, opens a cellular or satellite session on the [`hub.set`](https://dev.blues.io/api-reference/notecard-api/hub-requests/#hub-set) `outbound` cadence, and treats any `sync:true` alert Note as an immediate uplink: the difference between an alert reaching the operator in seconds and the equipment crossing a county line. The same module also owns the GPS receiver, the accelerometer, the real-time clock, and the battery-voltage ADC, so no external sensors are needed. [Environment variables](https://dev.blues.io/guides-and-tutorials/notecard-guides/understanding-environment-variables/) flow back from Notehub on each inbound sync. A fleet manager can retune the geofence radius or the after-hours window from a browser, and the firmware automatically reissues `hub.set` and `card.location.mode` so all three Notecard cadences stay aligned with the new wake interval. **Notehub responsibilities.** [Notehub](https://notehub.io) ingests every event from every device — whether it arrived over cellular or Skylo — stores it, and applies the project's [routes](https://dev.blues.io/notehub/notehub-walkthrough/#routing-data-with-notehub). Alert Notes (`alert.qo`) and tracker heartbeats (`tracker.qo`) land in separate Notefiles, so the security platform that needs alerts the moment they happen and the fleet-management store that needs position history can be served from the same device with no filter logic in between. Operators stage an `immobilize` or `release` command by posting a Note to the device's `immobilize.qi` inbound queue from the Notehub UI or via the [Notehub REST API](https://dev.blues.io/api-reference/notehub-api/api-introduction/). [Smart Fleets](https://dev.blues.io/notehub/notehub-walkthrough/#using-smart-fleet-rules) push site-level geofence and after-hours defaults to every machine on a job site at once. -**Routing to the cloud (high level).** Notehub supports HTTP, MQTT, AWS IoT, Azure, GCP, Snowflake, and 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 ships no specific downstream endpoint. +**Routing to the cloud (high level).** Notehub supports HTTP, MQTT, AWS IoT, Azure, GCP, Snowflake, and 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 ships no specific downstream endpoint. ## 3. Technical Summary @@ -311,13 +311,13 @@ Alert types: ### Low-power strategy -The Cygnet host and the Notecard are both put to sleep between sensing cycles. At the end of each wake, the firmware calls `NotePayloadSaveAndSleep`, which serializes the `AppState` struct to Notecard flash as a base64 payload and then issues [`card.attn`](https://dev.blues.io/api-reference/notecard-api/card-requests/#card-attn) with `mode:sleep` — physically cutting the Cygnet's power via the Notecarrier CX's ATTN-controlled power rail. The Notecard itself enters its own [low-power idle state](https://dev.blues.io/notecard/notecard-walkthrough/low-power-firmware-design/) (~8–18 µA @ 5V) between cellular sync windows. After `sleep_sec` seconds, the ATTN pin goes HIGH and the Cygnet's power is restored; `setup()` runs fresh and `NotePayloadRetrieveAfterSleep` rehydrates the state struct. +The Cygnet host and the Notecard are both put to sleep between sensing cycles. At the end of each wake, the firmware calls `NotePayloadSaveAndSleep`, which serializes the `AppState` struct to Notecard flash as a base64 payload and then issues [`card.attn`](https://dev.blues.io/api-reference/notecard-api/card-requests/#card-attn) with `mode:sleep`, physically cutting the Cygnet's power via the Notecarrier CX's ATTN-controlled power rail. The Notecard itself enters its own [low-power idle state](https://dev.blues.io/notecard/notecard-walkthrough/low-power-firmware-design/) (~8–18 µA @ 5V) between cellular sync windows. After `sleep_sec` seconds, the ATTN pin goes HIGH and the Cygnet's power is restored; `setup()` runs fresh and `NotePayloadRetrieveAfterSleep` rehydrates the state struct. -The sleep duration adapts to context: 2 minutes during after-hours (fast theft detection), 5 minutes while moving (active tracking), 1 hour during business hours at rest (background monitoring, and worst-case geofence-detection latency while parked). The after-hours wake interval is intentionally shorter than the heartbeat emission interval — the device wakes every 2 minutes to check for alerts and inbound commands, but heartbeat Notes queue at the stationary or moving rate regardless of time of day. This keeps the overnight Note volume consistent with daytime operation while still catching a theft event within the scan window. **Sampling/queuing cadence and transmission cadence are always distinct.** Heartbeat Notes are queued by the host into the Notecard's local flash, then transmitted to Notehub on the next outbound sync session — which fires at the `hub.set outbound` interval (set by `outbound_min`, default 240 minutes). A 5-minute moving sample rate means the Notecard accumulates a heartbeat every 5 minutes while in motion, but those records are batch-transmitted on the next outbound session unless an alert happens to force a `sync:true` flush first. Only `alert.qo` Notes (with `sync:true`) bypass the outbound window and trigger an immediate uplink sync. Separately, the Notecard independently manages its own **inbound sync sessions** — these are cellular connections the Notecard initiates on its own schedule to pull queued commands and updated environment variables from Notehub. The inbound cadence is context-aware: when the equipment is parked and daytime, the interval matches `heartbeat_stopped_min` (default 60 minutes, set via `hub.set inbound`); when after-hours or moving, it shortens to `inbound_min` (default 4 minutes). These inbound sessions are Notecard-driven and occur regardless of whether the Cygnet host is currently awake. The host's 2-minute after-hours wake cycle and the Notecard's inbound cellular cadence are independent of each other and tuned via separate parameters (`heartbeat_afterhours_min` and `inbound_min`, respectively), so daytime inbound sessions match the host wake cadence rather than running dozens of times per hour against a parked asset. Both cadences must be accounted for when sizing the energy budget (see §9). +The sleep duration adapts to context: 2 minutes during after-hours (fast theft detection), 5 minutes while moving (active tracking), 1 hour during business hours at rest (background monitoring, and worst-case geofence-detection latency while parked). The after-hours wake interval is intentionally shorter than the heartbeat emission interval: the device wakes every 2 minutes to check for alerts and inbound commands, but heartbeat Notes queue at the stationary or moving rate regardless of time of day. This keeps the overnight Note volume consistent with daytime operation while still catching a theft event within the scan window. **Sampling/queuing cadence and transmission cadence are always distinct.** Heartbeat Notes are queued by the host into the Notecard's local flash, then transmitted to Notehub on the next outbound sync session, which fires at the `hub.set outbound` interval (set by `outbound_min`, default 240 minutes). A 5-minute moving sample rate means the Notecard accumulates a heartbeat every 5 minutes while in motion, but those records are batch-transmitted on the next outbound session unless an alert happens to force a `sync:true` flush first. Only `alert.qo` Notes (with `sync:true`) bypass the outbound window and trigger an immediate uplink sync. Separately, the Notecard independently manages its own **inbound sync sessions**: these are cellular connections the Notecard initiates on its own schedule to pull queued commands and updated environment variables from Notehub. The inbound cadence is context-aware: when the equipment is parked and daytime, the interval matches `heartbeat_stopped_min` (default 60 minutes, set via `hub.set inbound`); when after-hours or moving, it shortens to `inbound_min` (default 4 minutes). These inbound sessions are Notecard-driven and occur regardless of whether the Cygnet host is currently awake. The host's 2-minute after-hours wake cycle and the Notecard's inbound cellular cadence are independent of each other and tuned via separate parameters (`heartbeat_afterhours_min` and `inbound_min`, respectively), so daytime inbound sessions match the host wake cadence rather than running dozens of times per hour against a parked asset. Both cadences must be accounted for when sizing the energy budget (see §9). -**Env-var cadence retuning scope.** When an operator changes any cadence variable (`heartbeat_moving_min`, `heartbeat_stopped_min`, `heartbeat_afterhours_min`, `inbound_min`, or `outbound_min`) via Notehub, the firmware detects the change via the `env.get` delta check and calls `applyHubCadence()`, which reissues `hub.set` (outbound and inbound windows) and `card.location.mode` (GNSS acquisition seconds, set to `heartbeat_moving_s`). `applyHubCadence()` is also called immediately when the motion or after-hours context transitions, so the Notecard's inbound window switches between the short active-monitoring interval (`inbound_min`) and the long parked interval (`heartbeat_stopped_min`) without waiting for a future env-var change. The outbound window uses `outbound_s` (set by `outbound_min`, default 240 minutes) — decoupled from the host wake interval. Env-var changes do not affect `card.motion.mode` (accelerometer sensitivity and bucket size) — those are set at cold boot only and require a firmware update to change. +**Env-var cadence retuning scope.** When an operator changes any cadence variable (`heartbeat_moving_min`, `heartbeat_stopped_min`, `heartbeat_afterhours_min`, `inbound_min`, or `outbound_min`) via Notehub, the firmware detects the change via the `env.get` delta check and calls `applyHubCadence()`, which reissues `hub.set` (outbound and inbound windows) and `card.location.mode` (GNSS acquisition seconds, set to `heartbeat_moving_s`). `applyHubCadence()` is also called immediately when the motion or after-hours context transitions, so the Notecard's inbound window switches between the short active-monitoring interval (`inbound_min`) and the long parked interval (`heartbeat_stopped_min`) without waiting for a future env-var change. The outbound window uses `outbound_s` (set by `outbound_min`, default 240 minutes), decoupled from the host wake interval. Env-var changes do not affect `card.motion.mode` (accelerometer sensitivity and bucket size); those are set at cold boot only and require a firmware update to change. -The GPS module is motion-gated at the Notecard level — it only activates after sustained accelerometer activity, keeping the GNSS radio silent during the many hours per day the equipment is parked and not moving. +The GPS module is motion-gated at the Notecard level: it only activates after sustained accelerometer activity, keeping the GNSS radio silent during the many hours per day the equipment is parked and not moving. ### Retry and error handling @@ -500,21 +500,21 @@ Satellite session validation requires outdoor antenna placement with clear sky v ## 11. Limitations and Next Steps -This POC demonstrates the control path, the data path, and the satellite fallback — but it deliberately stops short of being a production security device. A working immobilizer for a deployed fleet wants a latching relay that survives sleep gaps, a transient-protected ignition front end that can handle automotive load dump, and interrupt-driven wake that catches a key-on edge inside the next 100 ms rather than the next two minutes. Those are the items below, framed as the scope boundaries of the reference design and the engineering work that turns it into a production product. +This POC demonstrates the control path, the data path, and the satellite fallback, but it deliberately stops short of being a production security device. A working immobilizer for a deployed fleet wants a latching relay that survives sleep gaps, a transient-protected ignition front end that can handle automotive load dump, and interrupt-driven wake that catches a key-on edge inside the next 100 ms rather than the next two minutes. Those are the items below, framed as the scope boundaries of the reference design and the engineering work that turns it into a production product. ### Simplified for the POC -The boundaries below are the scope choices of the reference design — each marks where the POC stops short of a production security device and points to the engineering work that closes the gap. +The boundaries below are the scope choices of the reference design: each marks where the POC stops short of a production security device and points to the engineering work that closes the gap. -**Staged, polled, edge-triggered immobilizer, not a continuously-held cut.** The immobilizer in this POC is a _next-wake / next-key-on-edge_ design. `NotePayloadSaveAndSleep` physically cuts the Cygnet's power during the sleep window, so the relay coil de-energizes on every sleep interval and the NC contact re-closes — briefly restoring the ignition circuit. The Cygnet re-asserts the relay only when it wakes and reads `immobilized = true`. For the default 2-minute after-hours cycle, the relay is active for only a few seconds every 2 minutes; a determined thief who turns the key during the sleep gap can crank the engine. Additionally, the relay only fires on an OFF→ON ignition edge — the previous wake must have observed ignition OFF and the current wake must observe ignition ON. If the equipment is already running when the immobilize command is staged, the firmware deliberately holds off until the next key cycle (this avoids cutting the starter circuit while the engine is actively running, per the safety guidance in §5). If the thief cycles the key fully between two Cygnet wakes (OFF→ON→OFF inside one sleep window), the firing edge is missed entirely until the next OFF→ON transition the Cygnet observes. This is a proof-of-concept staging mechanism. Production deployments require a **latching (bistable) relay** that holds its contact state with no continuous coil power and survives Cygnet sleep, power cuts, and wiring interruptions. See Production Next Steps below. +**Staged, polled, edge-triggered immobilizer, not a continuously-held cut.** The immobilizer in this POC is a _next-wake / next-key-on-edge_ design. `NotePayloadSaveAndSleep` physically cuts the Cygnet's power during the sleep window, so the relay coil de-energizes on every sleep interval and the NC contact re-closes, briefly restoring the ignition circuit. The Cygnet re-asserts the relay only when it wakes and reads `immobilized = true`. For the default 2-minute after-hours cycle, the relay is active for only a few seconds every 2 minutes; a determined thief who turns the key during the sleep gap can crank the engine. Additionally, the relay only fires on an OFF→ON ignition edge: the previous wake must have observed ignition OFF and the current wake must observe ignition ON. If the equipment is already running when the immobilize command is staged, the firmware deliberately holds off until the next key cycle (this avoids cutting the starter circuit while the engine is actively running, per the safety guidance in §5). If the thief cycles the key fully between two Cygnet wakes (OFF→ON→OFF inside one sleep window), the firing edge is missed entirely until the next OFF→ON transition the Cygnet observes. This is a proof-of-concept staging mechanism. Production deployments require a **latching (bistable) relay** that holds its contact state with no continuous coil power and survives Cygnet sleep, power cuts, and wiring interruptions. See Production Next Steps below. -**Ignition-sense front end is POC-only — no transient protection.** The bare 33 kΩ / 10 kΩ voltage divider provides no protection against automotive electrical transients. Load-dump events on generator sets can produce transients 40–200 V above nominal 12 V; starter-motor switching creates fast inductive spikes on the battery rail. Both can exceed the Cygnet GPIO absolute maximum and damage the MCU. A production design must add a TVS diode (e.g. 15 V unidirectional, placed before the high-side divider resistor) and an RC low-pass filter (e.g. 1 kΩ + 100 nF at the A2 node) as a minimum, or use a properly isolated sensing front end. The relay-side vehicle interface carries the same risk; the 1N4007 flyback diode protects the MOSFET drain from the relay coil's inductive spike, but does not protect the 12 V feed from upstream transients — the inline fuse in the BOM addresses overcurrent only. +**Ignition-sense front end is POC-only: no transient protection.** The bare 33 kΩ / 10 kΩ voltage divider provides no protection against automotive electrical transients. Load-dump events on generator sets can produce transients 40–200 V above nominal 12 V; starter-motor switching creates fast inductive spikes on the battery rail. Both can exceed the Cygnet GPIO absolute maximum and damage the MCU. A production design must add a TVS diode (e.g. 15 V unidirectional, placed before the high-side divider resistor) and an RC low-pass filter (e.g. 1 kΩ + 100 nF at the A2 node) as a minimum, or use a properly isolated sensing front end. The relay-side vehicle interface carries the same risk; the 1N4007 flyback diode protects the MOSFET drain from the relay coil's inductive spike, but does not protect the 12 V feed from upstream transients. The inline fuse in the BOM addresses overcurrent only. -**No interrupt-driven ignition sense.** The firmware polls ignition state on each wake. A thief who turns the key and drives away within the 2-minute window between wakes will have a head start before the `ignition_on_immobilized` event fires. A hardware interrupt from the ATTN pin triggered by the ignition-sense line would wake the Cygnet instantly on key-on — the Notecarrier CX ATTN wiring and the `card.attn` `auxgpio` mode support this pattern but it is not implemented in this POC. +**No interrupt-driven ignition sense.** The firmware polls ignition state on each wake. A thief who turns the key and drives away within the 2-minute window between wakes will have a head start before the `ignition_on_immobilized` event fires. A hardware interrupt from the ATTN pin triggered by the ignition-sense line would wake the Cygnet instantly on key-on. The Notecarrier CX ATTN wiring and the `card.attn` `auxgpio` mode support this pattern, but it is not implemented in this POC. **Inbound commands require cellular.** The Skylo satellite link provides primarily uplink (device-to-cloud) data. `immobilize.qi` commands from Notehub to the device require a cellular or WiFi connection to be delivered. If the equipment is already in a dead zone, the operator must wait for cellular to be restored before the command arrives. -**Geofence decisions use cached location data, and daytime detection latency is bounded by `heartbeat_stopped_min`.** The firmware calls `card.location` to read the Notecard's most recently cached GNSS fix — it does not wait for a fresh acquisition. The cached fix age is bounded by the GNSS acquisition cadence (`card.location.mode seconds`, default `heartbeat_moving_s` = 5 minutes), so one or two after-hours wake cycles may evaluate the geofence against the same stale fix before GNSS re-acquires. A geofence breach alert will not appear until both (a) the host wakes and (b) the Notecard has a sufficiently fresh fix that places the device outside the radius. During business hours, when the host wakes every 60 minutes (default), the worst-case detection latency for a theft that starts from a parked state is approximately 60 minutes plus up to 5 minutes of GNSS fix lag. Every outbound Note includes `fix_age_s` (seconds ≥ 0, or `-1` when `card.time` is unavailable) so operators can assess the staleness of each geofence decision. +**Geofence decisions use cached location data, and daytime detection latency is bounded by `heartbeat_stopped_min`.** The firmware calls `card.location` to read the Notecard's most recently cached GNSS fix; it does not wait for a fresh acquisition. The cached fix age is bounded by the GNSS acquisition cadence (`card.location.mode seconds`, default `heartbeat_moving_s` = 5 minutes), so one or two after-hours wake cycles may evaluate the geofence against the same stale fix before GNSS re-acquires. A geofence breach alert will not appear until both (a) the host wakes and (b) the Notecard has a sufficiently fresh fix that places the device outside the radius. During business hours, when the host wakes every 60 minutes (default), the worst-case detection latency for a theft that starts from a parked state is approximately 60 minutes plus up to 5 minutes of GNSS fix lag. Every outbound Note includes `fix_age_s` (seconds ≥ 0, or `-1` when `card.time` is unavailable) so operators can assess the staleness of each geofence decision. **Geofence is a circle.** The firmware uses a Haversine-computed circle around a single center point. Irregular job-site boundaries (L-shaped lots, equipment lots separated by roads) would require multiple overlapping circles or a polygon geofence, neither of which is implemented here. @@ -522,7 +522,7 @@ The boundaries below are the scope choices of the reference design — each mark **No tamper detection.** The firmware does not detect cable cutting, enclosure intrusion, or GPS jamming. A motivated thief who locates and removes the tracker, jams the antenna, or removes the equipment battery before the solar reserve is depleted will defeat this POC design. -**Satellite data budget.** The Notecard for Skylo includes 10 KB of Skylo data per month. Compact record sizes derived from the actual template field types are **26 bytes** per `tracker.qo` heartbeat (4 floats × 4 bytes + 5 int16 × 2 bytes) and **47 bytes** per `alert.qo` event (4 floats × 4 bytes + 3 int16 × 2 bytes + 24-char string field at 25 bytes). The payload-only budget therefore supports roughly **390 heartbeat-sized Notes** (10,240 ÷ 26 bytes) or **215 alert-sized Notes** (10,240 ÷ 47 bytes) per month. Actual usable counts are lower after satellite-session protocol and framing overhead — validate against Notehub usage metrics and field measurements rather than relying on payload-only arithmetic. Under normal stationary operation, heartbeats queue every hour and batch-transmit every 4 hours (~6 outbound sessions/day), so the heartbeat budget is well within limits. **Alert storm risk:** if the equipment is under active pursuit and cellular coverage is lost, repeated `sync:true` alerts every `alert_cooldown_min` (default 5 minutes) can consume the Skylo budget quickly — 47 bytes × 288 alerts/day (5-min cadence) = 13.5 KB, exceeding the monthly satellite allowance in a single day. If satellite-only operation during a pursuit event is expected, raise `alert_cooldown_min` to 15–30 minutes via the Notehub fleet env var to protect the monthly budget. In production, consider gating satellite transmission to alerts only and enforcing a per-Note minimum satellite interval. +**Satellite data budget.** The Notecard for Skylo includes 10 KB of Skylo data per month. Compact record sizes derived from the actual template field types are **26 bytes** per `tracker.qo` heartbeat (4 floats × 4 bytes + 5 int16 × 2 bytes) and **47 bytes** per `alert.qo` event (4 floats × 4 bytes + 3 int16 × 2 bytes + 24-char string field at 25 bytes). The payload-only budget therefore supports roughly **390 heartbeat-sized Notes** (10,240 ÷ 26 bytes) or **215 alert-sized Notes** (10,240 ÷ 47 bytes) per month. Actual usable counts are lower after satellite-session protocol and framing overhead. Validate against Notehub usage metrics and field measurements rather than relying on payload-only arithmetic. Under normal stationary operation, heartbeats queue every hour and batch-transmit every 4 hours (~6 outbound sessions/day), so the heartbeat budget is well within limits. **Alert storm risk:** if the equipment is under active pursuit and cellular coverage is lost, repeated `sync:true` alerts every `alert_cooldown_min` (default 5 minutes) can consume the Skylo budget quickly: 47 bytes × 288 alerts/day (5-min cadence) = 13.5 KB, exceeding the monthly satellite allowance in a single day. If satellite-only operation during a pursuit event is expected, raise `alert_cooldown_min` to 15–30 minutes via the Notehub fleet env var to protect the monthly budget. In production, consider gating satellite transmission to alerts only and enforcing a per-Note minimum satellite interval. **Mojo is bench-only in this POC.** The firmware does not read Mojo's LTC2959 coulomb counter over the Qwiic bus. Mojo is used only as a bench measurement instrument during validation. @@ -546,4 +546,4 @@ The engineering work that turns this into a production security device follows, ## 12. Summary -The fleet manager who used to learn about a stolen skid steer when the morning crew arrived now learns about it within minutes of the wheels moving, and has a staged immobilizer command ready to fire on the thief's next key-on. A Notecarrier CX and Notecard for Skylo, a solar-trickled LiPo, and two wires into the ignition circuit turn the equipment into a recoverable asset. Hourly heartbeats during the business day, rapid two-minute after-hours scans that fire immediate alerts on motion, and a staged relay that blocks ignition on the next key cycle the Cygnet observes — that's the loop, with a production latching relay as the clear next step. And when the equipment ends up exactly where stolen equipment ends up — rural stash yard, shipping container, metal barn — Skylo satellite carries the location and alert Notes skyward when cellular has long since gone dark. That's the difference between a recovered skid steer and one that's already been exported. +The fleet manager who used to learn about a stolen skid steer when the morning crew arrived now learns about it within minutes of the wheels moving, and has a staged immobilizer command ready to fire on the thief's next key-on. A Notecarrier CX and Notecard for Skylo, a solar-trickled LiPo, and two wires into the ignition circuit turn the equipment into a recoverable asset. Hourly heartbeats during the business day, rapid two-minute after-hours scans that fire immediate alerts on motion, and a staged relay that blocks ignition on the next key cycle the Cygnet observes. That's the loop, with a production latching relay as the clear next step. And when the equipment ends up exactly where stolen equipment ends up — rural stash yard, shipping container, metal barn — Skylo satellite carries the location and alert Notes skyward when cellular has long since gone dark. That's the difference between a recovered skid steer and one that's already been exported.