obd2-simulator

Public

@filipraic

Download board files

Files for version 1. Pick what you came for.

Share obd2-simulator

Check access before sharing the link.

Who can open this board

Anyone can open this board. No sign-in is required.

This link opens the latest version. Copying it does not grant additional access.

Loading 3D model… large boards can take a moment.

README

OBD-II Simulator

Open-source OBD-II simulator board that answers a diagnostic tool over CAN exactly as a vehicle ECU does. The repository has three parts:

  • the protocol core (include/, src/, tests/) - portable, host-testable protocol and simulation layers with no external dependencies, described below,
  • the firmware (firmware/) - PlatformIO project for the device itself (FreeRTOS tasks, MCP2515 SPI driver, TFT_eSPI user interface, 16 MB SPI NOR flash storage with USB-C MSC / USB-A stick transfer), which compiles the core unchanged and plugs into it through the small set of extern platform hooks listed below. See firmware/README.md,
  • the board (hardware/) - the KiCad project, gerbers, bill of materials and the scripts that generate the board, at revision v0.7 (130 x 115 mm, two-layer FR4, ESP32-S3-WROOM-1). See hardware/README.md.

The simulator answers a diagnostic tool over CAN and, like a real vehicle, powers it from pin 16 of the J1962 connector. The protocol core described below is what runs inside the "Microcontroller" block, and everything around it is documented in hardware/README.md, which walks through the same schematics one design decision at a time.

Everything in the repository is in English. The project also keeps a set of Croatian working documents, which live outside it.

The v0.7 board has been fabricated and assembled in one unit. A commercial ELM327 adapter connects to it, reads all 21 parameters and the fault codes, and draws its own 12 V from pin 16 while doing so.

The website

The project has a landing page at https://filipraic.github.io/obd2-simulator/, which is the short version of everything below: what the device does, what it is built from and where to get the files. Two things on it are worth opening even if the page itself is skipped, because neither can be shown in a README:

PageWhat it is
The user interface demothe screens firmware/src/ui/screens/ draws on the display, redrawn in a browser and walked with the same encoder and joystick controls the device has, so the interface can be tried before anything is built
The interactive board viewthe v0.7 board drawn in the browser, with the tracks, the ground pour, the vias, the pads and the components as five layers that switch on and off, and a tooltip on every part. Generated from obd2-simulator.kicad_pcb by hardware/kicad/scripts/generate_pcb_html.py

Where to read what

The wiki is written for someone using or rebuilding the device. The files in this repository are the record of how it was built and why. The wiki is in English, which is the language of the project. A Croatian translation of the same pages exists but is not published yet, and if it goes up it will take an -HR suffix, leaving the page names below unchanged.

QuestionWiki pageIn this repository
What is this and what can it doHomethis file
How do I build oneBuilding the devicehardware/README.md, and hardware/gerber/README.md before ordering
How do I compile and flash itFirmwarefirmware/README.md, and firmware/tools/README.md when the ordinary upload path is unavailable
How do I drive itUsagescenarios/README.md for the JSON format
How do I contributeContributingthe conventions below
How is the board generated-hardware/kicad/scripts/README.md

Two internal documents govern changes to this project, and neither is published here: docs/MAPA-POVEZANIH-DATOTEKA.md is an "if you change X, check Y" table, because the same fact is written down in up to six places, and docs/combined/DNEVNIK-IZMJENA.md is the chronological record of every decision. Both are in Croatian and are working notes rather than product documentation, so docs/ is deliberately left out of the repository.

Modules

FilePurpose
include/obd2_pids.hMode/PID constants per SAE J1979 / ISO 15031-5
include/sensor_table.h21 simulated parameters with ranges and noise
src/pid_encoder.cppValue → raw bytes codec + supported-PID bitmasks
include/dtc_bank.hDTC bank (pending/confirmed, MIL, freeze frame)
src/iso_tp.cppISO 15765-2 transmit path (SF, FF/FC/CF)
src/can_handler.cppRequest dispatcher, modes 0x01-0x09
src/simulator_core.cppSimulation profiles (Manual / Idle / Drive)
tests/test_simulator.cppHost-side unit tests

Implemented services: 0x01 (current data, 21 PIDs), 0x02 (freeze frame), 0x03/0x07 (stored/pending DTCs), 0x04 (clear DTCs), 0x09 (VIN). Unsupported services receive the negative response 7F <mode> 11. Requests are accepted on 0x7DF (functional) and 0x7E0 (physical), while responses are sent on 0x7E8. Frames are padded to 8 bytes with 0x55 per ISO 15765-4.

Platform hooks (implement on target, stubbed in tests)

uint32_t millis();                                // ms since boot
void     can_send_frame(const CanFrame& frame);   // MCP2515 transmit
bool     iso_tp_wait_flow_control(FlowControl&);  // wait for FC frame
void     iso_tp_delay_us(uint32_t us);            // STmin pacing

Building and running the tests

cmake -B build
cmake --build build
ctest --test-dir build --output-on-failure

The same tests also run through PlatformIO (pio test -e native inside firmware/). Firmware build: pio run -e custom-board (the dedicated ESP32-S3 board, also used on the breadboard adapter during development).

Regenerating the board

The board is generated rather than drawn: there is no .kicad_sch, and the .kicad_pcb is an output. Two entry points, and picking the wrong one costs work:

# a part, a net or the placement changed - rebuilds and re-routes from nothing
powershell -ExecutionPolicy Bypass -File hardware\kicad\scripts\route_board.ps1

# the board file is already right, only the derived files are stale
powershell -ExecutionPolicy Bypass -File hardware\kicad\scripts\regen_outputs.ps1

route_board.ps1 ends by recomputing all 103 reference designator positions and so discards the hand-tuned silkscreen. If no copper moved, run only regen_outputs.ps1. Every step of the chain, what it writes and where, is in hardware/kicad/scripts/README.md.

Comments

No comments yet. Be the first to ask about this board.

Ask about this board

Sign in to BoardRepo

New here? Signing in creates your account; there is no separate sign-up.