
Previously, the instrument cluster only showed the basics: RPM, speed, temperature. Now you can display pretty much anything you want—video from a bumper-mounted camera, traffic signs, a fuel consumption chart.
A modern car is essentially a large computer network packed with sensors and actuators. However, you can only access information about how they’re operating using dedicated diagnostic tools.

The more expensive the car, the more useful information its factory-installed onboard computer displays.
Exploring the possibilities
Modern vehicles use the CAN bus to connect sensors, buttons, actuators, and electronic control units (ECUs). Every sensor that transmits data includes its own ID in each message. All other devices on the bus see these messages and decide for themselves whether to act on them.
For example, the engine coolant temperature sensor sends data, the ECU uses it in its control logic, and the instrument cluster displays the engine temperature.

To access information about a vehicle’s systems, you need to connect to the CAN bus. There are several ways to do this.
- Tap directly into the vehicle’s wiring. This method requires partially disassembling the car.
- Connect via the OBD-II diagnostic port.
In VAG-group vehicles (Volkswagen, Audi, Škoda, Seat), the OBD2 port is connected to the CAN bus through a gateway, so there’s no direct access to the bus. This means that if you try to sniff traffic at the OBD2 connector, you won’t see anything from the main network. The gateway prevents messages from the primary network from reaching the diagnostic port. However, there’s the official VCDS diagnostic suite, which lets you view all sensors, read fault codes, and configure components over OBD2.
It works like this: for each sensor, VCDS queries the gateway for its status; once the gateway has it, it relays the data over the OBD-II interface.

So, by sniffing what VCDS is requesting, you can extract the list of commands used to poll the sensors.
CAN Bus Sniffer
Using an Arduino Uno and a TJA1050 Niren module with an MCP2515 CAN controller, I built a sniffer that can be connected anywhere on the CAN bus to passively listen to traffic. The sniffer is non-intrusive and doesn’t affect system operation. To capture what VCDS is sending, you need to tap into the diagnostic cable by soldering onto the CAN High and CAN Low pins.

Once you plug the cable into the OBD2 port, you can monitor all traffic between the gateway and VCDS using CANHackerV2. There’s a dedicated Arduino sketch: it receives CAN data and sends it via a UART→USB converter in a format that CANHackerV2 understands. The sketch is open-source and available on GitHub.

After sniffing the VCDS traffic, I put together a list of commands the car supports and can be queried with.
Doors:
-
714— request;03 22 22 0D 55 55 55 55 -
77E— all doors closed;05 62 22 0D 55 65 AA AA -
77E— all doors open.05 62 22 0D 00 65 AA AA
Fuel level:
-
714— request;03 22 22 06 55 55 55 55 -
77E— 44 liters;04 62 22 06 2C AA AA AA -
77E— 22 liters.04 62 22 06 16 AA AA AA
Oil temperature:
-
714— request;03 22 20 2F 55 55 55 55 -
77E— -4 °C;04 62 20 2F 36 AA AA AA -
77E— 45 °C.04 62 20 2F 67 AA AA AA
Now we need to figure out whether there’s a way to obtain this data without the official diagnostic equipment, so we can display it.
ELM327 OBD-II Scanner
Since 1996, all cars must support the OBD‑II specification, which defines a 16‑pin diagnostic connector. The OBD‑II port must be located in the vicinity of the steering wheel or somewhere nearby. The specification also includes a standard set of commands that all vehicles are required to support.

Many car enthusiasts know about the inexpensive ELM327 diagnostic scanner, which lets you perform basic diagnostics on virtually any car that supports the OBD-II protocol: read and clear fault codes, and query the engine control unit for data such as vehicle speed, RPM, temperature, and misfires.

There’s plenty of software for the basic ELM327 functions. But developers know the ELM327 can do much more. It supports twelve different protocols, including ISO 15765-4 (CAN). In other words, a diagnostic scanner can access the CAN bus and communicate with it.
To enable the ELM327 to send requests and receive data over the CAN bus, you need to configure it. To do this, connect to the scanner’s UART console via Wi‑Fi, Bluetooth, or a wired connection, and issue a set of AT commands as described in the ELM327 documentation: https://www.elmelectronics.com/wp-content/uploads/2016/07/ELM327DS.pdf.
-
atz— reset the adapter; -
at— turn echo off;e0 -
at— set the target CAN ID for requests (0x714);sh 714 -
at— set the expected response CAN ID (0x77E);cra 77e -
at— set Flow Control CAN ID to 0x714;fc sh 714 -
at— set Flow Control data to 30 00 00;fc sd 30 00 00 -
at— Flow Control mode 1 (user supplies both ID and data);fc sm 1 -
at— allow long messages (>7 bytes);al -
at— set protocol to ISO 15765-4 CAN (11-bit ID, 500 kbps);sp 6 -
at— disable CAN automatic formatting;ca f0 -
at— turn linefeeds off.l0
After configuring the ELM327, let’s run a test query. We request the oil temperature (03 ) and receive the response: 05 .
CAN bus messages are transmitted at 500 kbaud (about 500 kbps), which is very fast. An ELM327 is much slower: the average request–response time is around 50 ms, so you can only make about twenty requests per second. Keep this in mind when designing an application that polls sensors and updates the display.
Building an iPhone App
Many automakers release mobile apps that let you remotely start the engine, turn on the climate control, and monitor fuel levels.

I decided to build a mobile app for phones and tablets that can function as a car dashboard.
The app will target iOS, but the ELM327 communication logic is the same on Android. To develop iOS apps you need Xcode. Apple officially supports two programming languages: Objective-C and Swift. The latter is newer, simpler, and provides better protection against common errors.

In the initial version of the app, the priority is to establish a stable foundation for communicating with the Wi‑Fi ELM327 scanner, so it’s easier to expand the app’s feature set later.
The CocoaAsyncSocket framework is easy to use and stable; it works directly with TCP and UDP sockets. It lets you initiate connections, send and receive data, and close the connection.

Once the ELM327 communication code is debugged, you can move on to building the virtual dashboard interface itself. The app’s design shouldn’t distract from driving, but it still needs to be informative and easy to read.

After placing the sensor widgets on the storyboard, you need to hook them up to your code. In Xcode, this is done using connections (outlets). Once that’s set up, whenever the sensor updates, its value will be assigned to a variable and displayed in the widget.

The foundation of the app is ready. Right now, it shows which doors are open and key vehicle data.


A long press on the TRIP stalk changes the instrument cluster display theme.

I tested the app on several cars:
- Škoda Octavia A5 2011 Ambiente;
- Škoda Octavia A5 2012 L&K;
- Škoda Yeti 2011 Ambiente;
- Škoda Octavia A7 2014 Elegance.
On the latter, only some of the parameters are shown. The app should also work with other models from the VAG group (Volkswagen, Audi, Škoda, Seat).
Conclusion
The project was originally conceived as a research effort. We wanted to understand how a car’s electronic systems work and how they could be improved. The knowledge we gained led to a simple mobile app that anyone can try.