-
Notifications
You must be signed in to change notification settings - Fork 13
Programming Guide
This page covers building the firmware from source and flashing it over a wire.
💡 Most people don't need this. Day-to-day firmware updates happen over the air from the web portal — see Firmware Update. Reach for wired flashing only for development, for the one-time OTA partition migration, or to recover a device that won't boot.
MiniSpeedCam has two microcontrollers, each with its own firmware project:
| MCU | Part | Role | Project |
|---|---|---|---|
| ESP32 | ESP32-S3-WROOM-1 (8 MB flash, 8 MB PSRAM) | Camera, WiFi, web portal, uploads | firmware/platformio/esp32_firmware_platformio |
| STM32 | STM32F301K8U6 (Cortex-M4F) | Radar DSP — samples the CDM324 and reports a speed | firmware/platformio/stm32_firmware_platformio |
Both are built with PlatformIO (the VS Code extension,
or the pio CLI). Install it first.
The ESP firmware needs a bootstrap token supplied as an environment variable — the build fails on purpose if it's missing, so the secret is never committed to the repo. Set it before building:
# PowerShell
$env:MSC_BOOTSTRAP_TOKEN = "your-token-here"# bash
export MSC_BOOTSTRAP_TOKEN=your-token-hereFrom the esp32_firmware_platformio folder:
pio run # compile
pio run -t upload # flash over USB
pio device monitor # serial console @ 115200 baudThe ESP32-S3 uses its on-chip native USB for the serial console, so you don't need a separate USB-to-serial adapter — the same USB cable used to flash carries the console.
- Defaults target an ESP32-S3-WROOM-1-N8R8 (8 MB flash, 8 MB OPI PSRAM). For a
different module, adjust
board_build.arduino.memory_type,board_upload.flash_size, etc. inplatformio.ini. -
FW_VERSION(a build flag inplatformio.ini) is the version this image reports to the cloud and the OTA check. Bump it on every release so devices can tell a new build apart. - The API base URL defaults to the test environment; uncomment the live URL build
flag in
platformio.inifor production builds.
Over-the-air updates need a dual-app flash layout (two firmware slots, so a new
image can be written to the inactive slot and switched on reboot). A unit flashed
before OTA support used a single-slot layout and must be wired-flashed once to
migrate onto the new table (partitions_8mb_ota.csv).
- Survives the migration: WiFi credentials and saved settings (they live in NVS, which keeps its address).
- Wiped by the migration: the SPIFFS data partition.
After this one wired flash, all future updates can be done over the air.
The STM32 is flashed over a USB-to-UART (CH340) adapter using the chip's built-in
ROM serial bootloader (via stm32flash). The PlatformIO project is already
configured for this (upload_protocol = serial).
The STM32 only listens for a serial flash when it boots with BOOT0 held high. The exact procedure depends on your harness, but the pattern is:
- Connect the CH340 adapter to the STM32's debug UART.
- Hold BOOT0 high, then reset/power-cycle the STM32 so it boots into the ROM bootloader. (Unplug, hold BOOT0, replug.)
- Set
upload_portinplatformio.inito your adapter's COM port (it varies by machine — check Device Manager /pio device list).
From the stm32_firmware_platformio folder:
pio run # build -> .pio/build/genericSTM32F301K8/firmware.{elf,bin,hex}
pio run -t upload # flash over the CH340 serial bootloader
pio run -t size # report flash/RAM usageAfter flashing, return BOOT0 to its normal (low) state and reset so the STM32 runs the application instead of the bootloader.
ST-Link / SWD is only needed for debugging; normal flashing uses the serial bootloader above.
This firmware is tight on RAM — roughly ~45 KB / 64 KB flash and ~16 KB / 16 KB RAM. Keep that in mind before adding buffers.
The ESP32 is the master: it resets the STM32, polls it for speed over a shared UART,
and acts on the results (camera, uploads, sleep). The full electrical + protocol
contract between the two — pinout, UART command set, checksummed reply format, the
WiFi-TX radar-blanking handshake — is documented in INTERFACE.md in the firmware
folder (firmware/platformio/INTERFACE.md). Read it before changing anything that
crosses between the two chips.