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_rightUntethered Trailer and Chassis Fleet Tracker

Untethered Trailer and Chassis Fleet Tracker

Untethered Trailer and Chassis Fleet Tracker 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/trailer_fleet_tracker_starnote/ so it can learn how the device works and help you adapt it to your hardware.

This project is a solar-trickle-charged, tractor-independent GPS and motion tracker for asset location tracking on freight trailers and intermodal chassis. It sends telemetry over cellular first and falls back to Iridium LEO satellite, which covers the whole globe. That keeps a trailer or chassis visible on trans-oceanic container routes and polar corridors where geostationary satellite networks have no coverage at all. The hardware is a Blues Notecarrier XI with a Swan host, a cellular Notecard, and a Starnote for Iridium (§4 has the BOM).

The unit mounts on the trailer roof or chassis frame and runs a parked/moving state machine entirely on the device. Departure, arrival, and position Notes go to the Blues Notehub cloud service over cellular, with automatic Iridium satellite fallback, so the tracker doesn't need a tractor hookup, site IT, or terrestrial coverage.

1. Project Overview

The problem. Long-haul trucking fleets have had the same blind spot for decades. The tractor has an ELD (electronic logging device), a telematics unit, and a driver, and the 53-foot box it drags around has none of those. An intermodal chassis is worse. The same steel frame might be owned by a chassis pool, leased to a carrier, loaded by a shipper, and pulled by three different tractors in a single week. At any moment, a fleet operator's dispatch system knows where the power unit is, but the trailer is wherever the last driver left it.

This matters because trailers and chassis tie up a lot of capital. When a $100,000+ refrigerated trailer sits dark for five days at a shipper's dock, the fleet can't see it. The carrier can't bill for detention time it can't prove, can't recover the equipment without calling around, and can't stop the slow drain of assets leaking out of rotation. For chassis pools it's an even bigger problem. Intermodal equipment management is still mostly a phone-call business, because there's no cheap, tractor-independent way to know where each piece of equipment is.

Why Notecard. A trailer changes tractors every day and can change carriers every few days. Anything that depends on the tractor, whether it's a J1939 tap, a cab-mount device, or a driver's phone, stops working the moment the trailer unhooks. Notecard fits here for three reasons that build on each other:

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.

First, cellular is tractor-independent. The Notecard on the trailer roof has its own prepaid SIM and its own cellular session, and it doesn't care which tractor is pulling it.

Second, satellite fallback fills coverage gaps, from remote land corridors to mid-ocean. North American freight routes cross the Great Plains, mountain passes, and border zones where LTE-M coverage has real holes. Container chassis go even further. On trans-Atlantic and trans-Pacific segments, they're completely out of reach of any terrestrial signal and outside every geostationary satellite footprint. This project covers all of those cases by pairing a standard cellular Notecard with a Starnote for Iridium. Delivery is cellular-first, with Iridium LEO satellite fallback that works pole-to-pole, every ocean segment included. After two cellular failures in a row, the Notecard routes through the Starnote automatically, and the firmware doesn't need to know which path is active.

Third, power is scarce. Trailers have no reliable 12V auxiliary hookup. The 7-way connector only carries power when a tractor is connected, and that's exactly the condition this design can't count on. A small solar panel and a LiPo battery are the only workable power source, so the whole system has to be strict about sleep. The Swan goes into deep sleep between checks and wakes on the ATTN interrupt. The firmware explicitly turns GPS on at each PARKED→MOVING departure (by issuing card.location.mode {"mode":"periodic"}) and off at each MOVING→PARKED arrival (by issuing card.location.mode {"mode":"off"}), so the GPS module never runs while the trailer is parked. The result is a device that can run for days without solar input and get month-scale battery life on trickle solar.

Deployment scenario. A weatherproof IP67 enclosure mounts flat on the trailer roof, with the solar panel on the same roof surface. Two SMA bulkhead fittings in the enclosure lid bring the cellular antenna and the combined Iridium+GPS antenna out to the lid surface, so there's no GPS patch inside. For chassis installations, Chassis deployment variant covers chassis-specific mounting. Either way, there's no tractor hookup and no wiring into the existing trailer or chassis systems.

2. System Architecture

System architecture: solar power chain → Notecarrier XI with Swan + NOTE-WBEX + Starnote for Iridium → LTE-M primary / Iridium LEO satellite fallback → Notehub → fleet / TMS / analytics routes

2.1 Swan host responsibilities

The tracker's brain is the Swan STM32L4R5 host. The XI has no Feather socket, so the Swan mounts alongside the Notecarrier XI and is wired to its 0.1" headers by hand. On each wake, the Swan asks the cellular Notecard's built-in accelerometer one question through card.motion: moving or parked? If a transition happened, the Swan queues the right Note over I²C. PARKED→MOVING fires card.location.mode {"mode":"periodic"} to start GPS, and MOVING→PARKED fires card.location.mode {"mode":"off"} to shut it down again for the dwell. Each transition Note is stamped at the wake where the change was first seen (with the current cached GPS fix and epoch), and that snapshot goes into the pending-event queue right away. Every delivery attempt, retries on later wakes included, reuses the stored snapshot, so a retried departure Note never picks up a stale location from a later parking period. Once the queue is handled, the Swan drops into STM32 STOP2 (a few µA, RAM intact) until the Notecard raises its ATTN pin, which is wired to Swan D5, for the next check. Execution resumes in place, so AppState just stays in RAM between wakes.

Departure Notes carry sync:true. On cellular, that wakes the radio right away to deliver them. On NTN/satellite paths it marks the Note as high priority, but it can't interrupt an Iridium orbital pass on demand. The Notecard queues the Note and sends it at the next scheduled satellite transmission opportunity, which is usually minutes away depending on LEO geometry. Position and heartbeat Notes wait in a batch for the next outbound window on either transport.

2.2 Notecard and Starnote for Iridium responsibilities

Queued Notes live on the cellular Notecard (e.g., NOTE-WBEX) between syncs. It manages the cellular session on the cadence set by hub.set. When two cellular attempts in a row fail, card.transport "method":"cell-ntn" has it route through the Starnote for Iridium module instead. The Starnote handles the Iridium LEO satellite session and GPS/GNSS through a single Iridium-certified combined antenna, and the standard card.location API returns the Starnote's fix with no special handling. The Notecard also passes environment variables down from Notehub, so the fleet can be retuned without a truck roll.

2.3 Notehub responsibilities

Once Notes leave the device, the Notecard's embedded global SIM carries them over supported carriers worldwide to Notehub. From there, Notehub ingests and stores the events and routes them downstream. Fleets let the operator group trailers by carrier, lane, or equipment type and share threshold configurations across each group, and Smart Fleets assign trailers to the right fleet automatically by region or device attribute.

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

3. Technical Summary

What you'll have when you're done: A solar-powered trailer or chassis tracker that reports motion-triggered departure/arrival events and position updates to Notehub over LTE-M (primary) or Iridium LEO satellite (automatic fallback). It covers the globe pole to pole and doesn't need a tractor hookup or any site IT.

  1. Notehub: Create a Notehub project and copy its ProductUID.
  2. Wire the bench rig: Notecarrier XI + Swan (including the XI ATTN → Swan D5 wake wire) + cellular Notecard + Starnote for Iridium + solar chain. The full pinout is in §5.1.
  3. Edit one line of firmware/trailer_fleet_tracker_starnote/trailer_fleet_tracker_starnote_helpers.h to set PRODUCT_UID to your Notehub project's ProductUID (in Notehub: Project Settings → ProductUID).
  4. Flash with the Arduino IDE or arduino-cli (see §7.1).
  5. Watch: Open Notehub → Events tab. A _session.qo should show up within a few minutes of power-on, which confirms the first cellular session and clock sync. The firmware then queues a trailer_heartbeat.qo locally on the next parked-check wake (~5 minutes in). Heartbeat Notes are not marked sync:true, so instead of going out right away they wait for the next scheduled outbound sync window. That's ~60 minutes at a full battery (voutbound high:60) or ~120 minutes at nominal charge (voutbound normal:120). Give it 1–2 hours from first power-on before the first heartbeat appears in Notehub.

Here's a sample Note from this device:

{
  "file": "trailer_event.qo",
  "body": {
    "type": 1,
    "dwell_h": 18.5,
    "gps_valid": 1,
    "lat": 41.8781,
    "lon": -87.6298,
    "evt_time": 1746182400
  }
}

4. Hardware Requirements

note

Hardware stack note. This design uses Notecarrier XI + Swan instead of the default Notecarrier CX stack (with its onboard STM32 host). The ocean-capable Iridium path needs the dedicated Starnote connector on the Notecarrier XI. The Notecarrier CX doesn't have that interface, so it can't support Starnote for Iridium or Iridium NTN satellite fallback.

PartQtyRationale
Notecarrier XI1Carrier board with M.2 Notecard slot, Starnote for Iridium connector, +VBAT screw terminal, Qwiic port, and 0.1" headers exposing I²C, ATTN, GPIO, and power rails for an external host MCU. No Feather socket, so the Swan is wired to these headers by hand.
Standard cellular Notecard, e.g., NOTE-WBEX1Global LTE-M / NB-IoT cellular + GPS/GNSS in an M.2 module. The Notecard handles the cellular session and motion detection, and the Starnote for Iridium provides satellite fallback and the combined GPS+satellite antenna.
Starnote for Iridium1Iridium LEO satellite module with a single Iridium-certified antenna that handles both satellite and GPS/GNSS. It plugs into the Notecarrier XI Starnote connector, and you don't need another GPS antenna.
Swan (STM32L4R5)1Blues Feather-format STM32L4R5 host MCU. The Notecarrier XI has no Feather socket, so the Swan mounts alongside the carrier and is wired by hand to the XI's 0.1" headers (3V3, GND, SDA, SCL, ATTN → D5). It sleeps in STM32 STOP2 between wake cycles until the Notecard's card.attn ATTN pin wakes it.
Blues Mojo (bench-only, not field-deployed)1Coulomb counter for power validation during bench bring-up. It connects inline between the LiPo and the Notecarrier XI +VBAT pad via Qwiic. Remove it before field deployment.
SparkFun Sunny Buddy MPPT Solar Charger1LT3652-based MPPT charger that accepts 6–20V solar input and charges a single-cell LiPo at up to 450 mA. MPPT keeps the panel at its maximum power point across the wide irradiance range a trailer roof sees.
SparkFun Small Solar Panel, 0.6W, 6V ETFE1Flexible, weather-resistant ETFE panel, 6V nominal. At 4 peak sun hours it delivers roughly 250–300 mAh/day. Whether that beats the system's parked quiescent draw depends on the Starnote for Iridium board's standby current, which isn't published, so measure the real floor with Mojo (§9) before you settle on sizing. Mount it flat on the trailer roof above the enclosure.
SparkFun Lithium Ion Battery, 2Ah (PRT-13855)13.7V / 2000 mAh cell with a 2mm JST-PH connector. It gives you several days of backup through cloudy dwell periods.
Cellular antenna (included with NOTE-WBEX)1 (included)Ships in the NOTE-WBEX kit. It connects to the Notecard MAIN u.FL port through the u.FL-to-SMA pigtail and SMA bulkhead fitting below, and covers the LTE-M / NB-IoT frequency bands for the regions you deploy in. Route it through the first SMA bulkhead to the outside of the enclosure lid.
Iridium-certified combined Iridium+GPS antenna (included with Starnote for Iridium)1 (included)Ships in the Starnote for Iridium kit. It's a single u.FL antenna that covers both the Iridium satellite uplink (1616–1626.5 MHz) and GPS/GNSS, so you don't need a separate GPS antenna. Must use only the included antenna: Starnote for Iridium is certified on Iridium's network exclusively with this antenna. Swapping in another antenna voids the Iridium network certification and risks getting blocked from the network. Route it through the second SMA bulkhead to the outside of the enclosure lid and mount it with an unobstructed 360° sky view.
u.FL to SMA pigtail, ~100 mm, e.g., SparkFun Interface Cable SMA to U.FL, WRL-091452Two pigtails: one for the NOTE-WBEX cellular MAIN u.FL port (runs to the cellular antenna through the first SMA bulkhead) and one for the Starnote's Iridium+GPS u.FL port (runs to the combined Iridium+GPS antenna through the second SMA bulkhead).
SMA female panel-mount (bulkhead) connector, 50Ω2Two fittings in the enclosure lid, one for the cellular antenna (NOTE-WBEX MAIN path) and one for the Iridium+GPS combined antenna (Starnote path). Both antennas exit through the lid, so there's no GPS patch mounted inside. The Amphenol RF 132289 is a standard panel-mount SMA female chassis connector (50Ω, through-hole), and any electrically equivalent 50Ω SMA female panel-mount fitting with a compatible flange size works as a substitute.
IP67 weatherproof enclosure, ~130×80×50 mm1Protects the electronics from road spray, rain, and the wide temperature swings on a trailer roof. Both antennas route through SMA bulkheads, so the lid material does not need to be RF-transparent. ABS, polycarbonate, and aluminum all work. Mount it flat on the trailer roof, with a cable entry gland in the side wall for the solar panel leads.

Antenna note. The Starnote for Iridium ships with an Iridium-certified antenna that connects to its single u.FL port and covers both the Iridium satellite link and GPS/GNSS. You don't need a separate GPS antenna, and the NOTE-WBEX GPS u.FL port goes unused. The NOTE-WBEX ships with a cellular antenna for its MAIN u.FL port. Each antenna runs through its own SMA bulkhead fitting to the outside of the enclosure lid. Mount the Iridium+GPS antenna with an unobstructed 360° sky view. Iridium LEO satellites pass over every azimuth, so it doesn't matter which direction the antenna faces.

The cellular Notecard (e.g., NOTE-WBEX) ships with an active Blues SIM that includes 500 MB of data and 10 years of global cellular service, with no activation fees and no monthly commitment. The Starnote for Iridium needs a separate Iridium satellite service plan that the cellular SIM doesn't cover. Contact Blues for current Iridium service details and activation.

5. Wiring and Assembly

Wiring: solar panel → Sunny Buddy MPPT → LiPo → Notecarrier XI +VBAT; Swan wired to the XI headers with XI ATTN → Swan D5 so the Notecard can wake the host from STOP2; NOTE-WBEX MAIN u.FL → pigtail → SMA bulkhead → cellular antenna; Starnote u.FL → pigtail → SMA bulkhead → Iridium+GPS antenna; Mojo inline between LiPo and +VBAT for bench bring-up

5.1 Notecarrier XI + Swan

The cellular Notecard seats in the M.2 slot, and the Starnote for Iridium plugs into the XI's dedicated Starnote connector. Since the Notecarrier XI has no Feather socket, the Swan mounts alongside the carrier and is wired by hand to the XI's 0.1" headers. Power, Qwiic, and both antennas land on headers and u.FL ports that are easy to reach.

Notecarrier XI interface reference:

InterfaceLocationNotes
+VBATScrew-terminal block, carrier edge3.4–4.2V single-cell LiPo input. Red wire to +VBAT, black wire to the adjacent GND. During bench bring-up, the Mojo LOAD output connects here through its JST-PH pigtail.
GNDScrew-terminal block, adjacent to +VBATShared power and signal return for the battery, solar charger, and Qwiic.
Host MCU headers0.1" header rows along the carrier edgeThe XI has no Feather socket. Mount the Swan alongside the carrier and wire it by hand to these headers: Swan 3V3 ↔ XI 3V3, Swan GND ↔ XI GND, Swan SDA (PB9) ↔ XI SDA, Swan SCL (PB8) ↔ XI SCL, and the XI ATTN pin to Swan D5 (the HOST_ATTN_PIN wake input, covered in the ATTN wire note below). Leave the XI's EN pin unconnected.
M.2 slotM.2 Key-E connector, carrier centerThe cellular Notecard (e.g., NOTE-WBEX) goes in at a 45° tilt, then pivots flat and is secured with the M.2 retaining screw. The M.2 key prevents reverse insertion.
Starnote connectorDedicated multi-pin connector, carrier faceStarnote for Iridium plugs straight down into this connector, which carries power, I²C, and the Iridium+GPS antenna passthrough. Line the Starnote module up over the connector and press firmly until it's fully seated. No screws needed.
QwiicJST-SH 1mm 4-pin, carrier faceMojo connects here with a Qwiic cable for I²C mAh reporting during bench bring-up. The XI has onboard I²C pull-ups, so you don't need extra resistors.
Swan USB-CUSB-C port on the Swan module itselfPrograms the Swan host through its DFU bootloader. The firmware is built with USB support set to None (required for STOP2), so this port does not give you a serial debug console. Debug output comes out of the Swan's STLINK debug connector instead (see §7.1).
Swan STLINK debug connector14-pin connector on the Swan moduleAttach an ST-LINK V3 for SWD programming and for the virtual COM port that carries the firmware's 115200-baud debug output.

Power chain for bench bring-up (Mojo inline):

The Mojo sits inline between the LiPo and the Notecarrier XI +VBAT screw terminal and measures only the device-side discharge current.

  1. Solar panel → Sunny Buddy SOLAR IN terminal (6–20V).
  2. LiPo battery → Sunny Buddy LIPO terminal (JST-PH 2mm 2-pin; charging connection).
  3. LiPo battery → Mojo BAT input (JST-PH Y-adapter from the battery pigtail; same node as the Sunny Buddy LIPO connection).
  4. Mojo LOAD output → Notecarrier XI +VBAT screw terminal (red to +VBAT, black to GND).
  5. Mojo Qwiic → Notecarrier XI Qwiic port.

Power chain for field deployment (Mojo removed):

Once bench bring-up is done (see §9), take the Mojo out before you seal the enclosure:

  1. Solar panel → Sunny Buddy SOLAR IN (unchanged).
  2. LiPo battery → Sunny Buddy LIPO terminal (unchanged).
  3. LiPo battery → Notecarrier XI +VBAT screw terminal directly.
warning

Polarity note. Check red-to-positive on every JST-PH connection before you apply power. The Notecarrier XI +VBAT accepts 3.4–4.2V, and going above 4.3V risks damage.

Antenna routing:

There are two external antennas, so the enclosure lid needs two SMA female bulkhead fittings:

  • NOTE-WBEX cellular antenna (MAIN u.FL): Run a ~100 mm u.FL-to-SMA pigtail to one SMA female bulkhead fitting on the enclosure lid, then thread the included cellular antenna onto the bulkhead from outside.
  • Starnote Iridium+GPS combined antenna (Starnote u.FL): Connect it to the Starnote's u.FL port with a second ~100 mm u.FL-to-SMA pigtail and route it to the second SMA female bulkhead fitting on the enclosure lid. Mount this antenna on the lid surface facing the sky, with a clear 360° view. Iridium LEO satellites pass over every azimuth, so it doesn't matter which direction the antenna faces. No separate GPS antenna is needed. The Starnote's combined antenna handles GPS, and the NOTE-WBEX GPS u.FL port goes unused.

Space the two SMA bulkhead fittings at least 25 mm apart to keep coupling between the two antenna paths low. If any trailer structure overhangs the spot you planned, shift the enclosure fore or aft to clear it, because even partial sky obstruction above roughly 8° elevation hurts Iridium link margin and GPS acquisition.

ATTN wire (host sleep):

Run a wire from the Notecarrier XI's ATTN header pin to the Swan's D5 pin. The Notecard pulls ATTN low while the Swan sleeps and raises it when the next check is due, and the rising edge on D5 wakes the STM32L4R5 from STOP2. Do not use the XI's EN pin for this. On the Notecarrier XI, EN is the Notecard's own enable (pulling it to GND turns the Notecard off), so it can't gate the host and must be left unconnected. Putting a Host to Sleep Between Sensor Readings shows the same STOP2-plus-ATTN pattern on the Notecarrier CX. The only differences here are the hand-run wire and the Swan's pin name.

I²C / debug:

The Swan talks to the cellular Notecard over the Notecarrier XI's onboard I²C bus. The Notecard manages the Starnote for Iridium through the Starnote connector, so satellite and GPS operation need no extra host wiring. During development, attach an ST-LINK to the Swan's STLINK debug connector. Its virtual COM port carries the firmware's debug output at 115200 baud. (USB CDC is disabled in this build, so the Swan's USB-C port is for DFU programming only.)

Chassis deployment variant

An intermodal chassis has no roof. It's a flat, low steel frame sized for a 20- or 40-foot ISO container. The BOM is the same as the trailer installation, but the mounting, solar, and antenna plan has to fit the chassis geometry.

Mounting location. Mount the enclosure on the front bolster or gooseneck cross-member at the kingpin end of the chassis. This area sits directly under the container floor plate, which partly shields it from horizontal impacts during container handling. Use stainless M6 hardware with split lock washers through pre-drilled holes. With the constant road vibration, it's a good idea to put thread-locking compound (e.g. Loctite 243) on every fastener. Stay away from the rear cross-members, which get more road spray from the axle group and more forklift contact near the rear twist locks.

Solar panel. Once a container is loaded, the chassis roof surface is completely blocked. Mount the solar panel on a bracket welded or bolted to the inboard face of the front bolster rail, angled 30–45° toward the sky and facing south in the northern hemisphere. Check that the bracket clears the container twist-lock castings and doesn't stick out past the chassis rail envelope, where it would get in the way of loading or break transport width limits. Budget conservatively. Assume 2–3 peak sun hours a day for a chassis-mounted panel (versus 4 on an unobstructed trailer roof), and consider moving up to a 4 Ah LiPo for high-latitude or winter deployments.

Antennas. The cellular antenna and the combined Iridium+GPS antenna both need a clear view of the sky. Put both SMA bulkhead fittings on the top or outboard face of the enclosure lid, and orient the enclosure so that face points up or outboard instead of being buried against the chassis rail. On a loaded chassis, any antenna inside the container envelope has the container floor plate right overhead, so mount the enclosure far enough forward that the antennas clear the front edge of the container.

Enclosure protection. A chassis is a rougher place than a trailer roof. Road spray hits the frame from below constantly, forklift tines pass close to the frame rails, and container handling knocks and scuffs any hardware nearby. Use an IP67 enclosure with stainless fasteners throughout, protect the cable entry glands with reinforced strain-relief fittings rated for abrasion and UV, and consider adding a steel guard plate over the enclosure if forklift traffic can reach the mount location.

6. Notehub Setup

Creating the project and provisioning the device

  1. Create a project. Sign up at notehub.io and create a new project. Copy the ProductUID, which looks like com.your-company.your-name:trailer-tracker.
  2. Set the ProductUID in firmware. Open firmware/trailer_fleet_tracker_starnote/trailer_fleet_tracker_starnote_helpers.h and replace the empty string on the #define PRODUCT_UID "" line with your value.
  3. Power the unit. On its first cellular session, the Notecard associates itself with your project automatically, so there's no manual claim step. The device shows up in your project's Devices tab within a minute or two.

Fleet organization

Create one Fleet per equipment category, such as reefer-trailers, dry-vans, and flatbed-trailers. Fleet-level environment variables reach every device in the fleet on its next inbound sync, so you can tune heartbeat cadence or motion sensitivity for a whole category at once. If your fleet follows a consistent naming scheme, Smart Fleets can sort trailers automatically by device attribute.

Environment variables

Go to Fleet → Environment (or Device → Environment for per-unit overrides) and add any of the variables below. Changes take two steps to arrive. First, Notehub delivers the updated values to the Notecard on the next inbound sync window (2 hours at high battery and 4 hours at normal battery, set by the vinbound profile). Then the host firmware picks them up on its next hourly env poll (ENV_POLL_SECS = 3600). At normal battery, expect new values to take effect within roughly 3–5 hours of saving them in Notehub, without a reflash or a truck roll.

VariableDefaultPurpose
parked_check_mins5How often the host wakes to poll the accelerometer while parked. Lower values catch departures sooner (this interval bounds transition detection accuracy) but raise the average sleep current. Range: 1–60.
moving_ping_mins15GPS position report interval while moving, which also bounds arrival detection accuracy. When it changes, the firmware reissues card.location.mode so the Notecard's GNSS fix cadence keeps matching the new report interval (right away if the trailer is moving, otherwise at the next departure). Range: 5–60.
heartbeat_hours6Alive-ping interval while parked. Set it higher (e.g. 12) for long-dwell equipment at known yards, or lower (e.g. 2) for high-value assets or demurrage monitoring. Range: 1–24.

Routing

Add two routes in Notehub:

  • trailer_event.qo → real-time delivery to a downstream HTTP endpoint, MQTT broker, or cloud function. These departure/arrival events drive detention billing, recovery workflows, and missed-connection alerts.
  • trailer_location.qo + trailer_heartbeat.qo → a long-term store (e.g. Snowflake, AWS S3, or a time-series database) for dwell-time analytics, lane utilization, and battery trending.

Keeping the two routes separate means bulk-load throughput never affects alert latency. The Notehub routing docs list the supported destination types.

What you'll see in Notehub

Your project's Events tab shows every Note type:

  • _session.qo: Notecard housekeeping on each cellular or satellite session, which confirms connectivity.

  • trailer_event.qo: fires on every departure and arrival and is delivered with sync:true. The body looks like this:

    {
      "type": 1,
      "dwell_h": 18.5,
      "gps_valid": 1,
      "lat": 41.8781,
      "lon": -87.6298,
      "evt_time": 1746182400
    }

    type 1 = departed, 2 = arrived. dwell_h is how many hours the trailer sat parked before this departure, and it's 0 for arrival Notes. gps_valid is 1 when a valid GPS fix was available at detection time and 0 when there was no fix (for example, on the first departure from a freshly installed unit). Ignore lat/lon when gps_valid is 0. lat, lon, and evt_time are the GPS coordinates and Unix epoch captured at transition detection time, meaning the wake cycle where the state change was first seen. parked_check_mins bounds the timestamp accuracy for departures, and moving_ping_mins bounds it for arrivals. The location is the Notecard's most recent cached fix at detection time. The firmware stores these values in the event queue at detection time and keeps them across retried deliveries, so a Note retried on a later wake always carries the original detection-time data instead of the post-transition GPS state.

  • trailer_location.qo: queued every moving_ping_mins while the trailer is rolling. The compact envelope carries the GPS fix the Notecard embeds, and you can see it on a map in Notehub's device view.

  • trailer_heartbeat.qo: fires every heartbeat_hours while parked. Body:

    {
      "volt": 3.84,
      "gps_valid": 1
    }

    If volt trends down across consecutive heartbeats, that's an early warning that the solar panel or charge path needs attention.

7. Firmware Design

The firmware lives in firmware/trailer_fleet_tracker_starnote/. setup() runs once at power-up, and each pass through loop() is one wake cycle that ends with the Swan asleep in STOP2 until the Notecard raises ATTN. The sleep helpers (the card.attn request, STOP2 entry, and ATTN wake) are in host_sleep.h.

7.1 Dependencies and flashing

Install the libraries:

Install note-arduino (Blues Wireless Notecard) and STM32duino Low Power (plus its dependency STM32duino RTC) from the Arduino Library Manager, or run arduino-cli lib install "Blues Wireless Notecard" "STM32duino Low Power" "STM32duino RTC". The note-arduino releases page lists the available versions. STM32duino Low Power provides the STOP2 entry and ATTN-pin wake that host_sleep.h uses. It supports the Swan's STM32L4R5, where deepSleep() enters STOP2.

Add the STM32 boards index:

Add https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json under File → Preferences → Additional Boards Manager URLs, then install "STM32 MCU based boards" from the Boards Manager.

Build settings: Select Blues boards → Swan R5 (pnum=SWAN_R5) and set USB support (if available) to None (usb=none). If the USB CDC stack is enabled and no USB host is attached (solar/LiPo power in the field), the STM32's USB wakeup interrupt fires continuously and the Swan never stays in STOP2. Debug output goes to the UART on the Swan's STLINK debug connector instead, which an ST-LINK V3 exposes as a virtual COM port (see Serial Logging With STLINK).

Flashing with the Arduino IDE: Open trailer_fleet_tracker_starnote.ino, apply the build settings above, and click Upload. Use the Swan's USB-C port (on the Swan module itself) for the DFU bootloader (hold BOOT, tap RST), or upload over SWD with an ST-LINK on the debug connector.

Flashing with arduino-cli:

# Compile and upload — usb=none disables the USB CDC stack, which must be
# off for the Swan to sleep.
arduino-cli compile -b STMicroelectronics:stm32:Blues:pnum=SWAN_R5,usb=none firmware/trailer_fleet_tracker_starnote/
arduino-cli upload  -b STMicroelectronics:stm32:Blues:pnum=SWAN_R5,usb=none \
                    -p /dev/cu.usbmodem* firmware/trailer_fleet_tracker_starnote/

firmware/trailer_fleet_tracker_starnote/sketch.yaml sets the same board options, so if you run arduino-cli compile in that directory without -b, it picks them up too.

Debug serial logging: The #define usbSerial debugSerial line in trailer_fleet_tracker_starnote_helpers.h is commented out by default. To turn on logging during development, uncomment that line, recompile, and open a serial monitor at 115200 baud on the ST-LINK's virtual COM port. That's the Swan's STLINK debug connector, not its USB-C port, which has no CDC serial in this build. You'll see [heartbeat], [departed], [location], and [sleep] log lines on each wake cycle. Comment the line back out before deploying to the field.

7.2 Module responsibilities

ResponsibilityWhere in sketch
Notecard config: hub.set, card.transport, card.location.mode, card.motion.modenotecardConfigure()
Compact Note templates (all three Notefiles)defineTemplates()
Env-var overrides from NotehubfetchEnvOverrides()
Motion state queryisMoving()
Time and voltage readsgetEpoch(), getBatteryVoltage()
GNSS state capture for transition eventscaptureGnssState()
GPS validity gate (location and heartbeat Notes)hasValidGnssFix()
State machine, sleep/wake schedulingloop()
Note emissionsendTransitionEvent(), sendLocationNote(), sendHeartbeatNote()
Transition event FIFO queue and retryenqueuePendingEvent(), drainPendingQueue()
Host sleep (STOP2 until the Notecard raises ATTN)host_sleep.h: cxSleepBegin(), cxSleepUntilAttn()
Application state (held in RAM across sleep cycles)AppState

7.3 Motion and GPS strategy

The Notecard's built-in accelerometer handles motion detection, configured with card.motion.mode. The firmware uses motion:5, seconds:60, so the Notecard calls the trailer "moving" when five or more motion events pile up in a single 60-second bucket, and "stopped" when the bucket goes quiet. sensitivity:2 (25 Hz / ±8G) is tuned to catch the low-frequency road vibration of a loaded trailer without tripping on wind buffeting or dock impacts while it's parked.

The state machine manages GPS mode explicitly instead of relying on the Notecard's implicit periodic-mode motion gating. That gating is only documented for the Notecard's own GPS module and isn't guaranteed on the Starnote for Iridium's combined GPS hardware path. On first boot, notecardConfigure() issues card.location.mode {"mode":"off"} because the unit always starts out parked. On each PARKED→MOVING departure the firmware issues card.location.mode {"mode":"periodic", "seconds":<moving_ping_secs>} to start GPS acquisition, and on each MOVING→PARKED arrival it issues card.location.mode {"mode":"off"} to shut the GPS module down for the parked dwell. Toggling it explicitly guarantees the GPS module never runs while the trailer sits parked, however the Starnote for Iridium's combined GPS hardware interacts with the Notecard on this path. On this hardware, GPS comes from the Starnote for Iridium's combined Iridium+GPS antenna, and the standard card.location API returns the fix with no special handling.

If you later change the moving_ping_mins environment variable in Notehub, fetchEnvOverrides() stores the new moving_ping_secs value right away. If the trailer is MOVING at the time, it also reissues card.location.mode {"mode":"periodic"} with the updated seconds field immediately. If the trailer is parked, the new period takes effect on the next PARKED→MOVING departure. The compact template's _lat / _lon keywords embed the most recent fix in location and heartbeat Notes, while transition event Notes use explicit lat/lon/evt_time fields captured at transition detection time (see §7.4).

GPS fix validity gating. Before queuing any Note that embeds location data, the firmware calls hasValidGnssFix(), which issues card.location and checks whether the Notecard reports a non-zero lat/lon with no error. card.location returns the last cached fix whatever the current GPS mode is (periodic or off), so this check doesn't add any GPS-on time. It keeps a freshly installed unit, where GPS has never gotten a fix, from sending Notes with silently zeroed coordinates.

  • trailer_location.qo: suppressed entirely when no valid fix is available. A location Note with zeroed coordinates is useless to the fleet. Since suppression doesn't advance last_location_at, the firmware tries again on the next moving-state wake once it has a fix.
  • trailer_event.qo and trailer_heartbeat.qo: always sent, because departure/arrival events and battery voltage matter too much to suppress. Instead, they carry a gps_valid field (1 = confirmed fix, 0 = no fix available). Downstream receivers can use that flag to tell a confirmed location from an invalid placeholder and skip map plotting or geofence checks when there's no fix.

GPS fix capture on transition events. On the wake cycle where a PARKED→MOVING or MOVING→PARKED transition is first detected, the firmware calls captureGnssState(), a single card.location query that returns the Notecard's currently cached lat/lon. Again, card.location returns the last cached fix whatever the GPS mode, so this costs no extra GPS-on time. The captured coordinates, validity flag, and current epoch go into the PendingEvent struct. Every delivery attempt for that event (including retries on later wakes after communication failures) uses that stored snapshot, not the Notecard's GPS state at retry time. So a departure Note retried two hours later still carries the location and timestamp from when the departure was detected, not the current parked position.

For arrival events, captureGnssState() runs while GPS is still in periodic mode (the step that turns GPS off comes right after), so the cached fix is within one moving_ping_mins interval of the stop. For departure events after a long parked dwell, captureGnssState() runs before GPS is turned back on, so the cached fix is from the trailer's last trip and could be hours or days old. gps_valid is still 1 in that case, because the fix is structurally valid even if it's aged. If you need fresh departure coordinates, you can extend the firmware to turn on GPS, poll card.location until a new fix comes in, and then call captureGnssState. That costs 30–90 seconds of extra GPS-on time and battery draw on every departure event.

7.4 Event payload design

All three Notefiles use "format":"compact" templates to keep the over-the-air size small. Every satellite packet has a maximum size. The compact format strips the JSON envelope and stores Notes as fixed-length binary records, and at the field sizes used here (uint8, float16, float32, int32), each Note comes to about 14–20 bytes on the wire, well under the limit.

Payload Reference (for downstream integrators):

NotefileTriggerFieldsNotes
trailer_event.qoDeparture or arrivaltype (1=departed, 2=arrived), dwell_h (parked duration in hours), gps_valid (1=fix, 0=none), lat, lon, evt_timesync:true, delivered over cellular right away. Falls back to Iridium on the next window if cellular is unavailable.
trailer_location.qoMoving state, interval elapsedNone in the body, just the GPS fix and time the Notecard embeds (_lat, _lon, _time).Batched and sent at the next outbound window (60–360 minutes, depending on battery state).
trailer_heartbeat.qoParked state, interval elapsedvolt, gps_validBatched and sent every 6 hours (default, overridable). Use it to confirm solar charging (declining volt = charging failure).

Sample trailer_event.qo (departed, 18.5 hours of dwell, GPS fix confirmed at detection time):

{
  "file": "trailer_event.qo",
  "body": {
    "type": 1,
    "dwell_h": 18.5,
    "gps_valid": 1,
    "lat": 41.8781,
    "lon": -87.6298,
    "evt_time": 1746182400
  },
  "sync": true
}

type 1 = departed, 2 = arrived. dwell_h is the hours parked before this departure, and it's 0 for arrival Notes. gps_valid is 1 if a valid GPS fix was available at detection time and 0 if not (a freshly installed unit, for example). When gps_valid is 0, ignore lat/lon. lat and lon are the GPS coordinates captured at transition detection time, and evt_time is the Unix epoch from that same wake. Timestamp accuracy is bounded by parked_check_mins (for departures) or moving_ping_mins (for arrivals), and the location is the Notecard's most recently cached fix at detection time. The host writes these fields explicitly at detection time so they survive retried deliveries intact. trailer_location.qo and trailer_heartbeat.qo use the Notecard's auto-populated _lat/_lon/_time keywords. Event Notes use explicit host-supplied fields instead, so a Note retried on a later wake never picks up a stale post-transition GPS state.

Sample trailer_heartbeat.qo (parked, battery healthy, GPS fix available):

{
  "file": "trailer_heartbeat.qo",
  "body": {
    "volt": 3.84,
    "gps_valid": 1
  }
}

Watch volt across consecutive heartbeats, since a steady decline is your early warning that the solar panel or charge path needs attention. Seeing gps_valid: 0 on a new unit's first few heartbeats is normal, and it clears once the Notecard gets its first fix.

trailer_location.qo has no application body fields. Its only payload is the GPS fix, which the Notecard embeds from its last acquired fix. The firmware suppresses location Notes entirely when there's no valid fix, so every trailer_location.qo that reaches Notehub carries real coordinates.

7.5 Low-power strategy

Host sleep. After every state-machine cycle, loop() calls cxSleepUntilAttn() (in host_sleep.h). It sends a card.attn sleep request for the computed interval, waits for the Notecard to pull ATTN low, and puts the Swan into STM32 STOP2, where it draws a few microamps and keeps its RAM. When the interval is up, the Notecard raises ATTN, and the rising edge on Swan D5 wakes the host. Execution picks up on the next line of loop(). Since the Swan resumes in place instead of cold-booting, the AppState struct just stays 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 wire), loop() waits out the interval awake and tries again on the next cycle, so the cadence holds either way.

GPS suppression. The firmware issues card.location.mode {"mode":"off"} on each MOVING→PARKED arrival and card.location.mode {"mode":"periodic"} on each PARKED→MOVING departure, so a parked trailer never runs the GPS module. Trailers spend most of their lives at docks, yards, and distribution centers, which makes this explicit GPS gating the biggest single power saving in the system.

Voltage-variable sync. hub.set is configured with voutbound:"high:60;normal:120;low:360;dead:0". As the solar battery drains, the cellular outbound sync interval stretches from 1 hour to 6 hours, and it stops entirely if the battery gets critically low. Transition events use sync:true to ask for priority delivery no matter what the outbound schedule says. On cellular that wakes the radio right away. On NTN it queues the Note for the next satellite transmission opportunity instead of suspending delivery entirely.

7.6 Retry and error handling

  • isMoving(), getEpoch(), and getBatteryVoltage() all guard against a NULL response and return safe defaults instead of crashing the state machine.
  • fetchEnvOverrides() checks the err field on the Notehub response before trusting the body. If the Notecard hasn't set up a session yet, the env response contains an error, and the firmware carries on with its last known defaults.
  • Notecard configuration is gated on config_version, which only gets set once notecardConfigure() and defineTemplates() both succeed. A transient failure leaves the tracker retrying every CONFIG_RETRY_SECS (sleeping in between) instead of emitting events against an unconfigured Notecard. Every reset zeroes AppState, so a firmware update always starts from a clean state and reapplies the Notecard-side configuration.
  • The firmware ignores integer env var inputs outside their documented ranges and keeps the current value, so a typo in Notehub can't set the ping interval to 0 or 65535 minutes.

7.7 Key code snippet 1: transport configuration

After two cellular failures in a row, the Notecard routes through the Starnote for Iridium module on its own. The firmware's only involvement is the single API call in notecardConfigure() that sets up the fallback. If the Notecard rejects it, configuration is marked incomplete and retried on the next wake.

req = notecard.newRequest("card.transport");
if (!req) return false;
JAddStringToObject(req, "method", "cell-ntn");
if (!sendAndCheck(req, "card.transport")) return false;

7.8 Key code snippet 2: compact template definition

All three Notefiles use the compact format so Notes are small enough to go out over satellite intact. trailer_location.qo and trailer_heartbeat.qo use the Notecard's auto-populated _lat/_lon/_time keywords. The host adds each of those Notes once, on the wake it describes, so the Notecard's GPS state at note.add time is the right value to embed. trailer_event.qo uses explicit host-supplied lat/lon/evt_time fields because transition events may be retried on later wakes. Capturing and storing the values at detection time means retries always carry the original departure or arrival location, not a post-transition GPS state. In the code below, NOTEFILE_EVENT is "trailer_event.qo" and PORT_EVENT is 50. The location and heartbeat templates use ports 51 and 52.

// trailer_event.qo — departure / arrival transitions (sync:true, immediate)
J *req = notecard.newRequest("note.template");
if (!req) return false;
JAddStringToObject(req, "file",   NOTEFILE_EVENT);
JAddNumberToObject(req, "port",   PORT_EVENT);
JAddStringToObject(req, "format", "compact");
J *body = JAddObjectToObject(req, "body");
JAddNumberToObject(body, "type",      21);    // TUINT8: 1=departed, 2=arrived
JAddNumberToObject(body, "dwell_h",   12.1);  // TFLOAT16: parked dwell hours
JAddNumberToObject(body, "gps_valid", 21);    // TUINT8: 1=valid fix, 0=no fix
// lat, lon, evt_time are explicit fields written from values captured at
// transition time rather than auto-populated keywords (_lat/_lon/_time).
// This ensures retried events carry the original transition location and
// timestamp rather than the Notecard's current GPS state at retry time.
JAddNumberToObject(body, "lat",       14.1);  // TFLOAT32: GPS lat at transition
JAddNumberToObject(body, "lon",       14.1);  // TFLOAT32: GPS lon at transition
JAddNumberToObject(body, "evt_time",  14);    // TINT32: Unix epoch at transition
if (!sendAndCheck(req, "note.template " NOTEFILE_EVENT)) return false;

7.9 Key code snippet 3: voltage-variable sync with host sleep

The voutbound string stretches the sync interval as the battery drains. notecardConfigure() sends this hub.set right after card.voltage sets the lipo thresholds that define the voltage buckets. VOUTBOUND_PROFILE is "high:60;normal:120;low:360;dead:0" and VINBOUND_PROFILE is "high:120;normal:240;low:720;dead:0", both in minutes:

// hub.set — periodic sync with voltage-variable outbound cadence.
// The voutbound / vinbound profiles stretch sync intervals as the solar
// battery drains, keeping the trailer visible even in extended cloudy
// dwell periods.  Transition events use sync:true to bypass this schedule.
req = notecard.newRequest("hub.set");
if (!req) return false;
JAddStringToObject(req, "product",   PRODUCT_UID);
JAddStringToObject(req, "mode",      "periodic");
JAddStringToObject(req, "voutbound", VOUTBOUND_PROFILE);
JAddStringToObject(req, "vinbound",  VINBOUND_PROFILE);

Between wakes, cxSleepUntilAttn() puts the Swan into STOP2, and the Notecard's ATTN pin brings it back. setup() arms the wake once, and every loop() pass ends with the sleep request:

// Arm the ATTN wake: the Notecard raises ATTN (Swan D5) to end each sleep.
cxSleepBegin();
// ...
#ifdef usbSerial
Stream *log = &usbSerial;
#else
Stream *log = NULL;
#endif
if (!cxSleepUntilAttn(notecard, sleep_secs, NULL, log)) {
    // The Notecard didn't take the sleep request, or ATTN never went low
    // (check the XI ATTN -> Swan D5 wire).  Keep the cadence and retry.
    // ...
    delay(sleep_secs * 1000UL);
}

7.10 Key code snippet 4: motion-triggered state transition

Every departure starts with a card.motion query in isMoving(), which returns false when the Notecard doesn't answer or reports an error, so a failed read suppresses transitions for that wake instead of faking one. The firmware calculates the dwell time from the stored parked_since epoch and attaches it to the Note, so fleet managers can measure detention without any outside tracking. captureGnssState() runs once, on the wake where the transition is detected, and the GPS switch to periodic (elided below) comes right after it. The captured fix goes into the PendingEvent FIFO and is passed to every note.add attempt, so retried events always carry the original detection-time location and timestamp. drainPendingQueue() then tries to deliver the event on the same wake. §7.3 covers GPS freshness on departures after long parked dwells.

bool moving    = false;
bool motion_ok = isMoving(moving);
uint8_t prev   = state.current_state;
// ...
if (motion_ok) {

    if (prev == STATE_PARKED && moving) {
        float dwell_h =
            (state.parked_since > 0 && time_ok && now > state.parked_since)
            ? (float)(now - state.parked_since) / 3600.0f
            : 0.0f;
        // ...
        // Capture departure GNSS state BEFORE enabling GPS.  GPS mode
        // is currently "off" (parked), so card.location returns the
        // Notecard's last cached fix — the best available position at
        // departure time.  That fix may be stale after a long dwell;
        // gps_valid=1 only means a fix exists, not that it is fresh.
        float   cap_lat = 0.0f, cap_lon = 0.0f;
        uint8_t cap_gps_valid = 0;
        captureGnssState(cap_lat, cap_lon, cap_gps_valid);
        // ...
        state.current_state = STATE_MOVING;
        if (time_ok && now > 0) state.last_location_at = now;

        enqueuePendingEvent(state, EVENT_DEPARTED, dwell_h,
                            (time_ok && now > 0) ? now : 0U,
                            cap_lat, cap_lon, cap_gps_valid);
        // ...
    }
}
// ...
// ── Attempt immediate delivery of any newly-queued event ─────────────
drainPendingQueue(state);

8. Data Flow

Data flow: accelerometer (5 minutes parked) + GPS (15 minutes moving) + battery ADC → parked/moving state machine with transition detect and timer checks → trailer_event.qo (departure/arrival, sync:true) and trailer_location.qo + trailer_heartbeat.qo (batched) → Notehub → routes

Collected. Every wake reads the Notecard accelerometer's moving/stopped status. While the trailer is moving, the firmware also collects GPS coordinates from the Notecard's periodic GPS module. While it's parked, it collects the LiPo battery voltage from the Notecard's ADC.

Transmitted.

NotefileTriggerCadenceTransport
trailer_event.qoState transition (depart or arrive)On event, sync:trueCellular (immediate); NTN satellite (next transmission window)
trailer_location.qoWhile moving, interval elapsedEvery moving_ping_mins (default 15 minutes)Batched, outbound window
trailer_heartbeat.qoWhile parked, interval elapsedEvery heartbeat_hours (default 6 hours)Batched, outbound window

On cellular, queued Notes flush at the outbound window, which is 60 minutes at high battery and 120 minutes at normal battery, stretching to 360 minutes at low battery (matching VOUTBOUND_PROFILE). Transition events skip the queue with sync:true, which wakes the radio right away to deliver them.

On NTN/satellite, sync:true marks transition events as high priority, but the Notecard can't interrupt a satellite orbital pass on demand. Instead of triggering an immediate radio wake, events are queued and delivered at the next scheduled Iridium transmission opportunity. This is documented Notecard behavior. Expect delivery within the next satellite window (usually minutes, depending on Iridium LEO geometry), not the sub-60-second latency you'd get on cellular.

Routed. All three Notefiles go to Notehub. From there, set up routes to send them on to your fleet-visibility platform, TMS webhook, or analytics store (see the Notehub routing docs).

Triggers and alerts. A trailer_event.qo with type:1 (departed) is your signal to close a detention clock, log an outbound scan, or send a "tractor has hooked" notification. An arrival (trailer_event.qo with type:2) starts the detention clock. If volt in trailer_heartbeat.qo keeps dropping below ~3.6V over consecutive reads, it's time for a yard check on the solar charging path.

9. Validation and Testing

Expected event cadence. On first boot, last_heartbeat_at is zero, so the heartbeat condition fires on the first wake where the Notecard has a valid clock (now > 0). The Notecard syncs its clock during the initial cellular session, which finishes within a few minutes of first power-on, so the heartbeat gets queued locally on the next parked-check wake (~5 minutes in). Heartbeat Notes are not marked sync:true, so the Notecard doesn't send them right away. They ride along on the next scheduled outbound sync window, which opens after 60 minutes at full battery (voutbound high:60) or 120 minutes at nominal charge (voutbound normal:120). Under typical battery conditions, expect the first trailer_heartbeat.qo to show up in Notehub roughly 1–2 hours after first power-on.

Commissioning state. AppState lives in RAM, so every power cycle, reset, or reflash starts fresh. On the first wake after that, the firmware seeds parked_since with the current Unix epoch from the Notecard's clock. If a unit has already been running in the field and then gets reflashed, its clock is already synced, and the first departure carries an accurate dwell measured from the moment of the reflash. A brand-new unit at its very first power-on has no time reference until the Notecard completes its first cellular session (usually within a few minutes). If the clock isn't available yet on that first wake, parked_since stays at 0, and the first departure reports dwell_h: 0. To avoid that edge case on a new unit, let the device sit powered and stationary until a _session.qo appears in Notehub (which confirms clock sync) before the trailer moves.

A trailer that's already been running and is sitting in the yard with a charged battery should produce:

  • Zero trailer_event.qo Notes (no hookups)
  • Zero trailer_location.qo Notes (not moving)
  • One trailer_heartbeat.qo every six hours (four per day)
  • Periodic _session.qo events confirming cellular connectivity

After a hookup, departure, run, and drop, you should see two trailer_event.qo events (one departed, one arrived), plus trailer_location.qo events spaced 15 minutes apart for the length of the trip.

Bench validation with Mojo. The Blues Mojo is a precision coulomb counter that sits inline between the LiPo and the Notecarrier XI +VBAT pad, and it reports cumulative mAh to the Notecard over Qwiic at 1% accuracy. §5.1 shows where it goes inline.

Expected current draw (from the Notecard low-power design guide, the NOTE-WBEX datasheet, and the Iridium 9704 modem datasheet):

PhaseExpected draw
Notecard idle (between syncs, radio off)~8–18 µA @ 3.7V
Iridium 9704 modem between satellite sessions (cellular available, NTN not active)Powered off by Starnote; see the board-level row below
Starnote for Iridium board supporting circuitry quiescent (regulators, level shifters, supervisory MCU)Not published by Blues, so measure with Mojo before sizing
Swan host in STOP2 (woken by ATTN on D5)~2–10 µA
Swan active (brief wake cycle, ~1–2 seconds)~5–25 mA
GPS acquisition via Starnote antenna (first fix, ~30–90 seconds)~20–50 mA
Cellular session (LTE-M data transfer, NOTE-WBEX)~200–300 mA avg, ≤2 A peak
Iridium satellite session (Starnote uplink, ~15–30 seconds)~300–500 mA avg, peaks up to 8.5 A at the modem (supplied by the XI's supercapacitors)

In cell-ntn mode, Starnote cuts power to the Iridium modem whenever it isn't sending, so the modem itself adds almost nothing while cellular is available. Blues doesn't publish a board-level quiescent figure for the Starnote for Iridium's supporting circuitry (voltage regulators, level shifters, and supervisory MCU). That board-level number is the biggest unknown in this design's parked-mode power budget, and you can't state a reliable daily energy total or size the solar panel until you've measured it. Use the Mojo bench procedure (§5.1) to measure the full system's quiescent floor before you pick the final panel and battery.

Important: The Iridium modem can draw up to 8.5 A during a transmit burst. The Notecarrier XI's supercapacitor bank supplies those bursts, and the LiPo keeps the bank topped up between transmissions, so the battery must stay connected at all times. Don't run a first satellite session on a heavily discharged cell (below ~3.6 V).

For high-latitude (above 60°N), winter, or chassis-mounted deployments where panel harvest drops to 2–3 peak sun hours a day, upgrade to a 3–5 W panel and a 4 Ah LiPo so there's enough reserve to get through several cloudy days in a row.

Here are three Mojo trace signatures worth recognizing:

  • Healthy (parked, cellular available): a near-continuous quiescent floor (the measured Starnote board draw, so use this run to establish that value), a brief ~2 seconds blip every 5 minutes (motion check + Swan wake), and one 10–30 seconds cellular burst at ~200 mA every 2 hours at normal battery.
  • Satellite fallback session: a 15–30 seconds burst at ~300–500 mA with a short high peak. That's the Iridium satellite exchange, and you'll see it when cellular has failed and the Notecard routes through the Starnote.
  • Stuck awake: continuous current well above the quiescent floor means the Swan isn't entering STOP2. Check the XI ATTN → Swan D5 wire (without it, the firmware logs [sleep] ATTN sleep failed and waits out each interval awake). Also confirm the firmware was built with USB support set to None (usb=none), because with the USB CDC stack enabled the Swan leaves STOP2 within a millisecond.

Functional test without a real trailer. You can check the departure/arrival state machine without driving anywhere. Shake or tap the Notecarrier gently to set off accelerometer motion events. The Notecard counts events in 60-second buckets, but the host only wakes to query card.motion on the parked_check_mins cadence (5 minutes by default). After shaking, give it up to parked_check_mins + 60 seconds + cellular sync time (roughly 6–7 minutes at the defaults) before you expect a trailer_event.qo with type:1 in Notehub. To speed up bench testing, temporarily drop parked_check_mins to 1 with a Notehub environment variable, and the motion check fires within about 90 seconds of the shake.

For the arrival event, note the asymmetric detection latency. Once the tracker switches to STATE_MOVING, it sleeps for moving_ping_secs (15 minutes by default) between wakes. Departure detection is bounded by parked_check_mins (5 minutes by default), while arrival detection is bounded by moving_ping_mins (15 minutes by default). To see a type:2 Note after letting the unit sit still, wait up to moving_ping_mins + sync time (roughly 16–17 minutes at the defaults).

10. Troubleshooting

Device won't stay asleep (stuck awake, draining battery fast):

  • Check that the ATTN wire from the Notecarrier XI's ATTN header pin to Swan D5 is intact, and that the XI's EN pin is left unconnected.
  • Confirm the firmware was built with USB support set to None (usb=none, see §7.1). If the USB CDC stack is enabled and no USB host is attached, the STM32's USB wakeup interrupt pulls the Swan out of STOP2 within a millisecond.
  • Watch the debug output with usbSerial enabled (uncomment it in helpers.h and use the ST-LINK virtual COM port). You should see a [sleep] sleeping Ns line every cycle, then nothing until the next wake.
  • If [sleep] ATTN sleep failed follows it, either the Notecard didn't accept the card.attn request or ATTN never reached D5. Recheck the wire and the Notecard's I²C connection.

No departure/arrival events in Notehub:

  • Confirm the accelerometer is working by checking Notehub for _session.qo events (connection handshakes). If none show up, the Notecard isn't connecting.
  • Check that PRODUCT_UID is set correctly in helpers.h (Notehub: Project Settings → ProductUID).
  • Move the device physically to trigger a departure. Departure detection is bounded by parked_check_mins (default 5 minutes), so wait up to 6 minutes and then check Notehub.
  • For arrival (the device must be in MOVING state), wait up to moving_ping_mins + sync time (default ~16 minutes) for the Note to appear.

Position always shows as GPS invalid (gps_valid=0):

  • GPS is off on purpose while the trailer is parked (see §7.3). Trigger a departure so the device enters MOVING state and turns on periodic GPS.
  • Once it's moving, GPS takes 30–90 seconds to get a first fix. Position Notes embed the most recent fix, so the first Notes of a trip may show gps_valid=0 if there's no fix yet.
  • Check the antenna routing. The Starnote's u.FL port has to run through the SMA bulkhead fitting to the combined Iridium+GPS antenna outside the enclosure.

Low battery warnings (volt < 3.6V) persist:

  • The 0.6 W solar panel provides ~250–300 mAh/day in good conditions (4 peak sun hours). In cloudy weather or a high-latitude winter, harvest can fall below the daily draw. Most of that draw is radio sessions, since a ~30–60 µA quiescent floor only adds up to about 0.7–1.4 mAh a day.
  • Run a Mojo current-draw trace (§9) to confirm the measured quiescent floor. If it's well above the expected 30–60 µA range, a supporting regulator may be failing.
  • For harsh environments, upgrade to a 3–5 W panel and a 4 Ah LiPo (see §11).

Iridium fallback isn't triggering (device only sends on cellular):

  • Iridium satellite mode only kicks in automatically when cellular is unavailable. On a bench with cellular available, events always go over LTE-M.
  • To test Iridium, move the device somewhere with no cellular coverage (check with a phone). On the next transmission window, the Notecard routes through the Starnote.
  • Check that the Starnote firmware is up-to-date.

Template registration fails (see error in serial log):

  • The firmware registers the compact templates (ports 50, 51, 52) once on first boot. If registration fails, the device retries after 60 seconds (CONFIG_RETRY_SECS).
  • Confirm Notehub connectivity by checking for _session.qo events.
  • Template port collisions happen when two Notefiles share a port number. Each Notefile needs its own port (50, 51, and 52 here), so give any templates you add unused ports. Every device in a project shares one PRODUCT_UID, and that's expected.

11. Limitations and Next Steps

Every reference design has to stop somewhere, and this one stops at the core problem: tractor-independent visibility with global coverage on trickle solar. The items below are deliberate trade-offs and the places where a production deployment will add hardening. All of them were chosen on purpose, and all of them are worth knowing before you scale past a pilot.

Simplified for this POC

These are the trade-offs to understand before a pilot grows into a fleet.

Transition detection latency and GPS freshness are wake-bound. The firmware only samples motion at wake boundaries, which means every parked_check_mins while parked (for departure detection) and every moving_ping_mins while moving (for arrival detection). Transition events get stamped with the wake time and the Notecard's cached GPS fix at that moment, not the exact instant of the hookup or drop. For departure events after a long parked dwell, the GPS module has been off the whole time, so the cached fix may be the trailer's last known pre-dwell location and potentially hours or days stale. gps_valid is still 1, because the fix is structurally valid and only its freshness is in question. Retried deliveries always carry the original detection-time capture and are never re-stamped with the current state. If you need fresh departure coordinates, the firmware can be extended to issue card.location.mode {"mode":"continuous"} and poll until a valid fix comes in before enqueuing the departure event. That costs 30–90 seconds of extra GPS-on time per departure.

Satellite sync introduces latency. Over Iridium NTN, sync:true event Notes are queued instead of sent right away, because the Notecard can't interrupt a satellite orbital pass on demand the way it can wake a cellular modem. Departure and arrival events go out at the next Iridium transmission opportunity, which may be anywhere from seconds to a few minutes away depending on LEO geometry. This is documented Notecard behavior.

The first-boot dwell baseline depends on clock sync. On the first wake after any power cycle, reset, or reflash, the firmware seeds parked_since with the current epoch if the Notecard's clock is available. A brand-new unit has to finish its first cellular session to sync its clock, and if the trailer moves before then, the first departure reports dwell_h: 0. Wait for a _session.qo in Notehub (which confirms clock sync) before the first trip, so the first departure carries a meaningful dwell value.

There is no motion-event persistence check, so short moves are a blind spot. The Notecard's 60-second / 5-event motion bucket (card.motion.mode motion:5, seconds:60) is the only debounce layer. It declares a window "moving" only when five or more accelerometer events pile up within 60 seconds, which filters out brief impulses from dock impacts or vibration from nearby equipment. The host firmware, though, acts on the first parked-state wake where card.motion reports moving, with no second-sample persistence check at the host level. A single moving read enqueues a departure event right away. It follows that a move that starts and ends entirely within one parked_check_mins interval is invisible to this firmware. The trailer can leave, travel, and park again between two host wakes without the host ever seeing a moving reading. At the default 5-minute parked-check cadence, short yard moves and brief tractor hookup attempts that resolve before the next wake can slip by unnoticed. Production deployments that need to see short moves should lower parked_check_mins (e.g., to 1–2 minutes with the env var), extend the firmware to require two moving reads in a row before enqueuing a departure event, or both. The motion and seconds parameters in card.motion.mode can also be tuned per equipment type to adjust bucket sensitivity.

Each position Note carries a single GPS fix. Location Notes embed the Notecard's most recent periodic GPS fix, so on a fast highway run the fix in any given Note may be up to moving_ping_mins old. Dropping moving_ping_mins to 5 minutes with the env var gets you more frequent fixes, at the cost of more Notes per trip.

Solar sizing is minimal. The 0.6 W panel is sized to trickle-charge a parked trailer in normal operating conditions. Long stretches of cloudy weather, high-latitude winter deployments, or a shaded mounting spot may not give enough solar input to cover even the modest quiescent draw. In harsh environments, a 3–5 W panel and a larger LiPo (4 Ah or more) make more sense.

There is no tamper or cargo detection. This build only covers location and dwell. Sensors for door-open detection, cargo weight, temperature, or tire pressure are natural extensions, but this POC doesn't include them.

Mojo is bench-only. The firmware doesn't read Mojo's coulomb counter registers, and power just flows through the Mojo's power path. Adding a cumulative mAh field to the heartbeat Note would be a simple extension.

DFU is not wired up. This POC doesn't configure Notecard Outboard Firmware Update on the Swan, so field firmware updates currently need physical access to the Swan's USB-C port.

An alternative hardware path uses Skylo NTN for land routes only. For fleets that stay on North American land-route corridors inside Skylo's geostationary footprint, Notecard for Skylo (NOTE-NBGLWX) on a Notecarrier CX puts cellular, Skylo NTN satellite, GPS, and the accelerometer in a single M.2 module, without a Starnote or a separate MCU board. The same Notefile schemas (trailer_event.qo, trailer_location.qo, trailer_heartbeat.qo) and the same Notehub project still apply. Skylo's service area covers defined land-route corridors only, with no ocean-route or polar coverage. The Choosing Between Skylo and Iridium guide has the full coverage comparison.

Production Next Steps

Past location and dwell, the next steps tie the tracker into the trailer's own systems and the back office.

J1939 / trailer ABS hookup through the 7-way trailer connector would read brake and ABS status from the trailer's onboard systems whenever a tractor is connected.

A door sensor (magnetic reed switch on the rear doors) would detect load/unload events and report them in a trailer_cargo.qo Notefile.

Detention billing automation would use a Notehub route that fires a webhook into the TMS on every trailer_event.qo with type:1 (departed). The dwell_h field would drive automatic detention invoices for any dwell past the contracted free-time allowance.

Outboard DFU, which means wiring the Notecard's DFU GPIO to the Swan RESET/BOOT0 pins, would allow over-the-air host firmware updates across the whole fleet through Notehub.

12. Summary

The carrier whose $100,000 reefer used to vanish at a shipper's dock can now see it directly, with no tractor involved. A cellular Notecard plus Starnote for Iridium on a Notecarrier XI with a Swan host sends telemetry over cellular first and falls back to pole-to-pole Iridium LEO satellite. The same hardware works on a regional dry-van running I-80 and on a chassis crossing the Pacific. GPS stays off during parked dwells, the Swan sleeps between motion checks, and voltage-variable sync stretches the cellular window as the battery drains, which lets the whole device live comfortably on trickle solar. Transition events are stamped at detection time and replayed exactly across retries, so the dispatch view shows the moment a trailer left, not wherever it happened to be when the Note finally landed. The same architecture carries over to chassis pools, container yard management, and intermodal drayage, or anywhere else the question is where the unpowered equipment is, no matter who's pulling it today.

On This Page

  • 1. Project Overview
  • 2. System Architecture
    • 2.1 Swan host responsibilities
    • 2.2 Notecard and Starnote for Iridium responsibilities
    • 2.3 Notehub responsibilities
  • 3. Technical Summary
  • 4. Hardware Requirements
  • 5. Wiring and Assembly
    • 5.1 Notecarrier XI + Swan
    • Chassis deployment variant
  • 6. Notehub Setup
    • Creating the project and provisioning the device
    • Fleet organization
    • Environment variables
    • Routing
    • What you'll see in Notehub
  • 7. Firmware Design
    • 7.1 Dependencies and flashing
    • 7.2 Module responsibilities
    • 7.3 Motion and GPS strategy
    • 7.4 Event payload design
    • 7.5 Low-power strategy
    • 7.6 Retry and error handling
    • 7.7 Key code snippet 1: transport configuration
    • 7.8 Key code snippet 2: compact template definition
    • 7.9 Key code snippet 3: voltage-variable sync with host sleep
    • 7.10 Key code snippet 4: motion-triggered state transition
  • 8. Data Flow
  • 9. Validation and Testing
  • 10. Troubleshooting
  • 11. Limitations and Next Steps
    • Simplified for this 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