In progress · Audi S5 B9 · one car

The numbers the factory dashboard
rounds off.

A second instrument display for a track-driven Audi S5. An ESP32 listens to the car's CAN bus without ever speaking to it, decodes the traffic into real units, and streams it over its own WiFi to the Android screen in the console fifty times a second. What arrives is everything the driver's own cluster smooths over - and, more to the point, where those numbers are heading next.

  • ESP32
  • CAN / TWAI
  • C++ · PlatformIO
  • Ionic
  • Angular
  • Capacitor
  • WebSocket
  • Android

A simulation, running in this page - not a car. The shape of the drive is taken from the recorded sessions, so the brackets are real: shifts near 6000 rpm, half a g under acceleration, oil swinging between 105 and 125 °C through repeated full-throttle pulls.

What it does

A gauge tells you where you are.
This one tells you where you are going.

Anything can print a temperature. The work went into the layer above it: deciding what is worth saying, when to say it, and when a number that looks alarming is only a load swing and should be left alone.

Monitoring

The temperatures, undamped

The factory cluster smooths the water gauge into bands and its oil reading does not wake up until 60 °C. This one shows oil, water, charge air and the intercooler delta to the degree, each with ten minutes of trend under it and a two-minute change beside it - because the direction a temperature is moving is worth more than the number.

Prediction

Ninety seconds before, not after

Not "the oil is over 120" but "the oil will be over 120 in about ninety seconds". Five rules keep the projection honest, and the fifth came from a drive: the arithmetic was right and the warning was still wrong for a hundred seconds, because a load swing can carry a temperature two degrees and only a real trend carries it seventeen. A projection now has to be short in value as well as in time.

Protection

Two warnings a threshold cannot give

A downshift that would land the engine past its limiter - predicted from gear ratios the display learns from the car itself rather than from a table of guesses - and an oil cooler that has quietly stopped keeping up, which shows as a gap between oil and water long before either crosses a line. It also answers the one question with an answer rather than a number: whether the turbo is cool enough to switch off.

Shift light

Twenty-six bulbs, and one of them blue

The bar fills from both outer edges inwards, green to yellow to red, then flashes blue at the shift point and red once the shift is late. Blue is the instruction, red is the reproach. The point it aims at is computed rather than copied - shift where the power you land on first matches the power you have - and it drops while the oil is still cold.

Timing

Runs only count when you meant them

Standing, rolling, braking and distance brackets, all timed on the ESP32's own clock at hundredths of a km/h. Every accelerating run is gated on the pedal being on the floor for the whole of it, every braking run on the brake staying on, and an interrupted run is thrown away rather than saved with a worse time. Only the brackets actually driven are shown, so the sheet is never a page of dashes.

Dynamics

A friction circle from four wheel speeds

There is no accelerometer on this bus and there never will be. But four wheel speeds at 50 Hz give yaw from the side-to-side difference and longitudinal g from the derivative of road speed, which is both axes of a g-g diagram. Validated against a real drive: 0.31 g right, 0.29 left, 0.59 accelerating, 0.46 braking, every peak landing on an event the other signals mark independently.

  • Session log

    The screen sits to the driver's left and is not read while moving, so its far side carries the one thing that can wait: shifts, lock-ups, peaks and warnings, listed as they happened.

  • Peak holds

    Highest oil, water, intercooler delta, rpm and speed since the session was reset. Fed frame by frame rather than through the UI, because a wheel that locked for 200 ms is exactly the sample a render pass would miss.

  • Link quality

    Packet loss measured from the ESP32's own millisecond clock, not the phone's - so a stalled head unit can never be mistaken for a radio problem, and no protocol change was needed to find out.

  • Tyre pressures, with an opinion

    The cluster already lists four numbers. This one says something the cluster cannot: whether selecting Dynamic on tyres that are still cold is a good idea.

How it works

From the bus to the screen, one way only.

Four hops, and the arrow never turns round. Everything that could be decided on the microcontroller is decided there, which is what leaves the head unit free to do nothing but draw.

  1. The extended CAN bus

    Tapped behind the gateway, where a curated subset of the car's own traffic is already broadcast. No module is asked for anything.

  2. ESP32, listening only

    An ESP32 with a CAN transceiver, its controller in listen-only mode: it cannot acknowledge a frame, let alone send one. That is a hardware mode, not a setting.

  3. Decoded before it leaves

    Scaling, filtering and unit conversion all happen on the microcontroller. What goes over the air is degrees, km/h and newton metres - the app has never seen a CAN frame.

  4. Its own WiFi, into the head unit

    The ESP32 is the access point. An Ionic and Angular app on a 12.3" Android head unit reads the binary stream straight out of a typed array and renders it.

Fifty times a second, but only where it counts

Engine speed and wheel speeds change inside a tenth of a second; oil temperature physically cannot. One universal rate would either starve the shift light or spend the head unit's whole budget re-parsing a number that has not moved. So the stream is split, and the rule for a new field is that it joins the slow tier until someone can argue it out of there.

The three tiers of the telemetry stream
TierRateFormatCarries
Fast50 HzBinary, fixed layoutrpm, road speed, four wheel speeds, gear, pedal, brake, torque, steering
Slow1 HzJSON, key-valueoil, water, charge air, ambient, rev limit, battery
EventImmediateJSONlink loss, faults, diagnostic state
  • 50Hzthe fast tier, every 20 ms
  • 26bulbsshift light, both edges inwards
  • 0frames sentthe bus is only ever listened to
  • 0.01km/hthe resolution the runs are timed at

The rules

What it refuses to do.

Every one of these has cost something - a signal left unimplemented, a panel left blank, a number labelled as a guess. They are the reason the display can be trusted in the one situation that matters, which is the one where it says something is wrong.

It never speaks to the car

The controller runs in listen-only mode. Nothing on the bus can be disturbed by a display that is physically unable to transmit, and that is the point: this is a car that gets driven.

Unknown is not zero

A value that has not arrived reads as unavailable, never as 0. A gauge that shows zero oil pressure because a frame was dropped is worse than one showing nothing.

Only confirmed signals ship

Every CAN identifier, offset and scale factor has one source of truth, and a field stays out of the firmware until it has been proven against the car. A plausible number is not a measured one.

An estimate says so

The g-g diagram is reconstructed from wheel speeds, and it degrades exactly where it matters most - at the limit of grip, under wheelspin. The display presents it as an estimate, because it is one.

It does not repeat the cluster

Speed, rpm and gear are already in front of the driver. The centre of this screen is for what is not, and the shift light is the only deliberate duplicate.

It is one car's display

The thresholds, the shift points and the torque scale were measured on this engine with this map. Nothing here is a product, and none of it would be right on your car without measuring it again.

Where it has got to

Still being driven into shape.

This is a build log, not a product. There is nothing to download: the thresholds, the shift points and the torque scale were all measured on one engine with one map, and on another car they would be wrong in ways that are hard to see. What it is good for is showing how the thing was reasoned about.

  • FirmwareStreaming from the car, both tiers, listen-only. Bench and vehicle builds.
  • DisplayTwo pages, the full assist stack, driven on real captures and in the car.
  • SignalsReverse-engineered one drive at a time. Some values still come from the diagnostic port rather than the broadcast bus.
  • CalibrationThresholds that came from another car are being replaced with ones this engine has actually produced.

Something similar, in your car?

Reading a car's bus, adding a screen that belongs there, or coding a module so the car treats it as its own - that is the same work as this, done deliberately rather than as a hobby. Write a couple of sentences about it and you will get an honest answer.

btech.birmingham@gmail.com

Work that changes how a vehicle behaves is carried out on the owner's instruction, and only where it is legal for the road it is used on.