Skip to main content

← All posts

Deep Dive

Peregrine and Milepost: What's Changed

· 5 min read

Two modules with substantial progress this week. Peregrine is getting a pre-built image installer that takes the setup path from a multi-step provisioning process down to flash, boot, and answer a few questions. Milepost completed its firmware sprint with user-configurable buttons, web-based OTA updates, and a full dashboard UI running on the 7-inch display.

Peregrine: moving to an image installer

The current Peregrine setup path works, but it asks more of the builder than it should. You flash a stock Radxa OS image, SSH in, and run a provisioning script that installs packages, downloads the NPU model and voice files, builds a Python virtual environment, and configures the systemd services. Each new board starts from nothing and the install is long.

The replacement is a pre-built Ubuntu Noble 24.04 image with everything already inside: the Llama 3.2 1B model staged for the Qualcomm Hexagon NPU, the Piper TTS voice, the wake-word models, the full Python environment, and all five systemd services already enabled. Flash the image in about ten minutes. The board handles the rest.

First boot is automatic. The board regenerates its SSH host keys (intentionally stripped from the image so every board gets unique credentials), expands the filesystem to fill the NVMe, and reboots cleanly. First login triggers an interactive setup wizard that runs four steps: forced password change, optional MQTT broker configuration for connecting to Headwaters, optional static IP setup, and an eight-point hardware self-test that checks the Jabra Speak mic, speaker playback, the Qualcomm CDSP coprocessor, the NPU genie server, and the voice assistant service itself.

All site-specific configuration lives in a single environment file in the home directory. Future firmware updates do not touch it. The wizard is re-runnable any time from the command line.

This brings Peregrine onto the same conceptual path as Headwaters. The ESP32-based modules get flashed from the browser via the web flasher. The Linux modules get pre-built images. Neither one requires babysitting a setup script through a fresh OS install.

The build pipeline is written and the image has been through initial validation. Final testing of the wizard and documentation cleanup are the last steps before the tagged release. Watch the Peregrine repo for it.

Milepost: firmware sprint complete

The April 8 post left off with the hardware finalized and a firmware sprint underway. That sprint is done. Here is what landed.

User-configurable buttons

Milepost has eight control buttons on the main dashboard. Previously the mapping between a button and a TrailCurrent PDM module (Torrent, Switchback) was fixed in firmware. Now the user configures it. Pick the module, pick the icon from a library of 82 curated FontAwesome icons, set the label, and the preference is stored in non-volatile storage. The configuration survives power cycles and firmware updates. If your layout changes, you change the button map without touching code.

This matters for flexibility. Not every installation has the same set of devices, and not every device should live on the same button slot. The configurable system means the display adapts to the vehicle rather than the other way around.

Web-based OTA updates

Milepost already supported triggering an OTA firmware update via a CAN bus message. It now also accepts updates over HTTP. POST a firmware binary to the board's local address and the update runs. No CAN controller required, no physical access to the bus. This makes development iteration faster and gives installers a simpler path for field updates on deployed units. The About screen now shows the running firmware version, the board's MAC address, and other diagnostic details so you always know exactly what is on the board.

Full UI on the 1024x600 display

The earlier firmware sprint got the display, touch input, backlight dimming, and WiFi working. The current state goes further. The full dashboard is running: battery state of charge, voltage, wattage, and time-to-go; solar MPPT charge status; interior temperature and humidity from the thermostat; GPS satellite count and elevation; and the eight configurable device control buttons. The Water screen is fully implemented and displays live Reservoir data. The leveling screen is ready and waiting for Plateau to come online. The UI was built in EEZ Studio and renders via LVGL 8.4 with double-buffered PSRAM framebuffers to keep transitions smooth and tearing-free.

The Water page layout was aligned with Fireside's conventions during this sprint, which keeps the visual language consistent across the display modules. If you know how to read the data on one, the other looks familiar.

Follow the Milepost repo for the detail page and build guide as the module moves toward its 1.0.0 release.

A platform pattern: OTA and discovery for wireless modules

Milepost's web-based OTA is part of a broader pattern that started with Fireside. When Fireside moved from CAN bus to WiFi and MQTT earlier this year, it became the first wireless MCU in the platform to get the same discovery and OTA capabilities that wired CAN modules have always had. The mechanism is different (MQTT instead of CAN messages) but the result is the same: the module announces itself when it comes online and can receive a firmware update without anyone touching it physically.

That pattern is now the standard for every wireless MCU in the TrailCurrent lineup. Fireside and Milepost are both on it. Spotter, Picket, and any other WiFi-connected module will follow the same approach.

What this enables at the system level is worth naming directly. Headwaters already distributes firmware to wired CAN modules from a single update bundle: one zip file, dropped into the right place, triggers coordinated updates across every node on the bus. Wireless modules joining the same discovery and OTA mechanism means that same bundle can cover the entire installed system. Wired modules, wireless displays, and WiFi sensors all update from one source, in one operation, without needing physical access to any of them.

That zip file now has two upload paths depending on how your system is set up. Farwatch, the cloud application, already supported uploading an update bundle through the UI. Overlook, the local PWA that runs directly on Headwaters for users who don't run a cloud deployment, now has the same thing. Upload the zip through the Overlook interface and the update goes out across the system, no SSH, no scp, no command line required. Whether your installation is cloud-connected or fully offline, the update experience is the same: one file, one upload, done.

It is a small architectural decision at the individual module level that compounds into something meaningful when the whole platform is running together.