MCU programming
Last updated:
Every ESci device ships with an STM32L0-family MCU on board, and every assembly guide reaches a step where firmware has to be flashed onto that MCU. The canonical tool for this is ESProgrammer — a desktop app that handles the toolchain, picks the right binary from the API, flashes the board, and registers the flash event back to the cloud. This page is the reference for how — guides should link here rather than re-document the workflow.
The canonical source for setup, releases, and internals is the ESProgrammer repo. When that diverges from what’s documented here, the repo wins.
Hardware
Section titled “Hardware”- Target board: any ESci device. All run the same STM32L0 family MCU.
- Programmer: the ESProgrammer device — ESci’s custom USB-to-Serial flasher (not to be confused with the ESProgrammer app, which runs on the workstation).
- Cable: TagConnect, between ESProgrammer device and the target’s programming pads.
Tool — the ESProgrammer app
Section titled “Tool — the ESProgrammer app”Install once per workstation, following the repo’s Getting started. Summary:
git clone https://github.com/EnsembleScientific/esprogrammercd esprogrammerbrew install uvuv venv -p 3.13source .venv/bin/activateuv pip install -e .esprogrammerOn first launch, open Preferences and enter your ESci username and password — the app uses this to sync the device catalog and pre-built firmware binaries from the API.
Production workflow
Section titled “Production workflow”Standard assembly-line flash:
- Plug the ESProgrammer device into the workstation. Switch ON.
- Launch the app (
esprogrammerif you set the alias, otherwisepython -m esprogrammer). - Click Sync in the app to pull the latest device list and binaries (only needed when firmware has changed).
- Connect the target to the ESProgrammer via TagConnect.
- Press the ESProgrammer device’s reset button.
- In the app, select the device (by part number or firmware name) and click Flash.
- The app flashes, verifies, and registers the flash event with the API — the device’s firmware version is now tracked in admin.
For repetitive flashing of the same firmware (e.g., batch production), use CLI mode:
python -m esprogrammer <firmware-filename> -p <port>The -p argument is optional — the tool auto-detects the port if only one ESProgrammer is connected.
Firmware filename
Section titled “Firmware filename”Every device’s firmware target lives in admin under firmware_filename. The app uses that field to pick the right binary. Examples:
| Device | Firmware filename |
|---|---|
| Spruce Node | NodeSpruce |
| HydroPulse Direct V3 | HydroPulseDirectV3 |
| IR Temperature Sensor | SensorIRTemp |
| Drip Line Pressure Sensor | SensorDriplinePressure |
If a device has no firmware filename in admin, it isn’t ESci-managed firmware (e.g., third-party integrations like the LI-COR ET sensor) — the flash step doesn’t apply.
Troubleshooting
Section titled “Troubleshooting”- App doesn’t see any port: confirm the ESProgrammer device’s switch is in the ON position and the USB cable is good. Some hubs swallow the device — try plugging directly into the workstation.
- Flash fails immediately: the target wasn’t in reset mode when you clicked Flash. Press the ESProgrammer reset button first, then Flash within a few seconds.
- App says the firmware isn’t synced: hit Sync in Preferences. If sync fails, check your credentials and the API URL.
- Device boots but reports the wrong firmware: the wrong binary was flashed. Confirm the device’s
firmware_filenamein admin matches what the app shows, and re-flash.
Outside the assembly path
Section titled “Outside the assembly path”- Firmware development (compiling from source, working with the Arduino toolchain directly): see ESFirmware/README. The ESProgrammer app uses
arduino-cliinternally and can be set up viapython -m esprogrammer -c, but for hands-on development the Arduino IDE path in that README is more direct. - Recovery / inspection (bricked board, custom hex inspection): STM32CubeProgrammer connects directly to the MCU over serial without the app abstraction. Out of scope for production assembly; reach for it only when something has gone wrong upstream.