Skip to content

4. Wheel Emulator

Spb2005 edited this page Feb 16, 2026 · 4 revisions

Overview

The wheel emulator replaces the original STM32-based wheel PCB and emulates the T248 communication protocol using a Raspberry Pi Pico (RP2040). Other 3.3 V microcontrollers may be used, but voltage compatibility must be ensured to avoid damaging the wheelbase.

Its primary purpose is to allow fully custom-built steering wheels to operate with a stock T248 wheelbase.

The development process was intentionally iterative, allowing features to be reverse-engineered and validated step by step:

  • V1.x – incremental versions for testing individual protocol features
  • V2.0 – the first fully functional, stable wheel emulator

Earlier in the project, a separate USB-only custom wheel implementation was created.


Development Versions (V1.x)

V1.0 – Minimal Emulator

Implements:

  • Startup sequence
  • Periodic keep-alive messages
  • Button state messages

This version prevents the wheelbase from continuously generating phantom DPAD-Up inputs when no wheel is connected.

Hardware notes:

  • UART RX/TX must be connected to the wheelbase
  • Wheelbase 3.3 V is connected to GPIO 11 as an enable signal
    (external pull-down resistor required)
  • The Pico must be powered before the wheelbase
  • The Pico must be connected to a separate USB port for power

V1.1 – Button Control via Serial Console

Adds interactive button control via the USB serial console.

Commands:

  • '1'–'10', '13', '22', '23' → normal buttons
  • 'dr', 'du', 'dl', 'dd' → DPAD directions
  • 'elu', 'eld', 'eru', 'erd' → encoder directions
    (example: elu = encoder left up)
  • 'display' → display button
  • 'mode' → mode button

⚠️ Warning:
Using the Display and Mode buttons can modify wheel settings without visual feedback. Use with caution.

At this stage, buttons were toggled. This caused encoder-related inputs (eru, erd) to appear as periodic pulses in Windows after some time.

V1.2 – Improved Button Transmission

Introduces:

  • void sendButtons(bool full) function

Behavior:

  • full = true → sends both B0 and B1 frames
  • full = false → sends only B0

Additionally, the B0 frame is transmitted immediately after a serial command.

V1.3 – UART State Machine & Encoder Decoding

Implements:

  • UART receive state machine to parse multiple frame types
  • Buttons are now momentary presses (100 ms) instead of toggles
  • Screen data is forwarded to the serial console for debugging
  • Encoder data decoding based on selected bits from the F3 frame

V1.4 – Hardware Integration Improvements

Changes:

  • Switched from uart1 (Serial2) to uart0 (Serial1) to match an existing USB steering wheel design
  • Wheelbase reset line is now used to control Pico startup

Reset signal inversion:

  • Wheelbase RESET is active high
  • Pico RUN pin is active low

Implemented using a BC548B NPN transistor:

  • Collector → Pico RUN
  • Emitter → GND
  • Base → wheelbase RESET via 10 kΩ resistor

Additionally:

  • Implemented responses to screen data frames
    (no observable effect on wheelbase behavior)

V1.5 – Encoder Hardware & OLED Display

Adds:

  • Physical rotary encoder as encoder input
  • 32×128 OLED display to show current encoder layer

Encoder layers renamed to:

  • TC
  • ABS
  • BB
  • ECU

(The Display EXP encoder position is not used.)

Required libraries:

V1.6 – Startup Acknowledgment Check

Adds:

  • Validation of the wheelbase acknowledgment after startup
  • If not received, the Pico reboots

(Note: likely redundant, as the wheelbase usually requires a reboot as well.)

V1.7 – UART Receive Timeout

Implements:

  • Timeout-based reset of the UART receive state machine
  • Prevents lock-ups caused by incomplete or corrupted frames

V1.8 – Full Button Set

Adds support for:

  • Buttons 1–10, 13, 22, 23
  • Full DPAD support

Details:

  • Buttons 1 and 2 use interrupts (preferred for shift paddles)
  • I²C pins changed to GPIO 8 and 9

V2.0 – Stable Wheel Emulator

Finalized version with:

  • Shortened interrupt service routines
  • Fixed multiple potential race conditions and edge cases
  • Added preprocessor flag DEBUG
    • Allows all debug output and serial commands to be disabled

This version is considered the first working emulator and is suitable for use with a custom-built steering wheel.

Required libraries:

And the arduino-pico core from earlephilhower

Steering_Wheel_USB (Legacy)

USB-only custom steering wheel implementation.

Characteristics:

  • Based on V1.8 logic
  • Enumerates as a USB gamepad using the Joystick library

Known limitations:

  • Long interrupt service routines
  • Not as optimized as V2.0

Despite these drawbacks, it worked reliably for multiple month.

Schematic for V2.0 / V1.8 and Legacy USB Wheel

⚠️ Warning: Never connect the Pico to USB while it is electrically connected to the wheelbase. VSYS may exceed 3.3 V and damage the electronics. ⚠️

Needed Components:

  • Raspberry Pi Pico or Pico 2
  • SSD1306 32x128 I2C OLED display
  • Rotary encoder breakout board
  • NPN BJT Transistor eg. BC548 or similar
  • Buttons
  • for debounce circuit 10 kΩ pull-up + 100 nF capacitor
  • Some Resistors for Transistor, Uart TX and Pull-up

Notes:

  • Every button should have an debouncing circuit, because there is no software debouncing (exept the Encoder Button).
  • The button mappings can be changed in the code. These button mapping show my implementation for my wheel.
  • The not connected pin in the wheelbase connector is the PA14 pin, which is probably only used during firmware update of the original wheel.
  • The pullup resistors for the encoder are already on most encoder breakout boards.

DIY Wheel Schematic PDF Version

Read next

For protocol details see:

For hardware mapping see: