Every modern car has a Controller Area Network (CAN) bus that broadcasts a wealth of sensor data. Rather than tapping into the OBD‑II port with a generic dongle, I connected directly to the CAN high/low wires using a PiCAN2 hat. The Raspberry Pi runs a Python script that listens for specific CAN message IDs, parses the relevant bytes, and updates a full‑screen Pygame dashboard. The result is a responsive, low‑latency display that updates at 20 Hz – far faster than any Bluetooth OBD reader.
The hardware stack is simple: a Raspberry Pi 4, a PiCAN2 hat, a 7‑inch HDMI touchscreen, and a DC‑DC converter to step down 12V car power to stable 5V. The software side consists of a CAN reader thread and a UI thread that share a data dictionary. The UI shows a large tachometer bar, a digital speed readout, coolant temperature, fuel level, battery voltage, oil pressure, intake air temperature, and a shift light that glows yellow at 6,000 RPM and red at 6,500.
Hardware

The PiCAN2 hat sits directly on the GPIO header and connects to the CAN bus via a twisted pair of wires (spliced into the OBD‑II port's pins 6 and 14). The display uses HDMI for video and USB for touch input. Power is drawn from the car's 12V source through a 3A DC‑DC converter – this isolates the Pi from electrical noise and ensures clean startup/shutdown. A simple GPIO‑based circuit detects ignition status to trigger a graceful shutdown, preventing SD card corruption.
All components fit into a 3D‑printed enclosure that replaces the factory instrument cluster. The entire build cost under $300, including the screen, the Pi, the CAN hat, and miscellaneous connectors and cables.
Software Approach
The core logic is split into two parts: a background thread that continuously reads CAN messages and updates a shared dictionary, and a foreground thread that renders the Pygame UI at 30 frames per second. The CAN reader uses the python-can library to interface with the SocketCAN driver on the Pi. Each CAN ID is mapped to a specific sensor, and the raw bytes are scaled according to known conversion factors (e.g., RPM is a 16‑bit value multiplied by 0.25, coolant temperature is an offset of –40°F).
The UI is intentionally minimalist – large, easy‑to‑read numbers and simple progress bars. A shift light blinks at user‑defined thresholds. The whole application auto‑starts on boot via rc.local, and the ignition monitoring script triggers a safe shutdown when the key is turned off.
The Three Things I'd Do Differently

Add a Real‑Time Clock (RTC) module. The Raspberry Pi doesn't have an onboard RTC. Without Wi‑Fi, every datalog timestamp starts from 1970. A $10 DS3231 module would have solved this and made data analysis much more meaningful.
Invest in a sunlight‑readable display. The 7‑inch screen I used looks great in the garage but is almost invisible in direct sunlight. Next time, I'd choose a display with at least 800 nits of brightness or add a built‑in sunshade.
Use a DBC file for CAN decoding. Instead of manually reverse‑engineering every CAN ID by correlating raw values with sensor readings (which took two weekends), I should have created or sourced a DBC file – a standard format that maps CAN IDs to physical values. Using a library like
cantoolswould have made the parser infinitely more maintainable and reusable.
Building your own digital dash is deeply rewarding. It gives you full control over what data you see, how it's presented, and how it's logged – all without relying on proprietary software or expensive commercial units. But it's not a weekend project. You'll need patience, basic soldering skills, and a willingness to read CAN bus documentation. If you're comfortable with Linux and Python, the learning curve is manageable.
For anyone considering this path: start by sniffing your car's CAN bus with candump to identify the messages you care about. Then build a simple text‑based reader before touching Pygame. And do yourself a favor – buy the brighter screen and the RTC from the start.
I've published my full BOM, wiring diagrams, and a simplified DBC file for common BMW E36 ECUs on my GitHub. The project isn't perfect, but it works – and every time I drive, I see data that my factory cluster never showed me.
No comments yet.