ESP32 CAN Bus Shift Light for the R53

CAN bus RPM to an 8-LED WS2812B bar — a shift light for the price of a track-day lunch

The R53 has a lot of charm, but a track-friendly tach is not part of it. The column pod is small, and mid-corner with your eyes up where they belong, it might as well not exist. Aftermarket shift lights either cost real money or want a dedicated tach signal wired across the dash.

So I built my own: an 8-LED WS2812B bar in a 3D-printed housing on the column shroud, driven by an ESP32 reading RPM straight off the CAN bus. Source is on GitHub: esp32-shift-light-R53-mini.

Reading RPM from the CAN bus

The car already broadcasts RPM constantly — it’s on the CAN bus. An SN65HVD230 transceiver (a $3 breakout) sits between the bus and the ESP32, which picks the engine-speed frames off the bus, extracts RPM, and translates it into light.

Shift light electronics — ESP32 mini and 8-LED WS2812B stick The whole system: one tiny USB-C ESP32, a screw terminal, three wires, and the 8-LED WS2812B stick.

Parts total is a dev board, the CAN transceiver breakout, and a $5 LED stick — a shift light for the price of a track-day lunch.

Reading the bar without reading it

A shift light you have to interpret is a shift light you’ll ignore. The display encodes RPM two ways at once — how many LEDs are lit, and what color they are — and you process both peripherally:

  • Below 3,000 RPM — dark. Cruising the paddock shouldn’t look like a police chase.
  • 3,000–6,000 — solid green, LED pairs filling in as revs climb.
  • 6,000–7,100 — the color fades continuously from green through amber to red. The “get ready” zone.
  • Past 7,100 — the whole bar flashes red at 5 Hz. Unmissable. Shift. Now.

The color math is a linear crossfade through the warning zone:

} else if (rpm <= 7100) {
  // Fade from green to red (6000 to 7100 RPM)
  uint8_t t = map(rpm, 6000, 7100, 0, 255);
  color = CRGB(t, 255 - t, 0);
}

One detail I’m fond of: the bar doesn’t fill left-to-right like a progress bar. The eight LEDs light in symmetric pairs from the ends toward the center — outer pair first, then inward, until the middle pair completes the bar right at the shift point:

if (numPairs >= 1 && (i == 0 || i == 7)) leds[i] = color; // Pair 1: Ends
if (numPairs >= 2 && (i == 1 || i == 6)) leds[i] = color; // Pair 2
if (numPairs >= 3 && (i == 2 || i == 5)) leds[i] = color; // Pair 3
if (numPairs >= 4 && (i == 3 || i == 4)) leds[i] = color; // Pair 4: Center

A bar growing from one side reads as “a number changing.” A bar collapsing toward its own center reads as convergence — the visual finishes exactly when the engine does. Much easier to catch in peripheral vision, which is the only vision you’re sparing it.

Brightness is capped at 75/255 — WS2812Bs at full tilt in a dark car will cook your night vision.

Bench testing without an engine

You don’t want your first test of a shift light to be at 7,000 RPM on a back straight. The firmware (PlatformIO, Arduino framework, FastLED) has a compile-time simulation mode:

//#define SIMULATE_RPM   // Uncomment to test without the car

With it defined, the code ignores the CAN input and sweeps RPM from 1,000 to 8,000 and back on a ten-second cycle — the dark zone, the green fill, the fade, the flash, all on the bench. Comment it back out, reflash, and it’s reading the car again.

Mounting

Shift light installed on the column shroud, under the tach pod 3D-printed housing clipped to the column shroud, directly below the tach pod.

That spot earns its keep: dead-center in the forward sightline, moves with the column so the wheel rim never blocks it, and the housing shrouds the LEDs enough to kill windshield reflections. The flashing red bar and the tach needle end up in the same glance — not that I read the needle anymore.

The housing is up on Cults3D if you want to print your own:

Download: R53 shift light housing on Cults3D

What’s next

  • Configurable shift point — the 7,100 RPM threshold is a #define today; making it adjustable per gear would be a fun upgrade.
  • Ambient dimming — a light sensor to knock the brightness down for night sessions.

For eight LEDs, one board, and an afternoon of firmware, it already does the one thing it needs to do: when the bar goes red and starts flashing, I shift. My eyes never leave the track.