Receive C-ITS (V2X) data with an ESP32-C5 and provide stand-alone use cases (like remaining signal phase time). Migrated to Codeberg (when they actually work)! https://codeberg.org/c-its/esp32-c_its-companion
This repository has been archived on 2026-07-31. You can view files and clone it, but you cannot make any changes to its state, such as pushing and creating new issues, pull requests or comments.
  • Rust 99.3%
  • Shell 0.7%
Find a file
2026-07-31 13:20:21 +02:00
.cargo setup rust project using esp-generate 2026-04-25 16:47:41 +02:00
docs proto/PositionState: Add time for geonetworking 2026-07-27 12:41:51 +02:00
hardware Hardware: Add PCB layout 2026-07-31 13:20:13 +02:00
src gnss: Add support for ublox GNSS 2026-07-31 13:20:21 +02:00
.clippy.toml radio: Enable TX of non-QoS frames 2026-07-19 17:16:06 +02:00
.gitignore Hardware: Add PCB layout 2026-07-31 13:20:13 +02:00
build.rs build: Add "io" module for BLE/ UART messages 2026-07-22 15:39:33 +02:00
Cargo.lock gnss: Add support for ublox GNSS 2026-07-31 13:20:21 +02:00
Cargo.toml gnss: Add support for ublox GNSS 2026-07-31 13:20:21 +02:00
feat-permut.sh gnss: Add support for ublox GNSS 2026-07-31 13:20:21 +02:00
Readme.md gnss: Add support for ublox GNSS 2026-07-31 13:20:21 +02:00
run-smartphone.sh Add scripts to run/ flash the supported feature-sets 2026-07-31 12:13:54 +02:00
run-standalone-cam.sh Add scripts to run/ flash the supported feature-sets 2026-07-31 12:13:54 +02:00
run-standalone-no_cam.sh Add scripts to run/ flash the supported feature-sets 2026-07-31 12:13:54 +02:00
rust-toolchain.toml setup rust project using esp-generate 2026-04-25 16:47:41 +02:00
rustfmt.toml chore: Add rustfmt config 2026-05-11 22:22:39 +02:00

ESP32-C5 C-ITS Companion/ Visualizer

Displays different C-ITS receive-only use cases for cheap.

Hardware Requirements

The code is currently tailored to:

  • Seeed XIAO ESP32-C5 (8MB PSRAM)
  • U-Blox M10Q GNSS (connected on GPIO12 (RX), GPIO11 (TX), and GPIO25 (reset))
    or Seeed XIAO L67K (connected on GPIO12 (RX), GPIO11 (TX), GPIO1 (wakeup) and GPIO25 (reset))
    only available with gnss_ubx or gnss_l67k feature (which is included in spat feature)
  • Some ST7789 172*320px screen (connected on GPIO8 (SCL/ SCK), GPIO10 (SDA/ MOSI), GPIO7 (reset), GPIO23 (DC), GPIO24 (CS), TODO GPIO0 (BL))
    only available with screen feature (which is included in spat feature)

Features

GNSS

Enable u-blox or L67K GNSS module and in main application logic/ state.

SPAT

Takes the current position and heading from the GNSS receiver and displays the signal phases of the upcoming intersection. The upcoming intersection is selected when the own position is "inside" some ingress approach of the intersection. The display will show the current phase and remaining time for all signal groups of the bike-able lanes in the approach.

DENM

TODO: Not implemented yet!

Shall "publish" the most relevant information of a DENMs via BLE

CAM

Just prints a line for each received CAM.

CAM-TX

Generates and transmits a CAM when a GNSS update was received. Depends on the gnss feature.

Note: In germany, using the 5875 to 5915 MHz frequency band is only permitted for C-ITS use cases which implement transmit power reduction measures with at least 30 dB reduction range (or equivalent measures) and have a maximum EIRP of 33 dBm. This is based on EU regulation 2014/53/EU, so it applies to other EU countries in similar ways.
The relevant harmonized standard is ETSI EN 302 571 which mandates (excerpt of most relevant points):

  • a maximum power spectral density of 23 dBm/Mhz EIRP
  • transmit power control (TCP) in a range from 3 dBm up to the maximum output power of the equipment
    • used for CEN DSRC and HDR DSRC interference mitigation by implementing measures from ETSI TS 102 792
      • Mode A or B: Output power less than 10 dBm EIRP and less than -65 or -45 dBm/MHz EIRP in CEN DSRC band -> needs to be measured
      • Mode C: Maximum transmission time of less than 1 ms and at least a few 100 ms between transmission (realistically) -> can't be ensured with big messages
      • Mode D: "any" realistically possible transmission time, but at least 500 ms between transmissions for ~5 ITS stations/ 1000ms for 10 ITS stations -> safe to assume when we only send CAMs at 1 Hz
      • But modes C and D also need to:
        • use protected zone information from CAM messages
        • use a protected zone database, e.g. from www.asecap-pzdb.com
    • used for dynamic congestion control (DCC)
      • mandatory mechanism described in ETSI EN 302 571, chapter 4.2.10

This is not implemented in this application! So legally, you're not allowed to send with this.

UART

Enable UART I/O protocol according to docs/uart-protocol.md.

Usage

Toolchain Installation

Install the toolchain, targe and tools like this:

rustup toolchain install nightly --component rust-src
rustup target add riscv32imac-unknown-none-elf

# cargo install esp-generate --locked
# cargo install esp-config --features=tui --locked
cargo install espflash --locked

(Project was setup using esp-generate with the options --chip esp32c5 -o esp32c5-wroom-1-psram -o alloc -o log -o unstable-hal -o wifi -o esp-backtrace -o embassy.)

To use the proper rustfmt features, enable the nightly toolchain:

rustup component add --toolchain nightly rustfmt

Build and Flash

In default configuration only signal phases (SPAT) data is displayed for the upcoming intersection. Additional features are available through feature flags:

  • esp: Run on ESP (required as feature flag to enable unit tests on host)
  • std: Run on system with std library
  • spat: Enable signal phase (and intersection map) data
  • spat_debug: Enable additional debug information for the SPAT/ GLOSA use case
  • denm: Enable DENMs
  • cam: Enable CAMs
  • cam_tx: Enable CAM generation and transmission (needs time and position source)

Officially supported feature combinations are:

  • esp,spat,gnss_ubx,screen (default features, "standalone")
  • esp,spat,gnss_ubx,screen,cam_tx ("standalone with CAM")
  • esp,spat,gnss_ubx,screen,cam_tx,cam,denm
  • esp,uart,cam,denm ("smartphone companion")

Connect your ESP32-C5 and run:

# default configuration
cargo run --release

# for e.g. also enable DENM feature
cargo run --release -F denm

Run Unit Tests on Host

The unit tests in this project are meant to be run on the host:

cargo test --target host-tuple --bin test --no-default-features -F std,spat