Files
MicrOBU/obu-firmware/FLASHING.md
T
Ashin WalpolaandClaude Opus 5 f3ae81a8fe Phase 03: CAM decode coverage, real sensor data in TX, V2X monitor for ESP32 path
CAM codec:
- Stop rejecting CAMs carrying a specialVehicleContainer. It is declared last in
  CamParameters, after everything this decoder reads, so buses / emergency
  vehicles / road-works vehicles now decode for position and kinematics instead
  of being dropped outright
- Drop the lowFrequencyContainer parse - it extracted nothing into Cam, and its
  reads were only correct when no high-frequency optionals were present
- Document why the 7 optional-presence bits are consumed but not acted on: UPER
  writes a SEQUENCE's presence bitmap up front but each field's value in
  declaration order, and all seven are declared after yawRate
- Field widths and container ordering verified against the ETSI ASN.1 sources in
  the C-ITS-Parser checkout, not from memory

Transmit path:
- Own StationID is now a persisted random 32-bit value instead of a hardcoded 0.
  Receivers key on StationID to track a station across CAMs, so every unit
  broadcasting 0 made two MicrOBUs indistinguishable - including to this app's
  own detection engine
- Populate longitudinalAcceleration from successive GNSS speed samples. Not from
  the accelerometer: CAM wants signed along-track acceleration, and the raw
  sensor is device-frame with gravity in it. Null outside a usable sample gap
  rather than a fabricated value
- CAM pinger builds from live GNSS/IMU via PhoneCamBuilder instead of beaconing a
  hardcoded bench coordinate with speed and heading pinned to zero, so it now
  exercises the sensor pipeline and not just the wire. Sends nothing without a
  fix, and reports that rather than sitting at "Sent: 0"

V2X monitor:
- Received-CAM pane for the ESP32-C5 path, replacing the MQTT topic list that is
  permanently empty there. One row per station rather than per message - CAMs
  arrive at 1-10 Hz per station, so the pane is bounded by road users nearby, not
  by traffic rate. Nearest first, tinted by active alert level
- DENM hazard pins on the live map as a warning triangle, drawn above vehicle
  markers. CiT One path only: the ESP32 firmware forwards BTP-B port 2001 (CAM)
  and drops port 2002 before it reaches the phone

DenmParser uses tolerant field-name matching - the Use Case API's DENM JSON
schema is not yet confirmed against real payloads.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 14:09:18 +02:00

4.6 KiB

obu-firmware — setup & flashing notes

Every new PowerShell session

Activate the toolchain (obu-firmware has no esp-idf of its own — reuse the receiver firmware's already-installed checkout):

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
C:\Users\Ashin\Documents\micrOBU_workspace\its-g5-receiver-firmware\esp-idf\export.ps1
idf.py --version

Build & flash

cd C:\Users\Ashin\AndroidStudioProjects\MicrOBU\obu-firmware
idf.py set-target esp32c5      # only needed once per clean build folder
idf.py build
idf.py -p COM5 -b 921600 flash monitor

Swap COM5 for whatever port the ESP32-C5 enumerates as (Device Manager → Ports). monitor opens the serial console after flashing — Ctrl+] to exit.

If the build fails

  • "includes X.h, provided by Y component(s)... not in the requirements list" — IDF 5.x split the old monolithic driver component apart (esp_driver_gpio, esp_driver_uart, etc.). Add the named component to REQUIRES in main/CMakeLists.txt and rebuild. Already fixed once for esp_driver_gpio + esp_driver_uart — if a new header comes up, same fix.
  • Otherwise, start clean before re-building:
    idf.py fullclean
    idf.py build
    

Connecting the phone (ESP32-C5-WIFI6-KIT)

The board has two USB-C ports — use the right one:

  • Native USB-C port (labeled for JTAG/native USB, up to 12 Mbps) — this is where the phone plugs in via USB-OTG. The CAM serial link (serial_link.c) runs over the ESP32-C5's native USB Serial/JTAG peripheral on this port, enumerating as a CDC-ACM device under Espressif's VID/PID (0x303A/0x1001).
  • UART-bridge port (labeled for flashing) — this is what you use for idf.py flash monitor from your PC. Leave the phone unplugged from this one; it only carries idf.py's flashing protocol and the ESP_LOG console.

The app recognizes the ESP32-C5's VID/PID via a custom probe table in UsbSerialTransport.kt (the default usb-serial-for-android prober doesn't know Espressif's device IDs). If the phone doesn't detect anything when plugged into the native port, first confirm with a tool like "USB Device Info" (or adb shell dumpsys usb from a PC) that Android sees a USB device at all — that isolates a bad/charge-only OTG cable from an app-side issue.

Work down this list — each step isolates the layer below it.

  1. Flash and install together. SERIAL_LINK_MAX_PAYLOAD is 512 on both sides. A phone at 512 talking to firmware still at 160 (or vice versa) silently rejects every large frame at the length exceeds max, resync branch. Never update one side alone.
  2. Does Android see the device at all? Plug the phone into the native USB-C port, hit Connect, and read logcat for UsbSerialTransport. It logs every attached device and each device's interfaces. Empty list = cable / OTG / wrong port, below the app entirely.
  3. Did the right interface get claimed? The C5's USB Serial/JTAG is a composite device — expect CDC control (class 2) + CDC data (class 10) + vendor-specific JTAG (class 255) in that dump. Compare against the ports= count on the matched device line.
  4. Is the link alive? The firmware sends a STATUS heartbeat at 1 Hz regardless of radio traffic, and the app marks the link ERROR after ~3.5 s of silence. Connected-and-staying-connected means device→host actually works.
  5. If it connects but no CAM_RX ever arrives — suspect DTR. The app now asserts DTR/RTS on open (openDevice() in UsbSerialTransport.kt), because CdcAcmSerialDriver doesn't do it by default and the ESP32's USB Serial/JTAG endpoint may gate TX on the host opening the CDC line. This is still unverified on real hardware — test it both ways (with the setDTR(true) call and with it commented out) and record the answer in serial_link.h next to the VID/PID note, so nobody has to guess again.
  6. Watch the counters, not just "Sent: N". The CAM Pinger card shows consecutive write failures (phone side) and the firmware's tx-failure / oversize-drop / CRC-error totals from the heartbeat. A rising tx fail means CAMs reach the ESP32 but esp_wifi_80211_tx rejects them — a radio problem, not a link problem.

Notes

  • No git submodule update needed here — obu-firmware has no pinned submodule of its own, unlike its-g5-receiver-firmware.
  • Don't use the global "ESP-IDF 5.5 PowerShell" shortcut — always export from the receiver-firmware's pinned checkout, since this firmware's undocumented PHY/driver internals were verified against that specific build.