Goal
Bring everything together: the production TFT UI from v0.3 + the live OBD2 data layer from v0.2 (Bluetooth ELM327). This is the last milestone before the data source changes from ELM327 to direct CAN (v1.0).
Why this phase matters
It validates the data/display layer separation in practice. The UI code from v0.3 should work as-is, and the BluetoothSerial + ELMduino data functions from v0.2 should plug straight in. If either needs rewriting, the abstraction leaked — and the v1.0 CAN swap would be painful.
Hardware
- ESP32 DevKit v1 (built-in Bluetooth Classic — no radio module needed)
- 3.2” ILI9488 SPI TFT (same wiring as v0.3, GPIO18/23 SPI + CS/DC/RST on 15/2/4)
- Bluetooth ELM327 dongle (same one paired in v0.2)
No CP2102, no USB ELM327 cable, no soldering. The dongle lives permanently in the car’s OBD2 port.
Runtime architecture
ESP32 boot
→ init TFT via TFT_eSPI
→ SerialBT.begin("ESP32-DashDisplay", master=true)
→ SerialBT.connect(dongleMAC) ← retry until paired
→ ELMduino.begin(SerialBT)
→ loop:
data layer: ELMduino query (RPM / Speed / Coolant / Boost / Volts)
display layer: draw gauges on TFT (unchanged from v0.3)
SPI bus (TFT) and Bluetooth radio (ELM327) run independently — no pin contention.
Status
Pending v0.2 (Bluetooth ELM327 streaming) and v0.3 (TFT full UI) completion. Once those are solid, this phase is mostly plumbing — plus benchmarking the OBD request-loop latency against the target gauge refresh rate.
What comes next
Once v0.4 is verified, the project forks off to v1.0 — replacing the ELM327 with an MCP2515 CAN controller tapped directly into the BMW’s CAN-H / CAN-L. See the CAN bus wiring doc for the plan.