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_rightCommercial Grease Interceptor Level Monitor

Commercial Grease Interceptor Level Monitor

Commercial Grease Interceptor Level Monitor 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/grease_interceptor_monitor/ so it can learn how the device works and help you adapt it to your hardware.

This project is a truck-roll reduction device for pumping providers who service commercial grease interceptors. A waterproof ultrasonic distance sensor in the access cover reports the fill level over cellular every 15 minutes. When the level hits a threshold, an alert goes straight to the Blues Notehub cloud service, so trucks get routed by how full each trap actually is instead of by a fixed calendar.

What you'll have at the end: A weatherproof, wall-mounted enclosure holding a Notecarrier CX, a Notecard Cell+WiFi, and an inline Blues Mojo coulomb counter. It samples a DFRobot ultrasonic sensor every 15 minutes and sends daily summaries (including the energy used in each window) and threshold alerts to Notehub. You can tune alert thresholds and sample intervals with fleet-level environment variables, without re-flashing.

This reference implementation is scoped to hydromechanical (HGI) and batch-collection interceptors without a fixed outlet weir. In those geometries the liquid surface rises predictably as FOG builds up, so the fill percentage is a direct proxy for pump-out urgency. Read §1 and §10 before you deploy on a conventional constant-level gravity interceptor, where a fixed weir holds the surface height steady no matter how deep the FOG layer gets.

1. Project Overview

The problem. Every commercial kitchen is legally required to install a grease interceptor (sometimes called a grease trap). It's a chamber plumbed into the kitchen drain line that catches FOG (fats, oils, and grease) before it reaches the municipal sewer. FOG collects as a floating layer at the top of the interceptor. Left alone, that layer eventually reaches the inlet pipe and starts flowing into the sewer. That's a violation, and it can bring fines, shutdowns, and backups into the kitchen floor drains.

To stay compliant, FSEs (food service establishments: restaurants, cafeterias, ghost kitchens, institutional food service) hire a pumping provider to vacuum the trap clean on a regular basis. The industry default is a fixed schedule, with the truck showing up every four weeks (or every two) no matter how full the trap is. But a slow-season week produces far less grease than a holiday rush. On a fixed schedule the pumper sometimes arrives when the interceptor is only 30% full, a truck roll that did nothing for compliance, and sometimes shows up after it has already overflowed. Neither one is good, and the FSE pays for every dispatch.

A fill-level sensor changes the economics. With a live reading, the pumping provider can dispatch trucks on condition instead of on a schedule. Interceptors that fill fast (high-volume kitchens, fryer-heavy menus) get serviced before they overflow, and slow-filling ones get serviced less often without the compliance risk. That means fewer wasted truck rolls, tighter routes, and a condition-based service the pumper can sell as a premium tier. This reference design targets hydromechanical (HGI) and batch-collection interceptors without a fixed outlet weir. In those geometries the top liquid surface rises predictably as FOG and wastewater accumulate, so a rising fill percentage is a meaningful proxy for pump-out urgency. If you're deploying on a conventional constant-level gravity interceptor, where an outlet weir holds the liquid surface nearly fixed regardless of FOG-layer depth, see the measurement-model warning below and §10.

warning

Read the measurement model before you deploy. The firmware measures the distance from the probe face to the top of the liquid/FOG surface and converts it to a "fill percentage" of the working liquid column. In a conventional constant-level grease interceptor, the outlet weir elevation fixes the working liquid height. The top surface stays nearly constant as FOG builds up beneath it, so a single top-down distance reading does not track FOG-layer thickness and does not map to regulatory pump-out criteria. You'll get the most useful readings in geometries where the top liquid surface does rise with accumulation (for example, hydromechanical or batch-collection interceptors without a fixed weir). On a conventional constant-level interceptor, treat fill_pct only as a proxy for liquid-level proximity, not as a compliance metric, and validate it in the field before you rely on the 75% alert threshold for dispatch decisions.

Why Notecard. Grease interceptors usually sit outside the building, in the rear yard or buried in a rear parking lot, or they're set into the floor of a basement utility room. None of those spots get reliable access to the restaurant's WiFi. A pumping provider also isn't one building owner deploying one device. It manages hundreds of independent FSE accounts spread across a city, each with its own WiFi network and IT contact (usually "the owner's nephew"), and each with a different level of willingness to hand network credentials to a pumping vendor. Cellular skips all of that. There's no access point to pair with or password to manage, and nobody has to chase an IT ticket. Notecard Cell+WiFi ships with a prepaid global SIM, so the same hardware and firmware deploy the same way at every FSE on a pumper's route, from a two-seat taqueria to a stadium commissary. WiFi stays available as an opportunistic fallback, with no firmware changes, for the rare utility-room install that happens to have building WiFi overhead.

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 small weatherproof electronics box mounts on the wall next to the interceptor access cover. This documented build targets indoor utility-room HGI installations with a standard 120 VAC wall outlet within ~1.5 m of the installation point. A DFRobot A02YYUW IP67-rated ultrasonic probe goes through a 22 mm clearance hole drilled in the interceptor's access cover (one cover penetration per installation). A P-clip holds it in place, and an IP67 silicone grommet and RTV seal it. The probe hangs below the cover, pointing at the liquid/FOG surface, and §5 walks through the full mechanical procedure. An external UL-listed 5 V DC wall adapter powers the box. Its low-voltage DC pigtail enters the sealed enclosure through a cable gland and connects directly to the Notecarrier CX +VBAT header pin. That keeps mains wiring out of the enclosure, and because VUSB stays absent, the Notecard reaches its lowest idle power floor (~8 µA between syncs). You don't drill into the interceptor tank body or drain piping or modify the drain line, and the only coordination with the building owner is "we're mounting a small sensor on your grease trap cover and a box on the wall next to it." For outdoor, rear-yard, or below-grade installations without accessible indoor power, see Limitations.

2. System Architecture

System architecture: Interceptor → A02YYUW probe → Edge enclosure (Notecarrier CX + STM32 host + Notecard) → Notehub → Routes

Device-side responsibilities. Inside the wall-mounted enclosure, the Notecarrier CX's STM32L433 host wakes every 15 minutes (configurable), reads the ultrasonic probe over hardware UART, converts the median distance to a fill percentage, and checks the alert threshold. Once per daily summary window it also reads the Mojo coulomb counter with card.power to capture the energy used in that window. When it's done, it hands any resulting Note to the Notecard over I²C and uses card.attn to ask the Notecard to wake it again after the sample interval. Then it sleeps in STM32 STOP2 (a few µA) until the Notecard's ATTN pin wakes it. Its runtime state (the running fill total, peak fill, and last alert and report timestamps) just stays in RAM, and execution picks up where it left off. Nothing gets marshaled to JSON for safekeeping, and no AT command ever touches the wire.

Notecard responsibilities. The Notecard holds Notes in its local queue and runs two independent schedules set by hub.set. Its outbound cadence (every 24 hours by default) flushes queued Notes to Notehub, and a fixed inbound cadence (every 2 hours, set by HUB_INBOUND_MIN) polls Notehub for updated environment variables. Anything tagged sync:true skips both windows and opens a session right away. Those same environment variables let a pumping provider retune interceptor depth, alert threshold, and sampling cadence across an entire route from a browser, without a reflash or a site visit.

Notehub responsibilities. Events travel over the Notecard's embedded global SIM to Notehub, which ingests them, stores every one, and runs the project's routes. Daily summaries and threshold alerts live in separate Notefiles so each can go to its own destination. grease_alert.qo goes to the dispatch endpoint that pages a truck, and grease_summary.qo goes to the analytics store that builds per-FSE fill trends.

Routing to the cloud (high level only). Notehub can route to HTTP, MQTT, AWS, Azure, GCP, Snowflake, and several other destinations. This project doesn't ship a specific downstream endpoint, since route setup depends on your project. See the Notehub routing docs for details.

3. Technical Summary

First Event in Minutes

  1. Flash the firmware (§7) with your ProductUID.
  2. Connect an ST-LINK to the Notecarrier CX debug jack and open its serial port at 115200 baud. The firmware is built with USB CDC off so the host can sleep, which puts debug output on the debug jack instead of USB-C (see §7).
  3. Take a tape measurement from the sensor face to the liquid surface.
  4. Override sample_interval_sec to 60 in the Notehub fleet environment variables (Fleet → Environment) so you get a reading every minute instead of every 15.
  5. Watch the serial output for [DBG] median distance mm: XXX on each wake. Compare it with your tape measurement. The two should match within 1–2 cm.
  6. Check Notehub events: Within a few minutes you should see a grease_summary.qo arrive, or a grease_alert.qo if you also lowered alert_threshold_pct to 5 to test the alert path.
  7. Restore sample_interval_sec to 900 before leaving the site.

Here's a sample Note from this device:

{
  "file": "grease_summary.qo",
  "body": {
    "fill_pct_avg": 42.3,
    "fill_pct_peak": 51.7,
    "fill_pct_now": 44.1,
    "valid_samples": 94,
    "power_mah": 248.6
  }
}

4. Hardware Requirements

PartQtyRationale
Notecarrier CX1Integrated carrier with an onboard STM32L433 host MCU, so you don't need a separate host board. The host sleeps in STOP2 between samples, and the Notecard's ATTN pin wakes it.
Notecard Cell+WiFi (MBGLW) (Datasheet)1Cellular-first connectivity means you don't depend on each site's WiFi, and WiFi fallback is there for utility-room installs with an accessible AP. Ships with a prepaid global SIM.
Blues Mojo1Required, permanently installed. LTC2959 coulomb counter wired inline on the +VBAT rail and connected to the Notecarrier CX Qwiic port. Notecard firmware (v8.1.3+) auto-detects it over I²C, and the host firmware reads per-window energy with card.power and reports it as power_mah in every daily summary (see §9).
Qwiic cable (4-pin JST-SH, 50–100 mm)1Connects the Mojo to the Notecarrier CX Qwiic port so the Notecard can read the coulomb counter over I²C. A short cable ships with most Mojo units, so check before you order.
DFRobot A02YYUW Waterproof Ultrasonic Sensor (SEN0311)1IP67-rated ultrasonic probe with UART output, a 3–450 cm range, and ≤8 mA average current. IP67 covers ingress protection against dust and temporary water immersion, so it handles splash and condensation. It does not address long-term chemical compatibility with the grease, H₂S, sewer gas condensate, or cleaning chemicals in an interceptor's atmosphere. This sensor's chemical durability in that environment hasn't been verified, so field-validate it before you commit to a deployment, or swap in a sensor with explicit chemical-resistance ratings for the target environment.
Hammond 1554W2GY enclosure, 180 × 180 × 66 mm, IP68 polycarbonate1Fits the Notecarrier CX (≈80 × 56 mm footprint) with room left for the Mojo and cable management.
SparkFun CEL-16432 LTE Hinged External Antenna, SMA male, 698 MHz–2.7 GHz1Hinged external antenna that mounts on the polycarbonate enclosure through an SMA bulkhead. It covers all MBGLW LTE Cat-1 bis bands across the 698 MHz–2.7 GHz range.
UL-listed 5 V / 2 A (min) regulated switching wall adapter with DC pigtail output, ≥ 1.5 m cable (any UL/CSA-listed 5 V, 2 A or higher regulated switching wall adapter with bare-wire or 2.1 mm center-positive barrel-jack output)1All mains wiring stays outside the enclosure, and only low-voltage DC comes in through the cable gland. The positive lead connects to the Notecarrier CX +VBAT pad and the negative lead to GND. That keeps VUSB absent, so the Notecard reaches its lowest idle current (~8 µA between cellular syncs). The 2 A minimum rating means the supply can handle the MBGLW's ≤2 A peak transmit bursts without browning out. If your adapter has a 2.1 mm barrel-jack output, use a short 2.1 mm pigtail-to-stripped-lead adapter cable inside the enclosure. Do not use a USB charger: USB power shows up at the CX USB-C port (VUSB present), which keeps the Notecard from reaching its lowest idle power floor.
M16 cable gland, IP68-rated2One goes in the enclosure wall for the sensor cable (it seals the four bare sensor wires after you cut off the PH2.0 connector; see Wiring), and the other for the DC power pigtail. M16 glands seal cables up to approximately 10 mm OD, so confirm your adapter's cable jacket fits before drilling. The interceptor cover penetration uses a wider opening and a bracket/grommet mount instead. See the BOM rows below and the Wiring section.
Silicone boot grommet, 22 mm OD / 19 mm ID (or nearest available; must grip a ~19 mm cylindrical probe body), IP67-rated1Seals the 22 mm cover penetration around the A02YYUW probe body. The probe head is ~19 mm in diameter and can't pass through an M16 cable gland bore, so it needs a wider opening and a grommet.
Two-piece P-clip or saddle clamp, 19 mm bore, stainless or nylon1Holds the probe body from above the interceptor access cover after insertion. It keeps the probe from sliding into the chamber and holds the probe face at the correct depth below the cover.
Neutral-cure RTV silicone sealant (food-safe / H₂S-resistant, e.g., Permatex #80050 or equivalent)1 small tubeSeals around the probe body at the cover penetration and around the gland bodies. Apply it after the probe is in its final position, and let it fully cure before replacing the cover.
Female DuPont crimp contacts, 2.54 mm pitch, 4-position housing with crimp pins (or 4 × female-to-female 2.54 mm jumper wires, one end cut and stripped)1 setTerminates the four stripped sensor leads so they plug onto the Notecarrier CX's 2.54 mm header pins.

All Blues hardware ships with an active SIM that includes 500 MB of data and 10 years of service, with no activation fees and no monthly commitment.

5. Wiring and Assembly

warning

⚠️ Wastewater and sewer gas safety. Grease interceptors build up hydrogen sulfide (H₂S) and other sewer gases that are toxic at low concentrations and flammable at higher ones. Before you open any access cover, ventilate the area, test with a gas monitor if you have one, keep ignition sources clear, and wear appropriate PPE (nitrile gloves, eye protection). Don't enter a below-grade vault. Confined-space entry requires dedicated procedures, a gas monitor, a standby person, and, in many jurisdictions, a permit. This reference design mounts the probe from above with the cover ajar, so nobody ever has to enter the interceptor chamber.

⚠️ Confirm the hazardous-location classification before deployment. The A02YYUW probe and all wiring and electronics in this build are standard, non-intrinsically-safe (non-IS) components with no NEC Article 505/506 (Class/Zone), ATEX, or IECEx certification. Local electrical code (NEC, NFPA 820, or equivalent) may prohibit hanging energized, non-IS electronics in an interceptor atmosphere that carries H₂S or flammable sewer gases. Whether a given installation counts as a classified hazardous location must be decided site by site by a qualified licensed electrician or the local authority having jurisdiction (AHJ). Don't assume an installation is unclassified without a documented review. This reference design is suitable only for non-classified installations, and only after a local code and site-safety review is complete and documented. Classified hazardous-location installations require intrinsically safe (IS) or explosion-proof (XP) sensors, certified IS barriers, appropriately rated enclosures, and installation by personnel qualified for hazardous-area work.

All host I/O lands on the Notecarrier CX dual 16-pin header. The Notecard Cell+WiFi seats in the CX's M.2 slot, and the SparkFun CEL-16432 hinged LTE antenna mounts on the outside of the polycarbonate enclosure through an SMA bulkhead connector. The Blues Mojo coulomb counter is a permanent part of the deployed unit. It's wired inline on the +VBAT rail, so it integrates the whole-board current, and connected to the Notecarrier CX Qwiic port so the Notecard can read it over I²C. The Notecard auto-detects the Mojo, and the firmware uses card.power to report per-window energy use (power_mah) in every daily summary. §9 covers the wiring detail and validation procedure.

The A02YYUW sensor has a 2-meter cable ending in a 4-pin PH2.0 connector: VCC (red), GND (black), RX (yellow, mode-select), and TX (white, UART data out). Cut off the PH2.0 connector, because its molded housing is wider than the bore of the M16 enclosure gland and won't pass through. Strip 8 mm from each wire and feed the four bare ends through the enclosure's M16 cable gland from outside. Tighten the compression nut on the cable jacket, then crimp a female 2.54 mm DuPont contact onto each stripped lead and seat them in a 4-pin housing (or individual housings). That terminated end plugs onto the Notecarrier CX's 2.54 mm header as described below.

Here's the pin-by-pin wiring:

  • +3V3_OUT → A02YYUW VCC (red). +3V3_OUT is the exact label on the Notecarrier CX dual 16-pin header, and it supplies 3.3 V at up to 100 mA. The sensor's ≤8 mA average draw is well within that limit.
  • GND → A02YYUW GND (black) and A02YYUW RX (yellow). Tying the sensor's RX pin to GND selects real-time continuous output mode, where the sensor streams packets as fast as it measures. You can also leave the RX pin floating, since the internal pull-down produces the same behavior.
  • RX header pin → A02YYUW TX (white). RX is the exact label on the Notecarrier CX header for the host's hardware UART receive line. When the firmware is built for the Notecarrier CX's onboard STM32 host, it assigns Serial1 to this UART instance, which is the right mapping for the standard target. If you retarget the sketch to a different STM32 board or core variant, check that Serial1 maps to that board's RX/TX header pins before wiring.
  • ATTN → 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.
  • +VBAT pad → the Mojo's output, with the Mojo spliced inline on the positive rail: DC wall adapter positive lead (red or marked +5V) → Mojo input; Mojo output → CX +VBAT pad. The adapter negative lead connects to GND. All board current runs through the Mojo this way, so it measures whole-board draw. Do not connect the CX's USB-C port to any power source during normal operation. VUSB has to stay absent for the Notecard to reach its lowest idle power floor (~8 µA). §9 lists the exact Mojo terminal labels.
  • Qwiic port → Mojo Qwiic connector. A 4-pin JST-SH Qwiic cable from the Notecarrier CX Qwiic port to the Mojo lets the Notecard read the coulomb counter over I²C. You don't need any other configuration, because the Notecard auto-detects the Mojo.

Power entry. The DC wall adapter plugs into a standard wall outlet outside the enclosure, and only its low-voltage DC pigtail enters the box. Drill an M16 clearance hole in the enclosure wall for the DC cable, fit the M16 gland body from outside, and secure it with its locknut from inside. Thread the DC pigtail through the gland from outside and tighten the compression nut on the cable jacket so it grips and strain-relieves the cable. Inside the enclosure, trim the leads to length and strip 8 mm of insulation from each. Connect the positive lead to the CX +VBAT pad and the negative lead to GND, either with female 2.54 mm DuPont crimp contacts or by soldering directly to the header pads. If your adapter has a 2.1 mm barrel-jack output, use a short barrel-to-DuPont pigtail adapter and connect it the same way. Since there's no mains voltage inside the enclosure, no insulation clearance, creepage, or earth-bonding requirements apply to the DC wiring.

Sensor cable entry and probe mounting. ⚠️ The A02YYUW transducer head is approximately 19 mm in diameter, so it will not pass through an M16 cable gland bore (typically 13 mm maximum insert diameter). Don't try to mount the probe through an M16 gland. Use this bracket-and-grommet approach instead:

  1. Mark and drill. Center-mark the interceptor access cover over the chamber opening. Drill a 22 mm clearance hole. A 22 mm step drill or bi-metal hole saw works on cast-iron, fiberglass, and polymer covers. If the cover already has a plugged service port of 22 mm or larger, clean it out and reuse it instead. Deburr the hole edge.
  2. Thread the cable through first. Feed the bare (connector-stripped) sensor leads through the 22 mm hole from above. The cable jacket passes through easily, and the probe head stays above the cover for now.
  3. Seat the grommet. Press a 22 mm OD / 19 mm ID IP67-rated silicone boot grommet into the hole from above. It should sit flush with the cover surface, and its inner bore will grip the probe body with light friction once the probe goes in.
  4. Insert the probe. Push the probe body down through the grommet from above, face pointing down, until the transducer face is at least 30 mm below the underside of the cover. (30 mm is the sensor's minimum blind zone, and anything closer returns invalid data.) The cable now comes out the top, above the cover.
  5. Secure with a P-clip. Fit a two-piece 19 mm bore P-clip or saddle clamp around the probe body flush against the top of the cover. Tighten the clip so the probe can't slide down into the chamber and the face-to-cover distance stays fixed. After tightening, confirm the transducer face is still at least 30 mm below the underside of the cover.
  6. Seal with RTV. Apply a continuous bead of neutral-cure RTV silicone sealant around the probe body at the grommet–cover interface on both the upper and lower face. Let it cure fully (typically 24 hours) before you replace the access cover and close the hatch.

Run the cable from the cover to the enclosure on the adjacent wall, and bring it in through the enclosure's M16 cable gland as described in the sensor cable prep above.

Wiring diagram: A02YYUW sensor → Notecarrier CX header pins; ATTN → D5 jumper so the Notecard can wake the host from STOP2; 5 V DC wall adapter → +VBAT pad; CEL-16432 antenna → SMA on Notecarrier CX

6. Notehub Setup

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

  2. Claim the Notecard. Power up the unit, and the Notecard joins your project automatically on its first cellular connection.

  3. Create a Fleet per pumping route. Fleets are how Notehub groups devices for shared configuration and routing. One fleet per service route fits well here. Interceptors on the same truck route probably share similar sizes and fill cadences, so fleet-level environment variables can hold route-wide defaults, and you override them per device for unusual installations. Smart Fleets can auto-assign devices based on FSE metadata tags.

  4. Set environment variables. Every variable below is optional, and the table shows the firmware defaults. Any value you set in Notehub overrides the compile-time default on the device's next inbound sync, with no re-flashing.

    VariableDefaultPurpose
    interceptor_depth_mm600Distance (mm) from the sensor face to the liquid surface immediately after pump-out (0% grease fill). Measure it once per installation during commissioning, since it varies by interceptor model and probe mounting height.
    alert_threshold_pct75Fill percentage at or above which a grease_alert.qo Note fires. On HGI units without a fixed weir, the fill percentage reflects the combined liquid-plus-FOG working volume, so this threshold maps directly to pump-out urgency. Calibrate it during commissioning by watching what fill level your target service interval produces. The default 75% is a reasonable starting point for most HGI geometries. See §10 if you're deploying on a conventional constant-level interceptor.
    sample_interval_sec900Seconds between distance readings (default 15 minutes). Grease builds up over hours to days, so 15 minutes is plenty of resolution.
    report_interval_min1440Minutes between summary Notes (default 24 hours). Whenever this value changes, the firmware re-issues hub.set to keep the Notecard's outbound sync cadence in step with the local summary period. Lower it to 360, for example, and summaries go out every 6 hours, with the outbound batch window shrinking to match. The inbound cadence (environment-variable polling every 2 hours) doesn't depend on this setting and stays the same.
  5. Configure routes. Add one route for grease_alert.qo that handles real-time dispatch notification (a webhook to a field-service platform, an SMS gateway, or a dispatch email), and a second that sends grease_summary.qo to a long-term analytics store. Because the two Notefiles are separate at the source, each can go to a different destination without any filter logic in the route itself.

7. Firmware Design

Building and Flashing

  1. Clone this repository and open the sketch in the Arduino IDE, or use arduino-cli from the command line.
  2. Install dependencies:
    arduino-cli lib install "Blues Wireless Notecard" "STM32duino Low Power" "STM32duino RTC"
    arduino-cli core install STMicroelectronics:stm32
  3. Fit the ATTN-to-D5 jumper on the Notecarrier CX header (see §5) so the Notecard can wake the host from sleep.
  4. Set your Product UID: Edit grease_interceptor_monitor.ino and paste your Notehub ProductUID between the empty quotes on this line. The comment shows the format it takes.
    #define PRODUCT_UID ""  // "com.your-company.your-name:your_project"
  5. Build and upload:
    arduino-cli compile -b STMicroelectronics:stm32:Blues:pnum=CYGNET,usb=none firmware/grease_interceptor_monitor/
    arduino-cli upload -b STMicroelectronics:stm32:Blues:pnum=CYGNET,usb=none -p /dev/ttyACM0 firmware/grease_interceptor_monitor/
    (Replace /dev/ttyACM0 with your serial port. arduino-cli board list will find it.) The usb=none board option disables the USB CDC stack, which has to be off for the host to sleep (see "Build settings" below). firmware/grease_interceptor_monitor/sketch.yaml sets the same board options, so running arduino-cli compile in that directory without -b picks them up too.
  6. Monitor the serial output on the ST-LINK virtual COM port (Notecarrier CX debug jack) at 115200 baud to check sensor readings and Notecard communication.

Firmware files:

FilePurpose
grease_interceptor_monitor.inoMain sketch: setup() / loop(), Notecard configuration, env-var fetch, alert/summary scheduling, sleep
grease_interceptor_monitor_helpers.hShared constants (SENSOR_BAUD, NUM_READINGS, …), State struct definition, utility-function declarations
grease_interceptor_monitor_helpers.cppUtility-function implementations: sensor read, median filter, distance-to-fill, Notecard response helpers, Note emission
cx_sleep.hHost sleep: card.attn request, STOP2 entry, ATTN wake

Dependencies:

  • Arduino core for STM32 (stm32duino/Arduino_Core_STM32).
  • Blues Wireless Notecard (note-arduino). Install it from the Arduino Library Manager (arduino-cli lib install "Blues Wireless Notecard") or download it from the releases page.
  • 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.

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

ResponsibilityFunction / symbolFile
Notecard configuration (hub.set, accelerometer disable)notecardConfigure.ino
Note template definitiondefineTemplates.ino
Environment variable fetch; re-applies hub.set when report_interval_min changesfetchEnvOverrides.ino
UART sensor read with packet validationreadDistanceMm_helpers.cpp
Median filter over multiple readingsmedianOf_helpers.cpp
Distance-to-fill-percent conversiondistanceToFillPct_helpers.cpp
Notecard response validation and error loggingnotecardResponseOk_helpers.cpp
Threshold evaluation and alert emissioninline in loop, sendAlert.ino / _helpers.cpp
Daily summary accumulation and emissioninline in loop, sendSummary.ino / _helpers.cpp
Host sleep (STOP2 until the Notecard raises ATTN)cxSleepBegin, cxSleepUntilAttncx_sleep.h
Application state (held in RAM across sleep cycles)State and Config structs_helpers.h / .ino

Sensor reading strategy

The A02YYUW streams 4-byte UART packets continuously at 9600 baud: [0xFF][high][low][checksum]. The distance in mm is (high << 8) | low, and the checksum is (0xFF + high + low) & 0xFF. On each wake, the firmware flushes any bytes that piled up during sleep, syncs to the next valid start byte (0xFF), and reads a complete packet. Reflections off the interceptor walls can occasionally return a short or long reading, so to suppress those acoustic multipath artifacts the firmware takes five readings in a row and returns the median. Any reading below 30 mm or above 4500 mm gets rejected as outside the sensor's rated range. The firmware also applies an installation-specific upper bound, rejecting anything above interceptor_depth_mm × 1.1. A longer distance means a lower surface, so that 10% headroom past the 0% fill reference lets a surface sitting a little below its pump-out level still read as 0% fill, while obviously bad long readings get thrown out. Near-overflow readings are short, so this gate never touches them. If interceptor_depth_mm is set more than about 10% shorter than the true sensor-to-surface distance at pump-out, this gate rejects every sample from a freshly pumped trap, valid_samples stays at zero, and the firmware produces no summary Note. The commissioning-depth diagnostic in §9 covers this case.

Event payload design

The device sends one template-backed daily summary Note (grease_summary.qo). It also sends an immediate alert (grease_alert.qo) whenever fill_pct is at or above the alert threshold and the 1-hour cooldown has elapsed, so a new alert fires every cooldown interval for as long as the interceptor stays above threshold. The template fixes each summary to a compact binary record (approximately 32 bytes on the wire). With sensors installed for years in hundreds of interceptors, that saving adds up over a full deployment. "Example payloads routed to Notehub" in §8 below shows the payload shape.

Low-power strategy

A back-of-house HGI installation has mains power, but the firmware still puts the host to sleep between samples. That means less heat in the enclosure, and the same firmware pattern ports to a solar- or battery-backed variant without a redesign. After each sample cycle, loop() calls cxSleepUntilAttn() (in cx_sleep.h). That function sends a card.attn sleep request for sample_interval_sec seconds, waits for the Notecard to pull ATTN low, and puts the STM32 host into STOP2, where it draws a few microamps and keeps its RAM. 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(). The host resumes in place instead of cold-booting, so the State and Config structs just live 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 itself idles at roughly 8 µA between cellular wakes when it's powered through +VBAT with VUSB absent. This build gets there by routing the 5 V DC pigtail from the wall adapter to the CX's +VBAT header pin instead of its USB-C port. The A02YYUW draws ≤8 mA from the +3V3_OUT pin, and the firmware doesn't switch sensor power. Putting the host into STOP2 doesn't touch the +3V3_OUT rail either (it's part of the CX's shared VIO rail, which stays enabled), so the sensor stays powered while the host sleeps. Treat the sensor as a continuous ~8 mA load when you size the power budget.

A continuous 8 mA sensor draw adds up to roughly 192 mAh over a 24-hour day. That's far more than a single daily LTE Cat-1 bis sync (~250 mA average for ≤60 seconds ≈ 4 mAh). The cellular sync is the biggest current spike, but the always-on sensor uses the most energy over a day. That makes sensor power switching, with a GPIO-controlled load switch on the sensor supply rail, the first optimization to pursue before moving to a battery-backed installation (see §10). Confirm the budget on real hardware with Mojo (see §9 Mojo validation).

Sampling and summary cadence are decoupled on purpose. The sensor fires every sample_interval_sec (15 minutes by default, or 96 times a day), but outbound summary syncs happen only once per report_interval_min (24 hours by default). Separately, the Notecard opens an inbound session every 2 hours (HUB_INBOUND_MIN = 120) to poll Notehub for updated environment variables. Each inbound session needs a full radio wake and session setup, so budget for them in any power analysis (see §9). At the default 2-hour inbound cadence, expect up to 12 inbound wakes a day on top of the single daily outbound sync and any alert syncs. Alert Notes set sync:true and skip both scheduled windows, waking the radio right away every time an alert fires. That repeats every cooldown interval as long as fill stays at or above threshold.

Typical power draw at 5 V DC (bench, with 5 V wall adapter): The always-on A02YYUW sensor uses the most, at approximately 8 mA continuous (~192 mAh over 24 hours). The Notecard idles at ~8 µA between syncs. One daily outbound sync (LTE Cat-1 bis, ~30–60 seconds at ~250 mA average) adds roughly 2–4 mAh, and 12 daily inbound polls (~15 seconds each at similar current) add approximately 12.5 mAh. Conservative daily budget: ~210 mAh. A UL-listed 2 A 5 V wall adapter (the recommended minimum) can sustain the Notecard's 2 A peak transmit bursts indefinitely and leaves margin for future expansion. Before you build any battery-backed variant, validate with the Mojo coulomb counter (§9) to confirm how the sensor rail behaves during host sleep.

Retry and error handling

  • Sensor reads that fail checksum, time out, or fall out of range (below 30 mm, above 4500 mm, or above interceptor_depth_mm × 1.1) are left out of the rolling average and peak. The firmware needs at least two valid readings out of five before it computes a fill percentage. With fewer than two, it silently skips the sample window and emits no Note for it, though it still calls env.get and card.time on every wake. No sentinel values get written, so bad data is simply missing from that sample window.
  • The alert cooldown (ALERT_COOLDOWN_SEC = 3600) keeps a near-threshold interceptor from triggering a dispatch notification every 15 minutes. One alert an hour is plenty to escalate a real overflow risk.
  • The firmware calls env.get with a names array on every wake, so the response always reflects the operator's current values no matter which variable was most recently updated on the server.
  • Whenever report_interval_min changes, fetchEnvOverrides immediately re-issues hub.set with the new outbound value so the Notecard's cellular sync cadence stays in step with the local summary period. Otherwise, summaries queued at the new (shorter) interval would sit in the Notecard's store until the old (longer) outbound window fired.

Note template format codes (abbreviated syntax)

Notecard templates use numeric codes to mark field types, and this firmware uses two of them:

  • TFLOAT32 (14.1): 4-byte IEEE 754 single-precision float
  • TUINT32 (24): 4-byte unsigned integer

The numeric code carries both byte width and signedness. For example, 14 is a 4-byte signed integer (TINT32), while 24 is a 4-byte unsigned integer (TUINT32). The note-c library that ships with the Blues Wireless Notecard library defines the named macros (TFLOAT32, TUINT32, and so on), so the firmware uses the names and the wire-format numbers stay an internal detail. See Notecard template field types for the full reference.

Key code snippet 1: Note template definition

The template makes each summary a fixed-length record. defineTemplates() checks the reply, and loop() retries it on every wake until the Notecard accepts it.

J *req = notecard.newRequest("note.template");
JAddStringToObject(req, "file", "grease_summary.qo");
JAddNumberToObject(req, "port", 50);
J *body = JAddObjectToObject(req, "body");
JAddNumberToObject(body, "fill_pct_avg",  TFLOAT32);  // 4-byte float
JAddNumberToObject(body, "fill_pct_peak", TFLOAT32);
JAddNumberToObject(body, "fill_pct_now",  TFLOAT32);
JAddNumberToObject(body, "valid_samples", TUINT32);   // 4-byte unsigned integer
JAddNumberToObject(body, "power_mah",     TFLOAT32);  // mAh consumed this window (Mojo)
J *rsp = notecard.requestAndResponse(req);
bool ok = notecardResponseOk(rsp);
notecard.deleteResponse(rsp);

Key code snippet 2: immediate-sync alert

sync:true tells the Notecard to skip the outbound batch window and open a cellular session as soon as the Note is queued, usually within 15–60 seconds of the threshold trip.

J *req = notecard.newRequest("note.add");
JAddStringToObject(req, "file", "grease_alert.qo");
JAddBoolToObject(req,   "sync", true);
J *body = JAddObjectToObject(req, "body");
JAddStringToObject(body, "alert",        "fill_threshold_exceeded");
JAddNumberToObject(body, "fill_pct",      fill_pct);
JAddNumberToObject(body, "threshold_pct", threshold_pct);
J *rsp = notecard.requestAndResponse(req);
bool ok = notecardResponseOk(rsp);
notecard.deleteResponse(rsp);
return ok;

sendAlert() makes a single attempt. If the Notecard doesn't accept the Note, loop() leaves the cooldown timestamp alone, so the next wake tries again as long as the fill is still at or above the threshold. An immediate retry could send a duplicate alert if the Note was queued but only the I²C reply got lost.

Key code snippet 3: sleeping until the Notecard raises ATTN

setup() arms the ATTN wake once with cxSleepBegin(). At the end of every loop(), cxSleepUntilAttn() asks the Notecard to hold ATTN low for sample_interval_sec 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 and forgetting it. When the Notecard raises ATTN, the firmware resumes exactly where it left off, with the fill accumulator, peak, timestamps, and everything else still in RAM.

// Arm the ATTN wake: the Notecard raises ATTN (D5) to end each sleep.
cxSleepBegin();

// ...

// Sleep in STOP2 until the Notecard raises ATTN sample_interval_sec
// seconds from now. Execution resumes here; state and cfg stay in RAM.
if (!cxSleepUntilAttn(notecard, cfg.sample_interval_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(cfg.sample_interval_sec * 1000UL);
}

8. Data Flow

Data flow: 15-min sample → evaluate threshold and window → grease_alert.qo (sync:true) / grease_summary.qo (daily, templated) → Notehub → routes

Every 15 minutes the host wakes, fires the sensor five times, takes the median distance, and converts it to a fill percentage. That reading goes into the rolling daily accumulator, and then two conditional paths run in parallel:

  • Threshold alert. If fill_pct >= alert_threshold_pct and at least an hour has passed since the last alert, the firmware queues a grease_alert.qo Note with sync:true. The Notecard opens a cellular session right away and delivers it to Notehub, which routes it to the dispatch endpoint.
  • Daily summary. Once every report_interval_min minutes (24 hours by default), the firmware queues a grease_summary.qo Note with the average fill percentage over the period, the peak fill percentage, the most recent instantaneous reading, and the count of valid samples. The firmware keeps the Notecard's outbound sync cadence in step with report_interval_min, so the Note ships on the next outbound window, which lines up with the summary period.

Collected: The distance from the sensor face to the top of the liquid/FOG surface (mm), the fill percentage derived from that distance, and a timestamp from the Notecard's synced clock. On HGI units without a fixed weir, the fill percentage tracks combined liquid-plus-FOG accumulation. See §10 for how it behaves on other interceptor geometries.

Transmitted:

  • grease_summary.qo: once per report_interval_min (outbound, 24 h by default), templated, and delivered in the Notecard's next scheduled outbound sync.
  • grease_alert.qo: fires with sync:true whenever fill_pct >= alert_threshold_pct and the 1-hour cooldown has elapsed, and keeps firing hourly for as long as the interceptor stays above threshold.
  • Inbound sessions: separately from the outbound cadence, the Notecard also wakes and polls Notehub every 2 hours (HUB_INBOUND_MIN = 120) for updated environment variables. An inbound-only session sends no application data, but each one still costs radio energy (see §9).

Routed: Both Notefiles land in Notehub. grease_alert.qo goes to whatever real-time notification channel the pumping provider uses for dispatch (a service management platform webhook, email, or SMS), and grease_summary.qo goes to a long-term store for trend analysis and proactive scheduling.

Alert triggers on: fill_pct >= alert_threshold_pct (default 75%). The alert is level-triggered, not edge-triggered. A new alert fires each time ALERT_COOLDOWN_SEC (1 hour) runs out and the interceptor is still above threshold, so an interceptor that stays full sends repeated hourly alerts until someone services it.

Example payloads routed to Notehub

Daily summary (one per report_interval_min, templated, ~32 bytes):

{
  "file": "grease_summary.qo",
  "body": {
    "fill_pct_avg": 42.3,
    "fill_pct_peak": 51.7,
    "fill_pct_now": 44.1,
    "valid_samples": 94,
    "power_mah": 248.6
  }
}

Threshold alert (fires whenever fill_pct >= threshold_pct after cooldown, sync:true):

{
  "file": "grease_alert.qo",
  "body": {
    "alert": "fill_threshold_exceeded",
    "fill_pct": 76.4,
    "threshold_pct": 75.0
  },
  "sync": true
}

The two Notefiles are separate so you can route them to different endpoints, with summaries going to a long-term analytics database and alerts going to a real-time dispatch webhook or SMS gateway.

9. Validation and Testing

Expected Steady-State Behavior

On a healthy install, one grease_summary.qo event shows up in Notehub every 24 hours, and no grease_alert.qo events appear unless the interceptor really is close to full. The summary's valid_samples field is the most useful commissioning diagnostic. After the first full 24-hour reporting interval, a working unit should show roughly 96 valid samples at the default 15-minute interval. (The very first summary fires on cold boot with only the samples collected since power-on, so don't treat a low count in that first event as a fault.) A count well below 96 on later days points to intermittent sensor reads from cable length, probe positioning, or FOG reflectivity issues.

If a day's summary Note is missing from Notehub, don't jump to the conclusion that the firmware emitted nothing. A Note the device created correctly may not be visible in Notehub yet. The Notecard might not have finished an outbound sync for that period, or the device could be temporarily offline or somewhere with poor signal. Queued Notes might still be waiting for the next outbound window, or a Notehub route or forwarding step might have failed silently. Check the device-side state before you diagnose a firmware-level suppression. Query hub.status and card.status from the serial monitor or the in-browser Notecard Playground, or watch the firmware's debug output on the ST-LINK serial port during a live wake cycle and look for a note.add request with a reply that has no err field. If the Notecard confirms a successful note.add and shows a non-empty outbound queue, the firmware did its job and the gap is upstream (sync timing, connectivity, or routing).

Look for firmware-level suppression only if the outbound queue is empty and no note.add was attempted for the reporting window. In that case, the firmware held back the summary because valid_samples stayed at zero for the whole reporting window. It gates sendSummary on valid_samples > 0, so a complete read failure produces no Note at all instead of a Note with valid_samples: 0. Check the UART wiring, cable continuity, and the probe connector. Also confirm that interceptor_depth_mm isn't set more than about 10% shorter than the true sensor-to-surface distance at pump-out, because a value that low makes the firmware's interceptor_depth_mm × 1.1 acceptance gate reject every reading (see §7 sensor reading strategy).

Cold-Boot and Clock Sync

On first power-up the Notecard may not have synced its clock yet (card.time returns 0 until the first cellular session completes). Before the clock is available, the firmware allows at most one cold-boot summary and at most one cold-boot threshold alert, then holds further reports until time sync succeeds. That keeps repeated low-count summaries or threshold alerts from flooding Notehub before the device has a real timestamp. Once the Notecard syncs time, the normal interval-based cadence resumes. If the device sits in a poor-signal spot and takes several wake cycles to establish its first session, no extra summaries or alerts fire in the meantime. The fill accumulator keeps running in the background, and its data goes into the first post-sync summary.

Speed up commissioning with a shorter sample interval. The default 15-minute interval is right for production, but it makes bench positioning slow. Before you settle on the final probe depth and cable dressing, temporarily set sample_interval_sec to 60 with a Notehub device-level environment variable (or edit the DEFAULT_SAMPLE_INTERVAL_SEC constant in firmware during development). At 60 seconds per cycle, you'll see several readings in the serial monitor within a few minutes and can confirm the fill percentage holds steady at several probe depths. Set sample_interval_sec back to 900 (or your production value) before you leave the site.

Sensor sanity check. At first light, before you deploy, make sure the sensor reads a plausible distance. With the interceptor hatch open and a tape measure in hand, connect an ST-LINK to the Notecarrier CX debug jack and open a serial monitor at 115200 baud. (The firmware is built with USB CDC off so the host can sleep, which puts debug output on the debug jack's virtual COM port instead of USB-C.) The firmware prints the raw median distance on every wake cycle:

[DBG] median distance mm: 423.00

Compare this value with your tape measurement from the sensor face to the liquid surface. If the raw distance is off by more than 2–3 cm, you have a physical installation or signal problem. interceptor_depth_mm doesn't affect the raw distance reading. It's only used in the fill-percentage calculation and can't shift what the sensor reports. Check these instead: (1) the probe is centered directly over the chamber opening and not angled, since off-center placement causes acoustic multipath off the interceptor walls and returns a longer-than-true distance; (2) the transducer face points straight down with no tilt; (3) the sensor face is clean, because grease fouling on the transducer weakens the signal and makes the sensor report a distance that's too long (so fill looks lower than it is); (4) the UART wiring is correct, though a wiring fault usually gets the read rejected entirely (no [DBG] line at all) rather than giving an offset reading.

Once the raw distance matches the tape measurement within 1–2 cm, validate interceptor_depth_mm by checking fill_pct_now in the first Notehub summary against your known reference. At 0% fill (right after pump-out), the distance should equal interceptor_depth_mm and fill_pct should read ~0%. If the derived percentage is off, adjust interceptor_depth_mm with the Notehub environment variable. Note: if interceptor_depth_mm is set more than about 10% shorter than the true pump-out distance, every reading from the freshly pumped trap lands above the firmware's interceptor_depth_mm × 1.1 acceptance gate and gets silently rejected, so no summary Note appears until you fix the value (see §7 sensor reading strategy). Correct it in Notehub and allow up to one inbound poll cycle (2 hours by default) for the update to take effect. When the reading looks plausible, close the hatch and disconnect the ST-LINK.

Alert simulation. The fastest way to test the alert path end to end is to lower alert_threshold_pct to 5 in the device's environment variables in Notehub. The device pulls the new value on its next inbound sync (within 2 hours at the default HUB_INBOUND_MIN). On the wake after that, the current fill percentage will very likely be above 5%, and a grease_alert.qo Note will reach Notehub shortly after the sample, once a session comes up.

Mojo wiring and energy reporting. The Mojo stays in the deployed unit permanently. Wire it inline on the +VBAT rail between the 5 V DC wall adapter and the CX +VBAT pad (adapter positive lead → Mojo BAT, Mojo LOAD → CX +VBAT pad, adapter negative → CX GND), and connect it to the Notecarrier CX Qwiic port with a 4-pin JST-SH Qwiic cable. Since Mojo sits on the +VBAT rail, its readings reflect the whole-board draw. That's the Notecard plus the CX's onboard regulators, quiescent biasing, and the continuously powered A02YYUW sensor, not the Notecard by itself. Notecard firmware v8.1.3 or later auto-detects the Mojo over I²C with no extra configuration.

Each daily summary cycle, the firmware calls card.power, reads the accumulated milliamp_hours, and reports it as power_mah in the grease_summary.qo Note. Then it resets the counter, so each summary reports only the energy used in that one window. A power_mah of -1 means the Mojo reading wasn't available for that window (check the Qwiic connection and the Notecard firmware version). To look at live values during commissioning, send {"req":"card.power"} from the in-browser Notecard Playground (CX USB-C with the DIP switch in NC) and check for a plausible milliamp_hours and voltage.

The table below puts the published MBGLW Notecard figures next to the trace shapes you should look for on your assembled unit. Board-level numbers beyond the Notecard's own idle depend on your assembly, so measure them with Mojo instead of assuming them from these figures.

PhaseMBGLW Notecard published figureExpected trace on your assembly (confirm with Mojo)
Notecard idle between syncs~8 µA (low-power design guide), reachable when powered through +VBAT with VUSB absent, as in this buildThe whole-board floor will be higher. Add CX regulator quiescent current, the STM32L433 host in STOP2 (~1–2 µA), the continuously powered A02YYUW (~8 mA), and any other peripheral leakage. The actual floor depends on your assembly, so confirm it with Mojo.
Host active (~2 seconds sampling cycle)Notecard stays near idle, and host MCU and UART activity add load on topBrief current step above the quiescent floor every sample_interval_sec (default 15 minutes). The A02YYUW draw is already part of the floor because the sensor is always powered, so the step is just the host's own added draw while it's awake.
Notecard cellular session (LTE Cat-1 bis)~250 mA average, ≤2 A peak during transmit bursts (MBGLW datasheet)Outbound sync: 30–60 seconds of elevated current once per report_interval_min (once a day by default). Inbound polls: shorter sessions every 2 hours (HUB_INBOUND_MIN = 120), or up to 12 extra radio wakes a day at default settings. Each inbound session still pays the radio-wake and session-setup cost even though it delivers no summary data, and at the default cadence the 12 daily inbound sessions together may match or beat the single outbound session in energy. Budget for both when you size supply capacity. The continuously powered sensor (~8 mA × 24 h ≈ 192 mAh/day) is still the biggest daily energy user, because the +3V3_OUT rail stays on while the host sleeps in STOP2. Confirm with Mojo (spliced between the DC wall adapter and CX +VBAT as described above).

The always-on sensor uses the most energy over a day (~8 mA continuous ≈ 192 mAh/day), because the +3V3_OUT rail stays on while the host sleeps in STOP2. The cellular budget includes both the outbound summary sync (one per report_interval_min) and the inbound environment-variable polls (up to 12 a day at the default 2-hour cadence). At default settings, the inbound sessions added together may approach or exceed the energy of the single outbound sync. A healthy Mojo trace shows a roughly constant quiescent floor (Notecard idle + always-on sensor), a brief step every 15 minutes when the host is active, shorter radio-wake spikes about every 2 hours (inbound polls), and a larger, longer cellular sync spike once per report_interval_min (outbound).

If you see sustained elevated current with no sleep pattern instead, the host isn't entering STOP2. On the Notecarrier CX, work through these: (1) check the ATTN→D5 jumper (see §5), because without it cxSleepUntilAttn() never sees ATTN go low, logs a warning, and waits out the interval awake; (2) confirm the card.attn request returns without an error in the ST-LINK debug stream (Notecard API debug output pauses after a successful sleep call); (3) confirm the firmware was built with USB support set to None (usb=none), since with the USB CDC stack enabled and no USB host attached, the host leaves STOP2 within a millisecond of entering it. The Mojo stays wired inline on +VBAT and connected over Qwiic in the deployed unit, so the same energy data is available in the field through the power_mah field of each daily summary.

10. Limitations and Next Steps

This reference design is scoped tightly to the indoor utility-room HGI install and to geometries where the liquid surface rises with FOG accumulation. The limits below are deliberate, and each one has a clear path to extend it for a production rollout.

Simplified for the POC

Keeping these corners cut is what lets you build this without a hazardous-location electrical review or a custom dual-sensor probe.

Scoped to HGI and batch-collection geometries, not validated for conventional constant-level interceptors. The design covers hydromechanical and batch-collection interceptors without a fixed outlet weir. In those geometries the top liquid surface rises as FOG and wastewater accumulate, so the fill percentage is a meaningful pump-out indicator. A conventional constant-level gravity interceptor is different. Its outlet weir holds the liquid surface at a fixed height regardless of FOG thickness, so the top surface barely moves as grease builds up. There, fill_pct won't track FOG buildup, and the 75% alert threshold won't map to regulatory pump-out criteria. Do not deploy this reference design on a conventional constant-level interceptor for compliance purposes without independent empirical validation that surface elevation tracks FOG accumulation in that specific unit. Conventional interceptors need direct FOG-layer measurement, such as a differential float pair, a bottom conductivity probe, or matched top-and-bottom ultrasonic sensors.

Not rated for classified hazardous locations. The A02YYUW probe, all associated wiring, and the electronics in this build are standard, non-intrinsically-safe (non-IS) components with no NEC Article 505/506 Class/Zone, ATEX, or IECEx certification. Whether a given interceptor installation counts as a classified hazardous location is a site-specific call that a qualified licensed electrician or the AHJ must make before deployment. Do not assume an installation is unclassified without a documented review. This reference design is suitable only for non-classified installations, after a completed code and site-safety review. Classified hazardous-location installations require IS-rated sensors, certified IS barriers, explosion-proof (XP) or purged-and-pressurized (P) enclosures, and installation by personnel qualified for hazardous-area work.

Indoor utility-room power architecture only. The documented hardware build assumes a 120 VAC wall outlet within ~1.5 m of the interceptor access cover, feeding the UL-listed 5 V DC wall adapter that powers the enclosure. A large share of commercial HGI installations sit in rear yards, under a parking lot, or in a floor vault with no convenient outlet. Those sites need a solar panel plus a lithium battery pack, or a long conduit power run, and this reference design covers neither. See the battery backup item in Production Next Steps below.

Single-layer measurement only. A grease interceptor has two distinct layers, with floating FOG at the top and settled sludge at the bottom. Many jurisdictions base compliance on the combined FOG-plus-sludge depth relative to the overall liquid depth, not just the distance to the FOG surface. The firmware measures one distance (sensor to FOG surface) and derives a simple fill percentage from it. In jurisdictions with explicit combined-depth rules, a production deployment would need a second sensor at the bottom or a different measurement method to account for sludge.

Fixed interceptor depth per device. interceptor_depth_mm is a single number: the sensor-to-reference-surface distance when the interceptor is at 0% fill. You measure and set it by hand for each installation, since there's no auto-calibration. If the probe mounting depth shifts (say, someone repositions the cover), the calibration drifts without any warning.

No FOG layer thickness calculation. The sensor reports the distance to the surface of the FOG layer, not how thick the layer is. Thickness is the more directly actionable number, but you'd need to know where the FOG layer ends, which is the top of the wastewater zone below it. Measuring that takes a second sensor or a conductivity probe.

Environmental fouling not detected. The A02YYUW probe is IP67 and handles condensation and splash. A heavy grease coating on the transducer face, though, will weaken the ultrasonic signal and produce false long readings, where the sensor thinks the surface is farther away than it is and the fill level looks lower than it really is. The firmware can't detect or correct for probe fouling. A valid-samples count well below the expected 96/day can be a symptom, but it isn't a reliable diagnostic.

No temperature compensation beyond the sensor. The A02YYUW has an internal temperature-compensation circuit for the speed of sound. The firmware doesn't read or log temperature separately, and no temperature data goes to Notehub.

Alert cooldown is per-device, not per-channel. The firmware enforces the 1-hour alert cooldown. If the downstream endpoint needs its own deduplication or escalation logic (for example, "send a second alert if not acknowledged within 4 hours"), build that into the Notehub route or the receiving system.

Production Next Steps

With the basic level monitor running in the field, these are the next things to build. They run roughly from per-site usability toward deeper measurement and fleet management.

A per-installation commissioning flow gets rid of the manual setup step. Expose a calibrate environment variable that, when set, records the current sensor reading as the 0%-fill reference distance and stores it back as interceptor_depth_mm. The firmware then does the calibration, and nobody has to pull out a tape measure.

Dual-layer measurement covers jurisdictions with combined-depth rules. Add a conductivity or float probe near the bottom of the interceptor to detect sludge buildup and report the combined FOG+sludge fill depth.

Probe-fouling detection turns a failure you can't see into an early warning. Add a signal-quality metric based on the standard deviation of the 5-reading median filter. A high std-dev or a rising rejection rate flags fouling or multipath before the readings go completely invalid.

Over-the-air firmware updates through Notecard Outboard DFU let you push threshold recipes and protocol updates to the whole fleet without a site visit.

Battery backup from Blues Scoop or a small sealed lead-acid battery keeps interceptors in outage-prone locations covered, so an overflow alert still fires during a kitchen's electrical fault.

Per-device pump-out logging closes the service loop. Add a grease_service.qi inbound Notefile that the dispatch system writes to when a pump-out is done, so the firmware can reset the fill accumulator on confirmed service and start fresh from a known-empty state.

11. Summary

The pumping provider who used to send a truck every four weeks, no matter how full the trap was, now dispatches on condition. The FSE near 75% gets serviced before it overflows, and the slow-season taqueria gets serviced less often without the compliance risk. An ultrasonic probe and a cellular Notecard deliver a fill percentage to Notehub every day, plus an alert that wakes the radio whenever the threshold is crossed. That turns a fleet of grease traps nobody could see into a route built on actual demand. The same firmware, enclosure, and Notehub project deploy the same way at every HGI on the route, whatever the WiFi situation, IT policy, or age of the building.

On This Page

  • 1. Project Overview
  • 2. System Architecture
  • 3. Technical Summary
    • First Event in Minutes
  • 4. Hardware Requirements
  • 5. Wiring and Assembly
  • 6. Notehub Setup
  • 7. Firmware Design
    • Building and Flashing
    • Modules
    • Sensor reading strategy
    • Event payload design
    • Low-power strategy
    • Retry and error handling
    • Note template format codes (abbreviated syntax)
    • Key code snippet 1: Note template definition
    • Key code snippet 2: immediate-sync alert
    • Key code snippet 3: sleeping until the Notecard raises ATTN
  • 8. Data Flow
    • Example payloads routed to Notehub
  • 9. Validation and Testing
    • Expected Steady-State Behavior
    • Cold-Boot and Clock Sync
  • 10. Limitations and Next Steps
    • Simplified for the POC
    • Production Next Steps
  • 11. Summary

Resources

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