Skip to content

NikUlj/STM32_Digital_Dashboard_DEMO

Repository files navigation

STM32H750B-DK Digital Dashboard for Racing Sims

Real-time telemetry dashboard for PC racing simulators running on an STM32H750B-DK dev board.

SimHub on the PC streams telemetry over a high-speed serial link (UART/DMA). The MCU renders a multi-screen TouchGFX UI (swipe between views) and drives external inputs/outputs: WS2812B shift lights + a set of physical buttons exposed to the PC as a USB HID gamepad.

Device running

Demo video (hosted on my collaborator's channel): https://www.youtube.com/watch?v=GPmhzNYBqZ4

Demo video thumbnail

What It Shows

  • TouchGFX UI with 4 swipeable views: main dashboard, radar, pedal positions + history graph, live-generated track map
  • Telemetry pipeline: SimHub -> fixed-length packet -> UART (921600 baud) -> DMA -> FreeRTOS queues -> TouchGFX (MVP)
  • WS2812B LED strip driven via SPI + DMA (shift lights, flags, TC/ABS status)
  • 6 physical buttons read via GPIO + debounce and sent as an 8-bit USB Custom HID report (gamepad buttons)

Quick Specs

  • Display: 4.3" touchscreen, 480x272 (STM32H750B-DK)
  • UI refresh: VSync (60 Hz target)
  • Telemetry link: UART (USART3) @ 921600 baud using DMA
  • Telemetry packet: fixed-length DataPacket (585 bytes) framed with "S" ... "E"
  • LEDs: WS2812B strip (16 LEDs) driven via SPI + DMA
  • Buttons: 6 tactile buttons exposed to the PC as a USB gamepad (Custom HID)
  • Enclosure: custom Fusion 360 design, 3D printed at home (button caps are from an external model)

Design Highlights

  • DMA-first data path: UART RX via DMA into a fixed-size packet struct, with RTOS queues sized to 1 element so the UI always renders the latest telemetry
  • Framed packet protocol: packets are framed with start/end markers ("S" ... "E"); a low-priority resync task restarts DMA when the stream is misaligned
  • UI architecture: TouchGFX MVP (Model reads from queue, Presenter updates only the active page to reduce invalidations)
  • Live track map: builds a 1000-sample lookup table during driving (0.1% lap steps), interpolates missed samples, then scales/rotates and renders a dynamic bitmap
  • WS2812B without bit-banging: encodes WS2812B timing into SPI bit patterns and transmits via SPI + DMA (shift lights + flag/TC/ABS indicators)
  • Plug-and-play buttons: GPIO scan + debounce, exposed as an 8-bit USB Custom HID report (appears as a gamepad)

Architecture

flowchart LR
  subgraph PC[PC]
    SIM[Racing simulator]
    SH[SimHub<br/>Custom Serial Device]
    HID[USB HID<br/>Gamepad]
    SIM --> SH
  end

  subgraph MCU[STM32H750B-DK]
    UART[USART3 RX<br/>DMA]
    ISR[HAL_UART_RxCpltCallback]
    DQ[(dataQueue<br/>DataPacket)]
    LQ[(LEDQueue<br/>DataPacketLED)]
    SQ[(dataSyncQueue<br/>startChar)]

    DT[dataTask<br/>DMA restart + resync]
    MODEL[TouchGFX Model::tick]
    PRES[Presenter<br/>screen logic]
    VIEW[View<br/>UI widgets]

    LEDT[LEDTask<br/>WS2812 effects]
    SPI[SPI2 TX<br/>DMA]
    LEDS[WS2812B<br/>LED strip]

    BT[buttonTask<br/>GPIO scan + debounce]
    USB[USB Device<br/>Custom HID]

    UART --> ISR
    ISR --> DQ
    ISR --> LQ
    ISR --> SQ
    SQ --> DT
    DT --> UART

    DQ --> MODEL --> PRES --> VIEW
    LQ --> LEDT --> SPI --> LEDS
    BT --> USB
  end

  SH -->|UART @ 921600| UART
  USB -->|HID reports| HID
Loading

Notes:

  • Telemetry is a fixed-size, NUL-padded packet framed with start/end markers so the MCU can DMA directly into a C struct.
  • The track map is generated during driving from position samples and scaled/rotated to fit the 480x272 display.
Telemetry receive + resync sequence (Mermaid)
sequenceDiagram
  participant SH as SimHub
  participant UART as USART3 + DMA
  participant ISR as RX complete IRQ
  participant DT as dataTask (resync)
  participant DQ as dataQueue
  participant TG as TouchGFX Model::tick
  participant UI as Presenter/View

  SH->>UART: Send fixed-size packet ("S" ... "E")
  UART-->>ISR: DMA complete
  ISR->>DQ: Overwrite latest DataPacket
  ISR->>DT: Post startChar to dataSyncQueue

  DT->>DT: Wait (timeout) for startChar
  alt startChar != 'S' or timeout
    DT->>UART: Abort + restart DMA RX (resync)
  end

  TG->>DQ: osMessageQueueGet()
  TG->>UI: updateData(DataPacket)
Loading

Screens

  • Dashboard: speed/gear/RPM + tyres/fuel/laps/electronics
  • Radar: left/right proximity indicators based on angle + distance
  • Pedals: throttle/brake/clutch bars + scrolling history graph
  • Track map: live-generated track outline + driver positions
Dashboard Radar
Dashboard screen Radar screen
Pedals + graphs Track map
Pedals/graph screen Track map screen
Hardware (LEDs, buttons, HID)
WS2812B shift lights Buttons
WS2812B LED strip close-up Button cluster close-up

USB HID gamepad proof (Windows)

Device enumerated as a USB HID gamepad

Mechanical design (Fusion 360)

Custom enclosure parts were modeled in Fusion 360 and 3D printed at home. Button caps were also 3D printed from an external model.

LED top piece Side button holder Mounting bracket
Fusion 360 - LED holder Fusion 360 - button holder Fusion 360 - mounting bracket

Code Tour (Custom Logic)

  • Core/Inc/main.h - DataPacket / DataPacketLED (telemetry packet layout)
  • Core/Src/main.c - FreeRTOS tasks, UART DMA receive + resync, button scanning + HID reports, LED queueing
  • TouchGFX/gui/src/model/Model.cpp - queue -> presenter handoff
  • TouchGFX/gui/src/screen1_screen/Screen1Presenter.cpp - per-screen updates, radar math, track-map orchestration
  • STM32CubeIDE/Application/User/TrackMapClass.cpp - track sampling, scaling/rotation, dynamic bitmap generation
  • STM32CubeIDE/Application/User/WS2812_SPI.c - WS2812B encoding over SPI + DMA and LED effects
  • USB_DEVICE/App/usbd_custom_hid_if.c - custom HID report descriptor

Deep Dives (Selected)

Telemetry packet format
  • Packet is a fixed-length C struct (DataPacket, 585 bytes) framed with start/end markers ("S" ... "E") so DMA can write directly into the receive buffer.
  • Most numeric fields are transmitted as fixed-length, NUL-padded strings (converted on-device using atoi/strtof).
  • RX path uses DMA + a 1-element message queue so the UI renders the newest sample and never lags behind.

Related code:

  • Core/Inc/main.h
  • Core/Src/main.c
Live track-map generation
  • Samples car position while driving and builds a 1000-entry lookup table (0.1% lap steps).
  • Interpolates missed samples to keep the outline continuous.
  • Scales/centers the map to screen bounds and conditionally rotates for vertical tracks, then draws a dynamic bitmap used as the map background.

Related code:

  • STM32CubeIDE/Application/User/TrackMapClass.cpp
  • TouchGFX/gui/src/screen1_screen/Screen1Presenter.cpp
WS2812B shift lights via SPI + DMA
  • Encodes WS2812B timing into SPI bit patterns (no CPU bit-banging) and transmits the whole frame via SPI DMA.
  • Outer LEDs indicate flags/TC/ABS; center LEDs act as shift lights with color transitions and a checkered-flag animation.

Related code:

  • STM32CubeIDE/Application/User/WS2812_SPI.c
USB HID buttons
  • 6 GPIO buttons are sampled periodically, debounced, and packed into an 8-bit report.
  • Device enumerates as a Custom HID gamepad, so buttons can be mapped in the sim without custom drivers.

Related code:

  • Core/Src/main.c
  • USB_DEVICE/App/usbd_custom_hid_if.c

Tech Stack

  • MCU/Board: STM32H750B-DK (Cortex-M7)
  • RTOS: FreeRTOS (CMSIS-RTOS v2)
  • UI: TouchGFX (MVP pattern)
  • Peripherals: LTDC/DMA2D, QSPI + SDRAM, UART (DMA), SPI (DMA), USB Device (Custom HID)

Repo Notes

  • This repo contains the STM32 firmware + TouchGFX project.
  • The PC-side SimHub Custom Serial Device formatter script and Fusion 360 source files are not included in this snapshot (only screenshots).

License / Reuse

This repository is published as a portfolio/demo artifact.

  • Third-party components are under their respective licenses (see Drivers/**/LICENSE*, Middlewares/**/LICENSE*, and individual file headers).
  • Unless a file header states otherwise, project-specific application code is provided for viewing/evaluation only (all rights reserved) and is not licensed for reuse or redistribution. If you want to reuse parts of it, please contact the authors.

Credit

Co-developed with my brother using a pair-programming workflow (I was usually the "driver" writing firmware while we jointly designed/debugged/tested the system).

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors