Use Your AI Agent to Talk to Your Products with Notehub IQ

Blues Developers
What’s New
Resources
API Reference
Notecard and Notehub API documentation
Blog
Technical articles for developers
Connected Product Guidebook
In-depth guides for connected product development
Developer Certification
Get certified on wireless connectivity with Blues
Newsletter
The monthly Blues developer newsletter
Terminal
Connect to a Notecard in your browser
Webinars
Listing of Blues technical webinars
Blues.comNotehub
Shop
Docs
Help
Support DocsNotehub StatusSecurity AdvisoriesVisit our Forum
Sign In
Docs Home
What’s New
Resources
API Reference
Notecard and Notehub API documentation
Blog
Technical articles for developers
Connected Product Guidebook
In-depth guides for connected product development
Developer Certification
Get certified on wireless connectivity with Blues
Newsletter
The monthly Blues developer newsletter
Terminal
Connect to a Notecard in your browser
Webinars
Listing of Blues technical webinars
Blues.comNotehub
Shop
Docs
Example Apps
Samples
Building a Simple Asset Tracker
Building Edge AI Applications
Continuous Asset Tracking with External GPS and Immediate Location Sync
Controlling Device State and Receiving Acknowledgment
Managing a Notecard's WiFi Network Remotely
Putting a Host to Sleep Between Sensor Readings
Routing Data from Notehub to a Custom Cloud Endpoint
Using LEDs and NeoPixels to Monitor Notecard Status
Accelerators
Asset Location Tracking
Heavy Equipment Hours-of-Use & Utilization Tracker
Returnable Container / Tote Pool Tracker
Untethered Trailer and Chassis Fleet Tracker
Asset Performance Optimization
Legacy Diesel Generator Fleet Performance Uplift
Solar Array String-Level Performance Dashboard
Battery Management Systems
Aerial Lift / Rental Equipment Battery Health Monitor
Off-Grid Solar Battery Site Controller
Remote Cabinet Backup Battery Sentinel
Downtime Prevention
Municipal Wastewater Lift Station Monitor
Rooftop HVAC Predictive Maintenance
VFD Pump Predictive Maintenance
Energy Monitoring Solutions
Commercial Tenant Sub-Metering Bridge
EV Charger Session & Utilization Monitor
Utility Distribution Transformer Load Monitor
Energy Savings
Commercial Plug-Load & After-Hours Waste Dashboard
Demand-Response Solar + Battery Dispatcher
Multi-Site Walk-In Cooler Energy & Setpoint Monitor
Industrial Equipment Monitoring
CNC Machine Spindle Load and Cycle Time Tracker
Injection Molding Shot-to-Shot Process Monitor
Trailer Manufacturer Connected Trailer Platform
Loss Prevention
Construction Equipment Anti-Theft Tracker with Immobilizer
Reefer Trailer Cold-Chain & Door-Event Monitor
Remote Patient Monitoring
Cellular Medication Adherence Pillbox
Post-Discharge Vitals Relay Hub
Remotely Monitored Assets
Off-Grid Livestock Water Tank Monitor
Remote Apiary Hive Health Monitor
Safety Assurance
Construction Site Environmental & Noise Exposure Monitor
Lone Worker Panic and Fall Detection Beacon
Regulatory-Grade Pharmacy and Lab Cold Storage Audit Monitor
Supply Chain Tracking
Pallet-Attached Cold Chain Logger
Rail Car Condition & Interchange Tracker
Truck Roll Reduction
Commercial Grease Interceptor Level Monitor
Propane / LPG Tank Fill Telemetry
homechevron_rightExample Appschevron_rightAcceleratorschevron_rightPropane / LPG Tank Fill Telemetry

Propane / LPG Tank Fill Telemetry

Propane / LPG Tank Fill Telemetry banner
note

This reference application is here to give you ideas and help you get started quickly. It's built on specific hardware that may not match yours, so focus on the sections that fit your use case. If you'd like to talk through your project and whether it's a good fit for Blues, reach out.

Building with an AI assistant? Point it at this accelerator's firmware in firmware/propane_tank_telemetry/ so it can learn how the device works and help you adapt it to your hardware.

This project is a truck roll reduction reference design that gives propane dealers fill telemetry for every tank in their delivery territory. It swaps fixed-schedule routes for demand-driven dispatch and projects days-until-empty for each tank in the fleet. A level sensor at the tank's existing gauge port and a temperature probe on the tank shell let each tank report on itself. A single Notecard for Skylo (one module with cellular, Skylo satellite, and WiFi radios that fails over between them automatically) gets the data out from a tank three minutes outside town just as easily as from a 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 delivery routes on a fixed calendar, where every tank gets a truck every six weeks. That schedule doesn't track demand. It's just the only option when dealers can't tell which tanks actually need filling. So trucks roll to tanks sitting at 60%, while tanks on remote farm properties run dry between scheduled visits. Neither failure is exotic. Both follow directly from not having fill-level data.

The root cause is infrastructure. A propane tank sits in a field, on a farm, at a cabin, or at a rural business. It's almost never near a WiFi access point the dealer can use, and it's often somewhere cellular is marginal or missing entirely. The tank itself is a sealed pressure vessel with no way to communicate. Retrofitting telemetry means solving three problems at once: connectivity that varies by site, sensing that's specific to LP (liquefied petroleum) gas vessels, and turning raw fill readings into data a dispatcher can act on.

This project handles all three. A weatherproof electronics enclosure mounts on a post or bracket outside the AHJ-defined classified area. Field wiring connects it to a 4-20 mA LP gauge-port float transmitter at the tank's existing dip-tube gauge port and to a DS18B20 temperature probe strapped to the tank shell. Every 15 minutes the device wakes, 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 cloud service. When fill drops below a configurable low-fill threshold, an alert goes out right away. The dealer's dispatch system sees fill %, gallons remaining, and projected days-until-empty for every tank in the fleet, which is enough to replace the calendar with a route that only rolls a truck when a tank actually needs it.

Why Notecard for Skylo. Propane tanks sit at farms, cabins, rural businesses, and homes. Most have no customer WiFi the dealer can use, and many are in areas where cellular coverage is spotty or missing. A dealer network covers all of these site types and can't afford a different hardware setup for each one. Notecard for Skylo (NOTE-NBGLWX) puts three radios on one M.2 module and picks among them automatically: cellular (LTE-M / NB-IoT / GPRS), satellite over the Skylo non-terrestrial network (NTN), and WiFi. The firmware sets a single card.transport preference of wifi-cell-ntn. That tells the Notecard to use WiFi where a provisioned AP happens to be in range (the rare residential tank), fall back to cellular (the de facto primary across most of the territory), and fall back again to Skylo satellite at remote sites. The Notecard handles failover, so the host firmware never branches on which network is live.

This used to be a two-device decision, with a cellular Notecard for in-coverage tanks and a separate satellite add-on for the rest. Now it's a single part number and antenna kit, plus one firmware image that deploys unchanged across the whole fleet. Notecard for Skylo ships with an active global SIM that includes 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. When a site turns out to have weaker coverage than the survey suggested, there's nothing to swap. The same board that runs on cellular near town reaches the Skylo network at the cabin on its own.

New to Blues?

Learn what we do in this 3-minute video that walks you through how we simplify wireless connectivity.

Learn what we do in this 3-minute video that walks you through how we simplify wireless connectivity.

Deployment scenario. A weatherproof NEMA 4X enclosure mounts on a separate post, wall, or bracket outside the AHJ-defined classified area (see the safety notice in §4) and runs off 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, and field wiring runs from the transmitter to the electronics enclosure outside the hazardous boundary. A waterproof DS18B20 temperature probe clamps to the tank shell, and its readings go into the daily summary Notes for seasonal demand analytics. Notecard for Skylo's antenna cables leave the enclosure for outdoor-mounted antennas with a clear sky view. One Skylo-certified antenna carries both cellular and satellite, so where there's no cellular coverage, the board falls back to the Skylo NTN satellite network on its own. It stays on the same Notehub project, with no antenna swap and no firmware changes. The tank itself isn't modified, and the install needs neither on-site internet infrastructure nor the OEM's cooperation.

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

Device-side responsibilities. Inside the post-mounted enclosure, the Notecarrier CX's STM32 host 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 on the spot. Otherwise it goes straight back to sleep. Once per report_interval_hr (24 hours by default) it sends a templated summary with the current fill %, fill gallons, the minimum fill seen in the window, window-averaged temperature, daily consumption rate, and projected days-until-empty. Between wakes the host sleeps in STM32 STOP2 (a few µA) until the Notecard's ATTN pin wakes it through card.attn, while Notecard for Skylo idles at ~8 µA. Every queued Note travels over I²C, and the host never hand-rolls JSON or sends an AT command.

Notecard responsibilities. Notecard for Skylo does the same job no matter which radio is live. It holds Notes in its on-device queue, opens a session on the hub.set outbound cadence, and pushes any sync:true alert through right away. The card.transport wifi-cell-ntn preference set at boot picks the path automatically, with no firmware branching. That's WiFi where a provisioned AP is reachable, cellular at most sites, and Skylo satellite at remote ones. Whatever the path, the module pulls 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. Over satellite that depends on an environment variable template, which the firmware registers at boot (see §7).

Notehub responsibilities. Events arrive in Notehub over whichever transport carried them, and Notehub ingests and stores them and passes them on through project-level routes. Per-fleet environment variables let a single firmware image handle tanks of every capacity, because the tank size and sensor calibration live in Notehub instead of in compiled constants. Smart Fleets can group tanks by territory, capacity class, or customer type so the right calibration values reach the right tanks automatically.

Routing to the cloud (high level). Notehub can route to HTTP, MQTT, AWS, Azure, GCP, Snowflake, and several other destinations, and route setup depends on your project. This reference design doesn't ship a specific downstream endpoint, so see the Notehub routing docs for details. For a propane dealer, the obvious targets are a route-optimization or ERP system (through an HTTP webhook) and a time-series database for trend analysis (in whatever cloud data store the dealer prefers).

3. Technical Summary

Clone this repository, build the firmware, and deploy it:

  1. Get the firmware onto your Notecarrier CX:

    arduino-cli core install STMicroelectronics:stm32
    arduino-cli lib install "Blues Wireless Notecard" "STM32duino Low Power" "STM32duino RTC" OneWire DallasTemperature
    arduino-cli compile -b STMicroelectronics:stm32:Blues:pnum=CYGNET,usb=none firmware/propane_tank_telemetry/
    arduino-cli upload -b STMicroelectronics:stm32:Blues:pnum=CYGNET,usb=none -p /dev/ttyACM0 firmware/propane_tank_telemetry/

    Change the port (/dev/ttyACM0 on Linux/Mac, COM* on Windows) if you need to. The usb=none board option disables the USB CDC stack, which has to be off for the host to sleep (see §7). firmware/propane_tank_telemetry/sketch.yaml sets the same board options, so running arduino-cli compile in that directory without -b picks them up too.

  2. Claim your Notecard to Notehub: Sign up at notehub.io and create a project. Copy the ProductUID and paste it into the firmware as PRODUCT_UID.

  3. Configure fleet variables in Notehub: Set these in Projects → Environment (tab) at the Fleet level:

    • tank_capacity_gal: your tank's usable capacity (e.g., 500)
    • fill_alert_pct: alert threshold (default 20)
    • Everything else has a sensible default. See §6 for the full list.
  4. See your first event: After a few minutes of network registration, check Notehub → Devices → [Your device] → Events. If your tank is below the alert threshold, a tank_alert.qo shows up within minutes. The first tank_status.qo daily summary Note arrives one report_interval_hr (24 hours by default) after the Notecard first syncs its clock, since the firmware waits out a full reporting window before sending it. That Note's body carries fill_pct, fill_gal, temp_c, gal_per_day, and days_until_empty.

§4–§9 cover full assembly and commissioning.

Here's a sample Note from this device:

{
  "file": "tank_status.qo",
  "body": {
    "fill_pct":         42.3,
    "fill_gal":         211.5,
    "min_fill_pct":     38.1,
    "temp_c":           14.8,
    "gal_per_day":      8.2,
    "days_until_empty": 25.8,
    "transmitter_ma":   10.8
  }
}

4. Hardware Requirements

PartQtyRationale
Notecarrier CX1Integrated carrier with an onboard STM32L433 host. It handles the 12-bit ADC for the 4-20 mA loop and OneWire for the temperature probe, so you don't need an external MCU.
Notecard for Skylo (NOTE-NBGLWX) · datasheet1One M.2 module carrying cellular (LTE-M / NB-IoT / GPRS, Quectel BG95-S5 modem), Skylo satellite (NTN), and WiFi (Silicon Labs WFM200S) radios. The firmware's card.transport wifi-cell-ntn setting makes it prefer WiFi where a provisioned AP is in range, use cellular at in-coverage tanks, and fall back automatically to the Skylo satellite network at remote sites beyond cellular reach, so there's no second device or part number to decide on. Cellular removes the per-site IT dependency, and the embedded global SIM and bundled satellite allocation cover the whole territory from one SKU. Requires the antennas below.
Blues Mojo1Bench only. Coulomb counter on the 5 V supply rail for checking power behavior during commissioning (see §9). Remove and discard it for field deployment, since it isn't integrated into production units.
Rochester Sensors M6300-LP Magnetel® Rough Rider® LP gas gauge + R6315-12 4-20 mA transmitter: M6300-LP datasheet · R6315-12 datasheet · 6300 series installation guide. Available from John M. Ellsworth Co. and LP gas equipment distributors.1Float-type magnetel level transmitter designed specifically for LP gas service. A float rides the liquid propane surface inside the tank and drives a two-wire 4-20 mA current loop proportional to fill level: 4 mA at 0 % fill, 20 mA at 100 % fill. Representative orderable assembly: M6300-LP gauge body (1¼″ NPT, 4″ dial) with the R6315-12 transmitter module attached. The R6315-12 clips to the M6300 gauge body and provides the 4-20 mA output, proportional to the float position. See the R6315-12 datasheet for electrical specifications and wiring. Mounting: the M6300-LP installs at the tank's existing 1¼″ NPT dip-tube gauge port (the standard gauge opening on most horizontal residential and commercial LP tanks). Dip-tube length and float arm length vary by tank geometry, so check the correct M6300-LP model suffix against the Rochester Sensors product application table and the tank's nameplate before ordering. Some larger commercial tanks use a 2″ NPT gauge boss, and Rochester Sensors offers matching variants. Electrical: two-wire loop-powered, 12–28 V DC supply. Note: the float tracks the liquid surface directly, so the firmware applies no density or temperature correction. The 4-20 mA output is already proportional to fill level regardless of liquid temperature or density. Installation at a propane pressure vessel must be performed by a licensed LP gas technician per NFPA 58.
SparkFun Waterproof DS18B20 Temperature Sensor (SEN-11050)1OneWire temperature probe clamped to the tank shell. Its readings go into daily summary Notes so the cloud side can correlate consumption with ambient conditions.
120 Ω 0.1 % precision resistor1Shunt across the 4-20 mA current loop. Converts 4–20 mA to 0.48–2.40 V DC at the host's A0 ADC pin. The 120 Ω value leaves safe electrical headroom for standard 4–20 mA transmitter fault currents. A 24 mA diagnostic output produces only 2.88 V at A0, well within the 3.3 V ADC absolute maximum. The firmware rejects currents outside the 3.5–21 mA valid window as NAN and emits a sensor_fault alert, and with this shunt the ADC is electrically safe up to ~27 mA (3.3 V ÷ 120 Ω).
4.7 kΩ resistor1OneWire pull-up for the DS18B20 data line.
12 V DC/DC step-down module, 5 V / 2.5 A output (e.g. Pololu D24V22F5)1Steps the 12 V battery rail down to 5 V for the Notecarrier CX VBAT input. This design needs a 2.5 A continuous output rating, because Notecard for Skylo's onboard modem (Quectel BG95-S5) can demand up to ~2 A in brief bursts and a 1 A regulator can't reliably source that peak. The D24V22F5 delivers 5 V at up to 2.5 A continuous from a 5.3–36 V input, which leaves comfortable headroom above the Notecard's 2 A burst demand plus the STM32 host's active-mode draw.
24 V DC/DC boost converter module, input 8–16 V, output regulated 24 V, ≥ 100 mA (e.g. Pololu U3V50F24)1Provides a stable, regulated 24 V supply for the 4–20 mA transmitter current loop. With a regulated 24 V loop supply, the transmitter stays in compliance across the full SLA discharge cycle, any practical cable run, and an AHJ-required IS barrier. See the loop compliance calculation in §5 Step 7. Do not drive the transmitter loop from the 12 V system rail. When the battery sags (11–11.5 V under partial charge and load), the loop supply falls below the R6315-12's 12 V minimum specification, and any IS barrier in the loop cuts the margin further. The Pololu U3V50F24 accepts inputs from 2.9 V up to its 24 V output and delivers a regulated 24 V at up to 500 mA. It runs from the same 12 V system rail as the 5 V step-down module.
Skylo-certified LTE/satellite antenna included with Notecard for Skylo (u.FL)1Connects to the MAIN u.FL port and carries both the terrestrial cellular signal and the Skylo satellite link, so one antenna covers both networks. Use only the Skylo-certified antenna supplied with Notecard for Skylo, because an uncertified antenna risks regulatory non-compliance and link failure. Mount it outdoors with an unobstructed view of the sky (northern hemisphere: the southern sky) so the board can reach Skylo wherever it falls back from cellular, and route it through a cable gland. Don't rely on the bare antenna inside a polycarbonate enclosure at tank-side, since the signal margin is too variable.
u.FL-to-SMA-F bulkhead pigtail, ~15–20 cm (e.g. Taoglas CAB.0150.A.01 or equivalent)0–1Optional. You only need it to mount an external SMA-terminated antenna instead of routing the bare u.FL antenna through the enclosure wall. It adapts the MAIN u.FL port to an external SMA bulkhead, which then connects to the external antenna cable outside. Skip it if you route the included Skylo-certified antenna straight through a gland.
Passive GPS/GNSS antenna (u.FL) per the Notecard for Skylo datasheet1Connects to the GPS u.FL port for GNSS time/location. Mount it outdoors with a clear sky view next to the main antenna, and route it through a cable gland.
IP68-rated PG-11 nylon cable gland, 5–10 mm cable OD (e.g. Lapp SKINTOP® MS-M PG 11 or equivalent)5One gland per field cable entering the enclosure. This installation needs penetrations for: (1) the Skylo-certified MAIN antenna lead (or its SMA bulkhead); (2) the GPS/GNSS antenna lead; (3) the DS18B20 temperature probe cable; (4) the 4–20 mA transmitter loop wiring (two conductors from transmitter to enclosure); and (5) the solar panel cable (skip this one if you use an MC4 pass-through instead, as in §5 Step 2). Every penetration must be sealed to keep the NEMA 4X enclosure rating. Pick each gland's cable-OD range to match that cable's outer diameter.
12 V sealed lead-acid battery, 7–10 Ah (e.g. Universal Power Group UB1280, 8 Ah)1Stores energy for cloudy stretches and overnight. At this device's duty cycle, 8 Ah gives ≥3 days of autonomy without solar input (see Limitations for the power budget).
Inline fuse holder + 5 A automotive blade fuse (e.g. Bussmann BP/HHM + ATC5)1Goes in the battery (+) lead as close to the battery positive terminal as possible, and protects the wiring from a short-circuit fault in the load circuit. The 5 A rating protects the ≤2 A maximum load while leaving headroom above the controller's worst-case startup surge. Use a weatherproof fuse holder if the battery sits outside the NEMA 4X enclosure.
Victron SmartSolar MPPT 75/10 solar charge controller1Regulates solar panel output to charge the 12 V SLA battery safely. The SmartSolar MPPT 75/10 has dedicated LOAD+ / LOAD− output terminals with built-in low-voltage disconnect (LVD) that automatically cuts load power to protect the SLA from deep discharge. The wiring in §5 depends on that feature. If you substitute a different controller, confirm it has equivalent LOAD terminals with LVD before following the §5 wiring steps.
Monocrystalline solar panel, 10–20 W, 12 V nominal (e.g. Renogy 10W Monocrystalline RNG-10D-SS)110 W is enough for mid-latitude sites (≥4 h/day usable sun). Go up to 20 W for northern latitudes, winter deployments, or sites with frequent cloud cover. Mount it with a clear sky view, not against the tank body.
NEMA 4X polycarbonate enclosure, ~8 × 6 × 3.5″1Weatherproof housing rated for outdoor tank-side mounting. Polycarbonate is UV-resistant and non-sparking.

Bundled connectivity (Notecard for Skylo): Notecard for Skylo ships with an active global SIM that includes 500 MB of cellular data and 10 years of service, plus 10 KB of bundled Skylo satellite data, with no activation fees, no monthly commitment, and no separate satellite provider subscription. Additional satellite data is billed per byte (see the Notecard for Skylo datasheet for current pricing). Keeping inbound syncs infrequent stretches the bundled satellite allocation.

warning

Safety notice. LP gas (liquefied petroleum gas) is a flammable compressed gas. Any sensor connection to a propane tank, including at the gauge port, must be performed by a qualified LP gas technician following applicable codes (NFPA 58, CGA, and the local authority having jurisdiction). The level transmitter, fittings, and wiring must be rated for LP gas service.

Classified-area / hazardous-location requirement. Blues Notecard and Notecarrier CX electronics are not rated for hazardous locations (NEC Class I Division 1 or Division 2 / ATEX Zone equivalents) and must not be installed inside the classified area as defined by the installation's authority having jurisdiction (AHJ) and NFPA 58. The classified area boundary around a propane container usually extends several feet from fittings, relief valves, and regulators. Confirm the boundary with the AHJ and the installing LP gas technician before you position the enclosure, and mount the electronics enclosure outside it. If the 4–20 mA transmitter loop wiring crosses the classified-area boundary, the AHJ may require a listed intrinsic-safety (IS) barrier or other approved interface device in the loop circuit, between the tank-side transmitter and the enclosure-side electronics. Confirm IS barrier requirements with the installing LP gas technician and the AHJ before wiring.

5. Wiring and Assembly

Wiring: 4–20 mA float transmitter with 120 Ω shunt → A0; DS18B20 with 4.7 kΩ pull-up → D2; ATTN → D5 jumper so the Notecard can wake the host from STOP2; 24 V boost converter for transmitter loop; solar + SLA dual-rail power chain (5 V → +VBAT, 24 V → loop)

All Notecarrier CX host I/O lands on its dual 16-pin header, and Notecard for Skylo seats in the M.2 slot. During bench validation only, the Mojo sits inline between the 5 V step-down and the Notecarrier +VBAT pad. It doesn't go out to the field.

warning

Enclosure placement first. Blues Notecard and Notecarrier CX electronics must be installed outside the classified-area boundary defined by NFPA 58 and the authority having jurisdiction. Confirm that boundary with the installing LP gas technician before you drill cable-gland holes or position the enclosure.

Step 1: Enclosure and cable-gland assignment. Mount the NEMA 4X polycarbonate enclosure at the location you picked. Before pulling any cables, drill and install one cable gland for each field-cable penetration. Assign the glands like this:

GlandCable / penetration
1Skylo-certified MAIN antenna lead (or its SMA bulkhead), which carries cellular and satellite
2GPS/GNSS antenna lead (GPS u.FL port)
3DS18B20 temperature probe cable
44–20 mA transmitter loop wiring (2-conductor, from transmitter to enclosure)

The solar panel cable takes a fifth gland (Gland 5) unless you use an MC4 pass-through instead (see Step 2). Match each gland's cable-OD clamp range to the actual cable outer diameter. After routing cables, tighten every gland to the manufacturer's torque spec, and don't leave any unused penetration open.

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 somewhere unobstructed with a good sky view, not against the tank body or in the tank's shadow. Set the tilt angle to catch the most winter sun for the deployment latitude. Run the panel cable into the enclosure through Gland 5 (or use an MC4 weatherproof pass-through if the controller has external PV terminals), and keep the run as short as practical to cut resistive loss.

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). Put the inline fuse holder + 5 A fuse from the BOM in the battery (+) lead, as close to the battery positive terminal as possible. If the battery sits outside the NEMA 4X enclosure, use a weatherproof fuse holder.

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 you substitute a different controller, check for those features before following these steps. If the controller has no LOAD terminals, wire from the 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).

Set the step-down module output to 5.0 V and check it with a meter before connecting any load.

Step-down Vout+ → Mojo BAT+
Step-down Vout− → Mojo BAT− / GND
Mojo LOAD+      → Notecarrier CX +VBAT
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.

Seat Notecard for Skylo (NOTE-NBGLWX) into the Notecarrier CX M.2 slot and secure the retaining screw.

Notecard for Skylo has 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, so there's no separate satellite antenna to install. Connect the antennas like this:

  • 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, because an uncertified part risks regulatory non-compliance and link failure. Don't skip this connection. Both cellular and satellite operation need 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.

Pick antenna cable lengths that suit the routing distance before you order, because most pre-terminated assemblies shouldn't be cut or field-terminated. Secure any extra cable outside the enclosure in a gentle loop, and don't coil cable inside the enclosure.

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, through Gland 4. Wire the loop from the dedicated 24 V boost converter output, not from the 12 V system rail or the 5 V Notecarrier rail (see the compliance note below):

  • 24 V boost converter Vin+ → charge controller LOAD+ (same 12 V rail that feeds the 5 V step-down). 24 V boost converter GND → system GND.
  • 24 V boost converter Vout+ (regulated 24 V) → transmitter + terminal (loop supply in).
  • Transmitter − terminal (loop signal out) → one leg of the 120 Ω precision shunt resistor; other shunt leg → system GND (same node as Notecarrier GND and battery −).
  • A0 (analog input on the Notecarrier CX header) → the junction between the transmitter − terminal and the shunt resistor.

At 4 mA (float at the bottom, empty tank), V(A0) = 0.48 V. At 20 mA (float at full scale, full tank), V(A0) = 2.40 V. Both are well within the host's 0–3.3 V ADC range. With the 120 Ω shunt, a 24 mA transmitter diagnostic output produces only 2.88 V at A0, and the ADC is electrically safe up to ~27 mA (3.3 V ÷ 120 Ω). The firmware's software fault window is 3.5–21 mA. Any current outside that range asserts a sensor_fault alert and marks the reading NAN. The shunt voltage and ADC range are the same as in a 12 V supply design, and only the loop supply source changes.

Loop compliance calculation. The R6315-12 datasheet specifies a supply voltage range of 12–28 V DC. Here's the worst-case compliance budget at 20 mA full-scale:

ElementVoltage drop at 20 mA
120 Ω shunt (sense resistor, enclosure side)20 mA × 120 Ω = 2.40 V
100 m of 22 AWG field wiring (both conductors combined)20 mA × 2 × 100 m × 0.053 Ω/m ≈ 0.21 V
IS barrier (Zener-diode shunt type, if required by AHJ)≤ 2.5 V at 20 mA
Total worst-case external drops≤ 5.11 V

With the regulated 24 V boost converter output, V at the transmitter terminals = 24 V − 5.11 V = 18.89 V. That's 6.89 V above the 12 V lower compliance limit and well below the 28 V upper limit. The transmitter stays in regulation across the full battery charge/discharge cycle, on any cable run up to 100 m, with or without an IS barrier.

Why not the 12 V system rail? An SLA battery discharges from ≈ 12.8 V (fully charged) to the low-voltage disconnect threshold (≈ 10.8 V). At partial charge under load it commonly measures 11.0–11.5 V, which is already at or below the R6315-12's 12 V minimum supply before you account for cable resistance or an IS barrier. Either one makes the margin worse. The 24 V boost converter removes that dependency, since it holds a regulated 24 V output as long as the SLA stays above the converter's 2.9 V minimum input voltage, well below the charge controller's LVD threshold.

The transmitter's process connection is the tank's single 1¼″ NPT dip-tube gauge port, so you don't need a second tank connection. Internally, the float mechanism provides the level reference. The LP gas technician installs the transmitter at the gauge port and runs the 2-conductor loop cable from the transmitter to the enclosure. Confirm the correct dip-tube length for the tank geometry before installation.

Before applying power, confirm that system GND (battery −), charge controller LOAD−, step-down Vin−, step-down Vout−, boost converter GND, and Notecarrier GND all connect to the same node.

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 for better thermal contact and less ambient-air influence. Secure the cable with a zip tie so it doesn't strain the gland. Inside the enclosure:

  • DS18B20 red wire (VCC) → +3V3 on the Notecarrier CX header.
  • DS18B20 black wire (GND) → GND on the Notecarrier CX header.
  • 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 has no onboard OneWire pull-up, so you need this resistor.

Step 9: ATTN-to-D5 jumper (host sleep).

Fit a short jumper between the ATTN and D5 pins on the Notecarrier CX header. Both are on the same 16-pin header (ATTN at position 3, D5 at position 14). The Notecard pulls ATTN low while the host sleeps and raises it when the next sample is due, and the rising edge on D5 wakes the host from STOP2. Leave the Notecarrier CX EN pin unconnected. On the CX it enables the shared 3.3 V VIO rail (host, Qwiic, 3V3_OUT, and Notecard I/O), so driving it from ATTN would brown out the whole board instead of putting the host to sleep. Putting a Host to Sleep Between Sensor Readings covers the full pattern.

Step 10: Satellite operation (automatic, no added hardware).

Satellite operation needs no extra module or wiring. 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). From then on, the Notecard automatically routes queued Notes over the Skylo NTN satellite network at any site where cellular is unavailable. For satellite to work in the field, the MAIN antenna has to be mounted outdoors with an unobstructed view of the sky (northern hemisphere: the southern sky), so confirm a suitable mounting spot at remote tank sites. The daily summary Note (~40 bytes) fits well within the NTN payload budget. Also note that the board must complete at least one initial non-NTN (cellular or WiFi) sync to associate with Notehub and register its Notefile and environment variable templates before it can use satellite. Commission each unit where it has terrestrial coverage, even if it will normally run over satellite. Before deploying to a cellular-dark site, review the Satellite Best Practices guide for duty-cycle and data-budget considerations.

Final pre-power checklist.

  • All cable glands tightened; no unused enclosure penetrations open.
  • All GND nodes common: battery −, charge controller LOAD−, step-down Vin−, step-down Vout−, boost converter GND, Notecarrier GND.
  • Step-down output confirmed at 5.0 V before connecting Notecarrier.
  • Boost converter Vin+ wired to 12 V system rail (LOAD+); boost converter Vout+ confirmed at 24 V before connecting transmitter loop wiring.
  • Skylo-certified MAIN antenna connected and routed outdoors with a clear sky view (carries both cellular and satellite); GPS/GNSS antenna connected to the GPS port and routed outdoors.
  • 120 Ω shunt installed in the current loop with A0 tapped at the transmitter − / shunt junction; loop supply drawn from 24 V boost converter output (not the 12 V rail).
  • Inline fuse installed in battery (+) lead, as close to the battery positive terminal as possible.

6. Notehub Setup

  1. Create a project. Sign up at notehub.io and create a project. Copy the ProductUID and paste it into the firmware as PRODUCT_UID.

  2. Claim the Notecard. Power up the unit, and the Notecard associates with the project on its first cellular session. Check that the device shows up in the Notehub device list with a recent session.

  3. Optional: configure WiFi credentials. Notecard for Skylo supports WiFi as an optional secondary transport, and the device runs normally on cellular (or satellite) alone if no WiFi credentials are set. This hardware stack has two reliable ways to provision them:

    • 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 reach the device on the next inbound sync. hubConfigure() sets inbound to 2× the outbound period, so at the default 24-hour report cadence, inbound syncs happen 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, which then connects over WiFi first whenever it can reach that network, since wifi-cell-ntn puts WiFi ahead of cellular. To roll out credentials faster, temporarily lower report_interval_hr (to 1 hour, for example), confirm connectivity, then restore the original value. Credentials persist on the Notecard even if the env vars are cleared later.

    • Alternative: direct Notecard USB (bench setup before deployment). With the Notecarrier CX fully powered off, set its USB-C DIP switch to NC so the USB-C port connects to the Notecard instead of the STM32 host, then power up and connect a USB cable. With that connection active, open Notecard Playground and send {"req":"card.wifi","ssid":"<SSID>","password":"<password>"}. It's easiest to do this at the bench before you seal the enclosure for field deployment.

    Normal operation doesn't need WiFi, so you don't have to provision it on every device.

  4. Create a Fleet per territory. Fleets let you group devices for shared configuration and routing. A natural split is one fleet per delivery territory or per tank capacity class, since a 250-gallon residential fleet and a 1000-gallon commercial fleet may need different alert thresholds and report cadences. Smart Fleets can auto-assign new devices by matching tags set at provisioning time (e.g. tank_size:1000gal).

  5. Set environment variables. In Notehub, go to Projects → [Your Project] → Environment and configure a Fleet at the Fleet level or Device level. Every variable below is optional, and the table shows the firmware's compile-time defaults. Any value you set in Notehub takes effect on the device's next inbound sync, with no firmware re-flash. Set variables on the Fleet so one configuration applies to every tank in it, and override at the Device level for per-tank exceptions.

    VariableDefaultPurpose
    tank_capacity_gal500Usable tank capacity in gallons at 100 % gauge reading.
    sensor_empty_ma4.0Transmitter output current in mA corresponding to 0 % fill (empty tank). Standard 4–20 mA transmitters output exactly 4.0 mA at empty, so adjust this only if the installed unit has a non-standard live-zero (rare).
    sensor_full_ma20.0Transmitter output current in mA corresponding to 100 % fill. Standard 4–20 mA transmitters output 20.0 mA at full. Adjust it if the installed unit doesn't reach exactly 20 mA at the full-tank position.
    fill_alert_pct20Fill percentage below which a low_fill alert fires.
    consumption_alert_gal_per_day100Daily consumption rate above which a high_consumption alert fires. Helps catch leaks or sudden demand spikes.
    sample_interval_min15Minutes between sensor samples.
    report_interval_hr24Hours between summary Notes.
    alert_cooldown_hr4Hours between repeated alerts of the same type. Keeps a slowly draining tank from sending an alert every 15 minutes.
    consumption_alert_streak3Number of consecutive sample cycles above consumption_alert_gal_per_day required before a high_consumption alert fires. Raising it cuts false positives from transient ADC jitter or short-lived post-refill spikes. Set it to 1 to alert on the first above-threshold reading.
    wifi_ssid(unset)SSID of a WiFi network to use as a secondary transport. Set both wifi_ssid and wifi_password, and the firmware issues card.wifi on the next inbound sync (up to 48 hours at the default cadence; see step 3 above) so the Notecard stores the credentials and connects over WiFi when it's available. Credentials persist on the Notecard even if the env vars are cleared later. Env var values are visible to Notehub project collaborators, so use a dedicated IoT or guest network.
    wifi_password(unset)WPA2 passphrase for the network specified by wifi_ssid.
  6. Satellite deployments (cellular-dark sites). You don't need a hardware change. Notecard for Skylo's satellite radio is already on the board, and the firmware enables cellular→satellite fallback by setting card.transport to wifi-cell-ntn (see §7). At sites with no cellular coverage, the board falls back to the Skylo NTN satellite network automatically, and every event travels through the same Notehub project whatever the transport. Before it can use satellite, the board must complete at least one initial non-NTN (cellular or WiFi) sync to associate with the project and register its Notefile and environment variable templates. Commission each unit where it has terrestrial coverage, even if it will normally run over satellite. The daily summary Note (~40 bytes per record) fits within typical NTN satellite payload budgets. Each inbound sync also uses some of the bundled 10 KB satellite allocation, so consider widening report_interval_hr (which widens the inbound cadence too) at satellite sites. Read the Satellite Best Practices guide before deploying for the satellite-specific duty-cycle and data-budget details.

  7. Configure routes. Add one route for tank_alert.qo (real-time delivery to the dealer's dispatch or routing system) and a second for tank_status.qo (batched delivery to a time-series store for historical trend analysis and route-density modeling). Because the two Notefiles are separate at the source, each can go to a different destination at a different urgency. Alerts go somewhere that pages an operator, and daily summaries go somewhere that feeds a dashboard.

7. Firmware Design

The main sketch is firmware/propane_tank_telemetry/propane_tank_telemetry.ino. Sensor math, fill-level calculation, and consumption tracking live in firmware/propane_tank_telemetry/propane_tank_telemetry_helpers.h.

Dependencies:

  • Arduino core for STM32 (stm32duino/Arduino_Core_STM32), installed from the Boards Manager.
  • Blues Wireless Notecard (the note-arduino library). Install it from the Arduino Library Manager or with arduino-cli lib install "Blues Wireless Notecard". See the note-arduino releases for available versions.
  • STM32duino Low Power (and its dependency STM32duino RTC), also from the Library Manager. It provides the STOP2 entry and ATTN-pin wake that cx_sleep.h uses.
  • OneWire, from the Library Manager.
  • DallasTemperature, also from the Library Manager.

Build settings: The Notecarrier CX's host is the same STM32L433 as the Blues Cygnet, so select Blues boards → Cygnet (pnum=CYGNET) and set USB support (if available) to None (usb=none). If the USB CDC stack is enabled and no USB host is attached (battery power, or the Notecarrier CX USB-C switch in NC), the STM32's USB wakeup interrupt fires continuously and the host never stays in STOP2. Debug output goes to the LPUART on the Notecarrier CX debug jack instead, which an ST-LINK V3 exposes as a virtual COM port (see Serial Logging With STLINK).

Modules

ResponsibilityWhere
Notecard configuration (hub.set, card.transport wifi-cell-ntn for cellular→satellite fallback, Note and environment variable templates)hubConfigure, defineTemplates
Environment-variable fetch per wakefetchEnvOverrides
4-20 mA loop read → mA currentreadTransmitterMA
DS18B20 OneWire temperature readreadTemperatureC
Transmitter current → fill % (linear interpolation)computeFillPct
Fill % → gallons (linear scale)computeFillGal
Consumption rate (EWMA), days-until-empty projectionupdateConsumption, daysUntilEmpty
Alert evaluation and emissionrunSampleCycle, sendAlert
Daily summarysendSummary
Host sleep (STOP2 until the Notecard raises ATTN)cx_sleep.h: cxSleepBegin, cxSleepUntilAttn
Application state (held in RAM across sleep cycles)AppState

Sensor reading strategy

Gauge-port level transmitter (4-20 mA). The host's 12-bit ADC reads the voltage across the 120 Ω shunt. A 16-sample average filters out switching noise, and then the firmware converts the mean voltage to current (mA):

current_ma = (adc_voltage / 120.0) × 1000.0

The firmware's valid window is 3.5–21 mA. Below 3.5 mA means an open-loop wiring fault, and above 21 mA means a short or an unexpected diagnostic output. Either one sets the reading to NAN and emits a sensor_fault alert. With the 120 Ω shunt, a 21 mA signal produces 2.52 V at A0, well within ADC range. The ADC is electrically safe up to ~27 mA, so a transmitter in a full fault-high condition won't damage it.

Fill percentage and fill gallons. The Rochester Sensors M6300-LP + R6315-12 float transmitter outputs a current proportional to the float's position in the liquid propane, so the output already represents fill level directly, independent of liquid density or temperature. computeFillPct converts the transmitter current to fill percentage with a simple linear interpolation between the configured empty and full calibration points:

fill_pct = (current_ma - sensor_empty_ma) / (sensor_full_ma - sensor_empty_ma) × 100.0

computeFillGal then scales that to gallons:

fill_gal = (fill_pct / 100) × tank_capacity_gal

The fill reading gets no density or temperature correction. The float tracks the liquid surface directly, and its current output already represents fill level accurately across the full operating temperature range.

Temperature (DS18B20 OneWire). The DallasTemperature library handles conversion timing. The daily summary Notes include tank wall temperature so cloud-side analytics can correlate demand patterns with ambient conditions, since propane consumption is strongly seasonal. A missing or faulted DS18B20 puts the -9999 sentinel in the temp_c field of summary Notes but doesn't affect the fill reading.

Sensor selection rationale

The initial project spec called for a low-power ultrasonic or pressure level sensor, with the DS18B20 temperature probe providing vapor-pressure compensation in the fill measurement path. After evaluating both sensing methods for LP gas tank duty, this design departs from that spec and uses a float-type 4–20 mA transmitter instead. The table below lays out why, and the firmware's top-of-file sensor model comment summarizes the same reasoning.

ApproachWhy evaluatedWhy not selected for this design
Ultrasonic time-of-flight (transducer at tank top; measures vapor-space height by round-trip echo time)Non-contact; no liquid exposure for the sensor electronics; well-established for above-ground tank gauging in other applicationsRequires a dedicated transducer port at the tank top, which is an extra tank penetration beyond the standard 1¼″ NPT gauge port that the Rochester Sensors float gauge already occupies. The speed of sound in the LP vapor space varies with temperature and gas composition, so an accurate fill reading needs a temperature-compensated speed-of-sound correction. That puts the DS18B20 in the fill measurement path and adds a second independent failure mode. The LP vapor composition (propane/butane ratio) varies by supplier and season and isn't known to the firmware, so it adds a systematic bias that can't be corrected without a composition sensor.
Hydrostatic pressure (pressure sensor measuring liquid column head pressure)Single-point measurement; sensor can be installed at an existing tank fittingOn a horizontal LP tank, the gauge port at the top of the tank dome opens into the vapor space, not the bottom of the liquid column, so a sensor at the gauge port reads vapor pressure instead of liquid head. Reaching the liquid bottom takes a second tank penetration (a service-valve tee or a dedicated bottom fitting), which adds installation complexity and more tank connections that need LP gas technician work. Even with a bottom connection, the liquid head for a typical 500-gallon horizontal tank is only ~5 kPa (~0.7 psi) riding on top of ~850 kPa (~120 psi) of vapor pressure. Resolving fill level to ±5 % from that signal takes a pressure transmitter with ≤ 0.01 % full-scale accuracy, well beyond standard industrial grade. A differential pressure sensor spanning a bottom port and a vapor-space port would cancel the vapor background and improve accuracy, but it adds a second tank connection and needs two separate field-wiring runs to the enclosure. Either pressure variant puts the DS18B20 in the fill calculation path (density correction), as the original brief intended, but at the cost of two tank penetrations instead of one.
Float-type 4–20 mA transmitter (Rochester Sensors M6300-LP + R6315-12, selected design)Industry-standard LP gas gauging method; well-understood installation at the existing gauge portn/a (selected)

This design uses the Rochester Sensors M6300-LP Magnetel® float gauge + R6315-12 transmitter because it installs at the tank's single standard 1¼″ NPT dip-tube gauge port, needs no extra tank penetrations, and produces a 4–20 mA output that's directly proportional to fill level regardless of liquid temperature or density. The float tracks the physical liquid propane surface, so its current output doesn't depend on density at all, and the firmware needs no temperature correction (and applies none). The main trade-off against the original spec is a continuously powered 4–20 mA current loop, the biggest load in the power budget, instead of the switched-power or ultra-low-power sensing an I²C ultrasonic or differential-pressure sensor could offer. See §11 for the power-budget discussion.

The DS18B20 temperature probe stays in the design for cloud-side seasonal demand analytics. Its reading goes into every tank_status.qo daily summary Note and is not passed to the fill calculation. The top-of-file sensor model comment in propane_tank_telemetry.ino records the same reasoning next to the implementation.

Event payload design

The device writes to two template-backed Notefiles. Templates store Notes as compact fixed-length records instead of free-form JSON. At 365 summary Notes per tank per year across a fleet of thousands of tanks, that saves real bandwidth on a prepaid SIM. Both templates also set format to compact and give the Notefile a port, which is what makes them NTN-compatible. That way the same Notes go out over Skylo satellite when cellular and WiFi aren't available. Compact format drops a Note's metadata, so each template adds a _time field to keep the time the Note was created.

tank_status.qo (daily summary):

{
  "file": "tank_status.qo",
  "body": {
    "fill_pct":         42.3,
    "fill_gal":         211.5,
    "min_fill_pct":     38.1,
    "temp_c":           14.8,
    "gal_per_day":      8.2,
    "days_until_empty": 25.8,
    "transmitter_ma":   10.8
  }
}

tank_alert.qo (immediate, sync:true):

{
  "file": "tank_alert.qo",
  "sync": true,
  "body": {
    "alert":            "low_fill",
    "fill_pct":         18.2,
    "fill_gal":         91.0,
    "gal_per_day":      8.2,
    "days_until_empty": 11.1
  }
}

The firmware defines two alert types. low_fill means the fill percentage dropped below fill_alert_pct. high_consumption means the smoothed daily consumption rate has exceeded consumption_alert_gal_per_day for consumption_alert_streak consecutive sample cycles (default 3), which debounces transient spikes from ADC jitter or post-refill noise. A third, synthetic type, sensor_fault, fires when the transmitter current falls outside the valid 3.5–21 mA window because of an open circuit or a short on the current loop. All three use the same tank_alert.qo Notefile with sync:true, so they skip the daily outbound window and reach the dealer's dispatch system as soon as the Notecard can open a session. That's usually well under 60 seconds in good cellular coverage, and minutes when the unit is running over the Skylo satellite link (see the NOTE-NBGLWX datasheet for authoritative figures).

warning

Satellite alert latency. When Notecard for Skylo is running over the satellite (NTN) link, sync:true doesn't remove latency. The alert has to wait for an available satellite pass, and Skylo's network duty-cycle rules limit how often sessions can open. Treat satellite alert latency as minutes, not seconds. A satellite session also has a different energy profile from a cellular one, so the cellular Mojo current figures in §9 don't directly apply. For sites expected to run over satellite, validate alert timing and solar/battery sizing separately with the Satellite Best Practices guide before commissioning.

Low-power strategy

Between samples the Notecarrier CX's STM32 host sleeps in STOP2, drawing a few microamps and keeping its RAM. loop() runs one sample cycle, then calls cxSleepUntilAttn() (in cx_sleep.h). That sends a card.attn sleep request for sample_interval_min × 60 seconds, waits for the Notecard to pull ATTN low, and enters STOP2. When the interval is up, the Notecard raises ATTN, the rising edge on D5 wakes the host, and execution resumes on the next line of loop(). Notecard for Skylo itself idles at ~8 µA between network sessions (the NOTE-NBGLWX published idle figure), no matter which radio it used last.

The host resumes in place instead of cold-booting, so all application state (the smoothed consumption-rate estimate, alert cooldown timestamps, and the summary window) just lives in the AppState struct in RAM. Nothing gets serialized to the Notecard, and setup() runs only once per power-up. If the sleep request fails or ATTN never goes low (a missing jumper), loop() waits out the interval awake and tries again on the next cycle, so the sample cadence holds either way.

The Notecard runs in periodic mode with an outbound period that matches report_interval_hr. Summary Notes pile up in its queue and sync in a single cellular session once a day, while alert Notes set sync:true and go out within minutes of triggering.

Retry and error handling

  • The firmware rejects transmitter current readings outside 3.5–21 mA as NAN and leaves them out of summary averages. A sensor_fault alert fires on the first detection and then stays quiet for alert_cooldown_hr. That pages the dealer once without flooding them on every 15-minute cycle.
  • The DS18B20 returns DEVICE_DISCONNECTED_C (−127.0) if no sensor is present. The firmware checks for this sentinel and leaves the reading out of the window temperature average, so a missing probe doesn't affect the fill reading. (When no valid temperature samples were collected, the summary Note's temp_c field carries the -9999 sentinel.)
  • The firmware computes consumption rate only when it has two consecutive valid fill readings. A refill event (fill level up by more than 5 % between samples) resets the short-term accumulator without touching the EWMA, so a delivery doesn't corrupt the running consumption estimate.
  • A change to the report_interval_hr env var re-applies hub.set on the next wake, so the Notecard's outbound cellular cadence stays in step with the local summary cadence.

Key code snippet 1: template definition

Templates compress daily summary Notes into fixed-length records. In Notecard template format codes, the first digit is the type (1 for signed, 2 for unsigned), the second digit is the byte size, and a .1 suffix marks a float:

  • 14.1: 4-byte float (±3.4e38, ~7 significant digits, good for fill %, consumption rates, days-until-empty)
  • 14: 4-byte signed integer, used here for the _time timestamp
  • 21 and 22: 1- and 2-byte unsigned integers, used for the interval variables in the environment variable template

defineTemplates() sends the two Note templates and then an env.template for every variable fetchEnvOverrides() reads. Notecard for Skylo needs that template before env.get works in NTN mode, and over satellite Notehub only delivers the variables it names. env.get still returns every value as a string, so the hints only size the satellite encoding. Each request's result is checked, and perWakeConfigure() retries all three on every wake until they succeed.

J *req = notecard.newRequest("note.template");
JAddStringToObject(req, "file", "tank_status.qo");
JAddNumberToObject(req, "port", 50);
JAddStringToObject(req, "format", "compact");
J *body = JAddObjectToObject(req, "body");
JAddNumberToObject(body, "_time",            14);    // Note creation time, which compact format otherwise drops
JAddNumberToObject(body, "fill_pct",         14.1);  // 4-byte float; current fill at time of note
JAddNumberToObject(body, "fill_gal",         14.1);  // current fill gallons
JAddNumberToObject(body, "min_fill_pct",     14.1);  // lowest fill seen in this reporting window
JAddNumberToObject(body, "temp_c",           14.1);  // window-averaged tank-shell temperature
JAddNumberToObject(body, "gal_per_day",      14.1);
JAddNumberToObject(body, "days_until_empty", 14.1);
JAddNumberToObject(body, "transmitter_ma",   14.1);  // current transmitter output current
ok_status = notecard.sendRequest(req);
// ...
J *req = notecard.newRequest("env.template");
J *body = JAddObjectToObject(req, "body");
JAddNumberToObject(body, "tank_capacity_gal",             14.1);
// ...
JAddNumberToObject(body, "sample_interval_min",           22);   // 2-byte unsigned int (1–1440)
JAddNumberToObject(body, "report_interval_hr",            21);   // 1-byte unsigned int (1–168)
// ...
JAddStringToObject(body, "wifi_ssid",                     TSTRINGV);  // variable-length string
JAddStringToObject(body, "wifi_password",                 TSTRINGV);
ok_env = notecard.sendRequest(req);

The Note.template API documentation has the full reference on Notecard template codes.

Key code snippet 2: 4-20 mA level transmitter current → fill percentage → fill gallons

computeFillPct (in propane_tank_telemetry_helpers.h) converts the float-type LP gauge-port transmitter current to fill percentage with a linear interpolation between the configured empty and full calibration points, and computeFillGal scales that to gallons. There's no density or temperature correction, because the float rides the liquid surface directly and its current output is already an accurate fill reading across the full operating temperature range.

// Convert 4-20 mA float-type level transmitter current to fill percentage (0–100 %).
// ...
// A simple linear interpolation converts the transmitter current to fill %:
//   fill_pct = (current_ma − sensor_empty_ma) / span × 100
//
// Returns NAN if current_ma is NAN (transmitter fault).
static float computeFillPct(float current_ma,
                             float sensor_empty_ma, float sensor_full_ma) {
  if (isnan(current_ma)) return NAN;
  float span = sensor_full_ma - sensor_empty_ma;
  if (span < 0.1f) return NAN;
  float fill_pct = (current_ma - sensor_empty_ma) / span * 100.0f;
  return fmaxf(0.0f, fminf(100.0f, fill_pct));
}

// Convert fill percentage to gallons via a simple linear scale.
// ...
static float computeFillGal(float fill_pct, float tank_capacity_gal) {
  if (isnan(fill_pct)) return NAN;
  return (fill_pct / 100.0f) * tank_capacity_gal;
}

In runSampleCycle() the call is:

float fill_pct = computeFillPct(xmtr_ma, SENSOR_EMPTY_MA, SENSOR_FULL_MA);

The firmware still reads temperature on every cycle for the daily summary, but it doesn't pass it to the fill calculation.

Key code snippet 3: sleeping until the Notecard raises ATTN

setup() arms the ATTN wake once with cxSleepBegin(). Each pass through loop() then runs the per-wake configuration and one sample cycle, and cxSleepUntilAttn() asks the Notecard to hold ATTN low for exactly SAMPLE_INTERVAL_MIN × 60 seconds, confirms the pin has gone low, and puts the STM32 into STOP2. Since the host stays alive, the firmware checks the result of the card.attn request instead of firing it off and forgetting it. The Notecard's ATTN pin brings the host back on schedule, and loop() carries on with the next sample.

// Wake from STOP2 on the ATTN rising edge.
cxSleepBegin();

// ...

void loop() {
  // Sample sensors and evaluate thresholds, then sleep until the Notecard
  // raises ATTN SAMPLE_INTERVAL_MIN × 60 s from now.
  perWakeConfigure();
  runSampleCycle();
  state.cycles++;

  uint32_t sleep_sec = (uint32_t)SAMPLE_INTERVAL_MIN * 60UL;
  if (!cxSleepUntilAttn(notecard, sleep_sec, NULL, &usbSerial)) {
    // The Notecard didn't take the sleep request, or ATTN never went low
    // (check the ATTN -> D5 jumper). Keep the sample cadence and try again.
    delay(sleep_sec * 1000UL);
  }
}

8. Data Flow

Data flow: 15-min sample of 4–20 mA loop current → fill % and consumption EWMA → two rules (low_fill, sensor_fault) → tank_alert.qo (sync:true) and tank_status.qo (daily templated) → Notehub routes

Every sample_interval_min (15 min by default) the host wakes, reads the LP gauge-port level transmitter and DS18B20 temperature probe, converts the transmitter current directly to fill %, updates the consumption EWMA, and evaluates three alert conditions.

Collected. Fill percentage (from the 4-20 mA float-type level transmitter current, linearly interpolated between the configured empty and full calibration points), fill gallons (fill % × tank capacity), tank shell temperature (DS18B20 °C, included in every summary for seasonal demand analytics), raw transmitter current (mA, for diagnostics), smoothed daily consumption rate (gal/day), and projected days-until-empty.

Transmitted.

  • tank_status.qo: one templated Note per report_interval_hr (daily by default). It carries the current (most recent valid) fill_pct, fill_gal, and transmitter_ma instead of window averages, so a refill or a sharp draw-down shows up accurately at reporting time. Alongside those, it includes min_fill_pct (the lowest fill percentage seen during the window, for analytics), window-averaged temp_c (the day's thermal environment), the current EWMA gal_per_day (a running smoothed consumption estimate), and the derived days_until_empty (current fill gallons divided by the EWMA rate). The Notes are batched and synced in a single cellular session, for 365 Notes per tank per year.
  • tank_alert.qo: sent with sync:true when a threshold trips, skipping the outbound timer. It's suppressed for alert_cooldown_hr after each firing so nobody gets alarm fatigue.

Routed. Notehub sends tank_alert.qo to whatever real-time channel the dealer's operations team uses (a dispatch system webhook, SMS gateway, or paging service) and tank_status.qo to a time-series store that feeds historical trend analysis and route-density modeling.

Alerts trigger on.

  • low_fill: fill percentage drops below fill_alert_pct (default 20 %). It fires once per alert_cooldown_hr until the tank is refilled.
  • high_consumption: the smoothed daily consumption rate has exceeded consumption_alert_gal_per_day (default 100 gal/day) for consumption_alert_streak consecutive sample cycles (default 3). The streak debounce prevents false positives from transient ADC jitter or short-lived post-refill consumption spikes, and the counter resets to zero any time the rate drops back below threshold or the transmitter reports a fault. At the 15-minute default sample rate, a streak of 3 means the high rate has to hold for at least 30 minutes before the alert fires. Most residential tanks use 3–15 gal/day in normal operation, so 100 gal/day sustained points to a possible leak or piping fault.
  • sensor_fault: transmitter current outside the valid 3.5–21 mA window. It points to wiring damage, a flooded enclosure, or a failed transmitter, and someone needs to inspect it in person.

Cloud-side usage model (high level). The dealer's analytics system receives daily tank_status.qo Notes with fill_gal and gal_per_day for every tank. The firmware computes a simple projection, days_until_empty = fill_gal / gal_per_day, and includes it in each Note, so the dealer's route planner can sort tanks by urgency without running any analytics locally. Route density optimization (grouping tanks within a delivery window by geography and urgency) belongs in the cloud, not the firmware. The device's job is to get accurate fill data into Notehub on time.

9. Validation and Testing

Expected cadence in steady state. A working unit on a residential propane tank should produce one tank_status.qo event per day and no tank_alert.qo events during normal operation. During commissioning, expect a sensor_fault event if the transmitter wiring isn't finished, and low-fill alerts if the tank already happens to be below threshold.

Bench validation before field deployment. To simulate the transmitter on the bench, drive the A0 analog input with a variable voltage in the 0.48–2.40 V range. A potentiometer from the 3.3 V rail to GND works, and so does a bench DC supply. Confirm the firmware maps 0.48 V to 0 % fill (4 mA), 1.44 V to 50 % fill (12 mA), and 2.40 V to 100 % fill (20 mA). Check that the open-circuit condition (A0 driven to 0 V or below 0.42 V, corresponding to < 3.5 mA) emits a sensor_fault alert Note. For the DS18B20, confirm the firmware reports a valid temperature on the serial port and that a missing probe produces NAN (which becomes the -9999 sentinel in summary Notes) instead of a garbage reading.

Commissioning calibration. Once the unit is on the tank, set tank_capacity_gal in the fleet's Notehub environment variables to the tank's rated usable capacity. Check that the fill percentage in Notehub matches an independent reference reading (the mechanical gauge, weight, or the LP technician's measurement) within a few percent. If there's a persistent offset that grows toward the high-fill end, the transmitter's span may not reach exactly 20 mA at the full-float position. Adjust sensor_full_ma to the transmitter's actual full-scale output current until the Notehub reading lines up with the reference. If the offset is the same across the full range (a roughly constant error from empty to full), the transmitter may have a non-standard live-zero. In that case, change sensor_empty_ma from its default 4.0 mA to match the transmitter's actual output at the empty (float-at-bottom) position. The fill calculation is a simple linear interpolation with no temperature correction, so the commissioning measurement is valid at any ambient temperature and doesn't need any special thermal condition.

Using Mojo to validate power behavior. Place the Mojo inline between the 5 V step-down output and the Notecarrier VBAT pad. The table below lists the expected current envelope on the 5 V rail for each major firmware state, along with where each figure comes from.

Firmware stateExpected current (5 V rail, Mojo)Source
Deep sleep (host in STOP2, Notecard idle, radio off)~10 µA @ 5 V~8 µA is the Blues-published idle figure for the NOTE-NBGLWX (see the low-power design guide and firmware best practices guide); the STM32L433 in STOP2 adds ~1–2 µA. The Mojo measures the entire powered subsystem (Notecard + host + Notecarrier CX regulators), so the bench reading will be modestly above the Notecard-only figure. Use trace shape and per-session energy as the main commissioning targets, not an exact match to the Notecard-only idle number.
Host awake and sampling (STM32 active, 16-sample ADC average, DS18B20 750 ms conversion, I²C Notecard call, ~5 s total)30–50 mABench estimate for the host subsystem only, not a Blues-published figure. Covers STM32L433 active-mode current, 12-bit ADC operation, DS18B20 conversion current, and I²C Notecard transactions. The exact value varies with supply voltage and MCU clock. Trace shape (a brief spike every sample_interval_min, then flat near zero) is a more reliable commissioning indicator than the absolute mA reading.
Notecard network session over cellular (or satellite), small queued Note, good signalin-session average ~250 mA from the onboard modem; brief peaks up to ~2 A for a few msNotecard for Skylo's Quectel BG95-S5 modem draws on the order of ~250 mA average during a network session (cellular and satellite are similar in magnitude), with brief higher peaks. A 2G transmit burst can pull nearly 2 A for a few milliseconds (see the Blues low-power hardware design application note). The Pololu D24V22F5 step-down (2.5 A rated) and SLA battery in this design can comfortably source ≥ 2 A. A cellular session typically lasts 30–60 s, so expect a broad hump on the Mojo trace, not a sharp spike. Weaker signal or first-time network registration makes the session longer and raises per-session energy. The RSRP/SINR signal-quality table in the Blues low-power design guide shows how signal conditions affect mAh per session.

With a 15-minute sample and a 24-hour cellular sync, the Mojo trace should show a brief (~5 s) 30–50 mA spike every 15 minutes from host-awake sampling, plus a broader 30–60 s hump averaging ~250 mA once a day for the cellular sync. Between sample spikes the trace should sit flat at the ~10 µA idle floor. If the current stays elevated between spikes, the host isn't entering STOP2, so check the ATTN→D5 jumper and confirm the firmware was built with USB support set to None.

At the 15-minute default cadence, the expected 24-hour Mojo total comes from three places. (1) idle: ~10 µA Notecard + host-in-STOP2 floor × 24 h ≈ ~0.25 mAh. (The total 5 V rail idle, including Notecarrier CX regulator quiescent current, will read a bit higher at the bench.) (2) sampling: 96 host-awake wakes/day × ~5 s @ 30–50 mA = ~4–6.7 mAh (96 wakes × 5 s ÷ 3 600 s/h × 30–50 mA). (3) daily sync: ~250 mA × ~45 s ÷ 3 600 s/h ≈ ~3 mAh. That puts the expected daily total at roughly 7–10 mAh/day. If the Mojo's 24-hour total runs well above that range, the network session may be staying open longer than expected, or the Notecard may be in continuous mode instead of periodic. Confirm with hub.get.

The 4-20 mA transmitter loop runs off the 24 V boost converter circuit, so it does not show up on the Mojo trace (Mojo measures only the 5 V Notecarrier rail). For a complete energy audit of the transmitter loop, put a bench ammeter in series with the boost converter's Vin+ lead on the 12 V system rail. Counting boost converter losses, expect a continuous draw from the 12 V rail of approximately 110 mW (4 mA loop, empty tank) up to 550 mW (20 mA loop, full tank). You can read the 4–20 mA loop current itself directly in the serial debug output as xmtr_ma.

When operating over satellite (NTN). The session-duration and daily-energy figures above describe cellular sessions. When Notecard for Skylo falls back to the Skylo satellite link, the idle draw stays the same (~8 µA) and a satellite session draws a similar ~250 mA average from the same modem. Session duration, the number of sessions Skylo's duty-cycle rules allow per day, and per-session energy all differ from cellular, though. sync:true alert delivery depends on a satellite pass being available, so latency is minutes, not seconds. Each inbound sync also uses some of the bundled 10 KB satellite allocation, so widen report_interval_hr at satellite sites to stretch it. Validate solar panel sizing, battery capacity, and alert latency separately for any site expected to operate over satellite using the Satellite Best Practices guide before commissioning. Don't assume the cellular sizing figures in this section are enough.

10. Troubleshooting

No device appearing in Notehub after power-up.

  • Confirm the Notecard MAIN u.FL antenna is connected to an external antenna (not left stubbed internally). A missing or unplugged antenna prevents cellular registration entirely.
  • Check that PRODUCT_UID is defined in the firmware and matches the ProductUID shown on your project's tile or Settings page in Notehub.
  • Make sure the 5 V step-down puts out exactly 5.0 V (measured at the Notecarrier +VBAT pad before applying load).
  • Look at the serial console for Notecard and I²C errors. If the console isn't available, move the device somewhere with strong cellular signal (≥2 bars) and reboot.

Device appears in Notehub but no events are arriving.

  • Confirm the device shows a recent session timestamp in Notehub (Devices → [Your device] → Events → Device Activity). A stale timestamp means the device isn't connecting.
  • Check the Notecard's hub settings. With the Notecarrier CX's USB-C DIP switch set to NC, connect over USB-C, open the Notecard Playground, and send {"req":"hub.get"}. The response should show "mode": "periodic" and "outbound": 1440 (minutes, so 24 hours). Then send {"req":"hub.status"}. If that response includes an err field, the Notecard may not be properly associated with the project.
  • Make sure environment variables are being delivered by sending {"req":"env.get"} in Notecard Playground. If the response is empty, the device hasn't received the fleet's environment variables yet, which can take up to 48 hours at the default 48-hour inbound sync cadence (see §6 step 3).

Fill percentage is incorrect or drifts over time.

  • Confirm the tank capacity is set correctly in the tank_capacity_gal environment variable. Capacity doesn't affect the fill percentage, but a wrong value scales fill_gal and gal_per_day proportionally.
  • Check the transmitter wiring. The loop supply must come from the 24 V boost converter output (not the 12 V rail), and the junction between the transmitter − terminal and the shunt must connect to A0. With an empty tank (float at the bottom), A0 should read ~0.48 V on a meter, and with a full tank it should read ~2.40 V.
  • If the fill reading is consistently high or low across the full range, the transmitter may have a non-standard live-zero or span. §9 "Commissioning calibration" explains how to adjust sensor_empty_ma and sensor_full_ma.

Alerts are firing constantly, or false sensor_fault alerts.

  • A sensor_fault alert means the transmitter current is outside the 3.5–21 mA window (open circuit or short). Check the loop wiring. Both conductors from the transmitter should be connected and undamaged, and the shunt resistor should be solidly connected.
  • High-consumption alerts may be false positives after a refill event. The firmware requires consumption_alert_streak consecutive above-threshold cycles before alerting, so raise consumption_alert_streak in the environment variables to make it less sensitive to post-refill transients.
  • Increase alert_cooldown_hr to stretch the minimum hours between repeated alerts of the same type.

Very high or very low current readings in serial debug.

  • The firmware reads the transmitter current every sample cycle and prints it to the debug console (the LPUART on the Notecarrier CX debug jack via an ST-LINK; see §7). An empty tank should show ~4.0 mA, and a full tank ~20.0 mA. If readings are consistently outside that range, re-check the shunt wiring and the 24 V boost converter output voltage, which should be exactly 24 V at the transmitter + terminal with no load attached.

Battery drains quickly / device stops after a few hours.

  • Confirm the host is actually entering STOP2. The firmware calls cxSleepUntilAttn() after each sample cycle, and if it can't sleep, the host runs continuously and drains the battery in hours. Check the ATTN→D5 jumper (see §5 Step 9), and confirm the firmware was built with USB support set to None. With the USB CDC stack enabled and no USB host attached, the host leaves STOP2 within a millisecond of entering it.
  • If you used the Mojo for validation, make sure it's removed before field deployment, since it adds a continuous measurement load even during deep sleep.
  • For sites running over the Skylo satellite (NTN) link, review the Satellite Best Practices guide. Satellite session timing and duty-cycle behavior differ from cellular and may shift the energy budget, so size the battery and solar panel for the expected satellite session pattern.

WiFi is not connecting even after credentials are set.

  • WiFi credentials arrive through environment variables and take effect on the next inbound sync. At the default 24-hour report cadence, inbound syncs happen every 48 hours, so credentials may take up to 48 hours to reach the device. To speed that up, temporarily lower report_interval_hr to 1 hour, then restore the original value once you've confirmed the connection.
  • You can also set WiFi credentials over USB at the bench (see §6 step 3) before sealing the enclosure.
  • Notecard for Skylo's WiFi uses its onboard 2.4 GHz antenna, and a metal enclosure will weaken that signal. If WiFi fallback matters at this site, use a non-metallic enclosure or rely on cellular/satellite, which use the external MAIN antenna.

11. Limitations and Next Steps

This reference design covers the common case: a dealer instrumenting a tank fleet for demand-driven dispatch with a float transmitter at the gauge port, a temperature probe on the shell, and cellular (or satellite) backhaul. Every trade-off below was a deliberate scope choice, and each one has a clear path to extend it for a production rollout.

Simplified for the POC

Continuously-powered current loop. The Rochester Sensors M6300-LP + R6315-12 and similar LP gauge-port float transmitters use a continuously-powered 4–20 mA current loop. Running from the 24 V boost converter, the loop draws 96–480 mW from the 24 V rail (4 mA × 24 V to 20 mA × 24 V). With the boost converter's ≈ 87 % efficiency, the draw on the 12 V system rail runs continuously from ≈ 110 mW (empty tank) to ≈ 550 mW (full tank), which makes it the biggest load in the system power budget. In the worst case (full tank, 20 mA), the transmitter loop draws ≈ 550 mW for 24 h = ≈ 13.2 Wh/day from the 12 V rail. A 10 W solar panel at ≥ 4 h/day peak sun yields ≈ 40 Wh, well above the combined transmitter and electronics load for mid-latitude deployments. For low-sun environments or high-latitude winter deployments, size the panel to 20 W. The tank spends most of its time between 20–80 % fill (about 7–17 mA), so the draw typically sits between about 200 and 460 mW, below the 550 mW worst case.

Fill-gallons calculation uses a linear scale. computeFillGal computes fill_gal = (fill_pct / 100) × tank_capacity_gal. A horizontal cylinder's cross-section adds a small nonlinearity between liquid height and volume (the relationship curves near the top and bottom of the tank), and the firmware doesn't correct for it. A geometry correction table keyed to tank_inner_diameter_in could improve accuracy below ~20 % or above ~80 % fill, at the cost of another environment variable and more complex calibration. Across 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 the Skylo link only works if the Skylo-certified MAIN antenna is mounted outdoors with a clear view of the sky (northern hemisphere: the southern sky). It can't reach the satellite from under a metal obstruction. Satellite is also opt-in at the Notecard level. The firmware turns it on 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 its Notefile and environment variable templates before NTN works, so 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 there's a good sky-view antenna location before you rely 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. If the 4–20 mA wiring 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 fall outside the scope of the electronics design. Any connection to a propane pressure vessel must comply with NFPA 58 and applicable codes, and it must be performed by a licensed LP gas technician.

Consumption rate requires stable readings over time. The EWMA consumption rate only means something after several days of operation, so on first deployment days_until_empty may be unreliable until the EWMA converges. The firmware starts consumption at zero and doesn't report days_until_empty until it has at least two consecutive valid fill readings.

No flow meter. The firmware estimates consumption rate from successive fill readings, as a delta-volume over delta-time approximation. That's accurate enough for daily route planning but not for billing or high-precision leak detection. A turbine or ultrasonic flow meter at the regulator outlet would measure consumption directly, though integrating one would take an additional pulse-counting or analog input channel.

Mojo is bench-validation equipment only. The firmware doesn't read the Mojo's LTC2959 coulomb counter at runtime. If fleet-level power telemetry would help the dealer's operations team, adding cumulative mAh to the daily summary is a simple extension.

Production Next Steps

  • Transmitter calibration tool: a Notehub JSONata route transform that reads transmitter_ma from the first three Notes after provisioning and suggests a sensor_full_ma correction automatically, so nobody has to do 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. That 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 accounts for known demand patterns instead of only trailing-average consumption.
  • Over-the-air host firmware updates through Notecard Outboard DFU once the fleet gets large. Then you can push a threshold recalibration or a new alert type fleet-wide without a site visit.

12. Summary

The dealer who used to roll a truck every six weeks because the calendar said so now rolls one because a specific tank is at 22% and trending toward empty in nine days. The build is a float transmitter at the gauge port, a temperature probe on the shell, and a single Notecard for Skylo with cellular, satellite, and WiFi on one module. It reaches cellular near town and the Skylo satellite network at the remote cabin with nothing to swap, and a daily summary in Notehub lets every tank in the territory report on itself. That means fewer miles, fewer emergency calls, and no more Friday-night apologies to the customer whose heat just went out.

On This Page

  • 1. Project Overview
  • 2. System Architecture
  • 3. Technical Summary
  • 4. Hardware Requirements
  • 5. Wiring and Assembly
  • 6. Notehub Setup
  • 7. Firmware Design
    • Modules
    • Sensor reading strategy
    • Sensor selection rationale
    • Event payload design
    • Low-power strategy
    • Retry and error handling
    • Key code snippet 1: template definition
    • Key code snippet 2: 4-20 mA level transmitter current → fill percentage → fill gallons
    • Key code snippet 3: sleeping until the Notecard raises ATTN
  • 8. Data Flow
  • 9. Validation and Testing
  • 10. Troubleshooting
  • 11. Limitations and Next Steps
    • Simplified for the POC
    • Production Next Steps
  • 12. Summary

Resources

  • GitHub
  • Request More Info
Can we improve this page? Send us feedback
© 2026 Blues Inc.
© 2026 Blues Inc.
AboutDocsAPI ReferenceTermsPrivacy