No description
  • C++ 91.1%
  • Python 8.9%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-11 17:37:37 +02:00
docs Remove unit and status lines and enlarge dashboard digits 2026-10-11 17:37:37 +02:00
include Display temperatures as rounded whole degrees 2026-10-11 17:24:11 +02:00
scripts Implement Core2 Octavia BLE telemetry display 2026-10-11 17:12:48 +02:00
src Remove unit and status lines and enlarge dashboard digits 2026-10-11 17:37:37 +02:00
test/test_telemetry Display temperatures as rounded whole degrees 2026-10-11 17:24:11 +02:00
.gitignore Implement Core2 Octavia BLE telemetry display 2026-10-11 17:12:48 +02:00
platformio.ini Implement Core2 Octavia BLE telemetry display 2026-10-11 17:12:48 +02:00
README.md Remove unit and status lines and enlarge dashboard digits 2026-10-11 17:37:37 +02:00

Octavia onboard display

M5Stack Core2 firmware built with PlatformIO. Starts scanning immediately on power-up; no pairing, BLE connection, phone, or USB computer is required.

The landscape 320 × 240 screen shows coolant, intake air and Haldex clutch oil temperatures in °C rounded to whole degrees, and actual charge pressure in bar with two decimals. Pressure is absolute, before the throttle, as documented by the diagnostic transmitter; it is not gauge boost pressure.

Black background and white labels. Fresh readings are white; retained stale readings are orange, and unavailable readings show an orange --. A missing BLE signal clears all readings after two seconds; reception restores them automatically. Four tiles fill the screen, with approximately 91-pixel-high seven-segment numbers. Each tile contains only its label and reading, with no unit or status lines. Long values are narrowed to fit while retaining their height. Detailed BLE, cache and fault status is available over USB.

Preview captured from the Core2 using sample readings (temperatures in °C, pressure in absolute bar):

Dashboard with whole-degree temperatures and pressure in bar

Build and upload

$env:PYTHONIOENCODING = 'utf-8'
platformio run -e core2
platformio run -e core2 -t upload --upload-port COM4
platformio device monitor -p COM4 -b 115200

COM4 is the connected CH9102 Core2 as detected during setup. Use platformio device list if the port changes. Versions of the platform and direct libraries are pinned in platformio.ini.

Receiver behavior

Uses passive, continuous BLE scanning with repeated reports enabled, inspecting AD type 0x21 directly for UUID 37f8fc84-7412-4ac3-adc3-adb94faab82c. There is deliberately no service-UUID-list filter: the transmitter does not advertise that list. Scan results are not accumulated in RAM. The scanner is restarted automatically if it stops.

Supports schemas 1 (10 bytes), 2 and 3 (13 bytes), checks exact lengths, availability bits, sentinels and age consistency, and rejects unsupported or malformed packets without refreshing the timeout. Negative temperatures are preserved. Schema 3 Haldex age is in two-second units. Engine samples older than two seconds are shown in orange; Haldex freshness is 320 seconds for schema 3 and 45 seconds for earlier schemas. Fault flags mark retained values stale. Local elapsed time advances sample ages between advertisements.

By default, the display binds to the first valid Octavia broadcaster until reboot, so it cannot mix values from multiple transmitters. Set config::transmitterAddress in include/config.h to pin a particular public BLE address (the documented board is B4:3A:45:AE:5D:B9). Brightness is also configured there. BLE callback data is copied under a lock; rendering runs in the main loop using a full-screen canvas to avoid flicker.

Protocol sources: ../octavia-diag/docs/ble-message.md, the historical ble-message-v1.md / ble-message-v2.md, and ../octavia-diag/scripts/ble_scan.py. Core2 drivers follow M5Stack's M5Unified guidance. Scanning uses the NimBLE scan API.

Verify on hardware

platformio test -e core2 --upload-port COM4 --test-port COM4
platformio run -e core2 -t upload --upload-port COM4

Tests temporarily replace the application with the test firmware. Upload the application again afterwards. Tests cover documented packets, all schema versions, negative temperatures, malformed data, partial group availability, cache boundaries, fault independence, timeout, clock rollover and pressure formatting.

The running firmware prints status every five seconds. USB command s prints an immediate status, including scan state, bound address, packet count, schema and field values. Command p exports the actual rendered framebuffer:

python scripts/capture_display.py --port COM4 --output artifacts/display.ppm

The script uses pyserial, included in the PlatformIO Python environment. Close the serial monitor before using the capture script or uploading.