Skip to content

Building the device

FilipRaic edited this page Aug 31, 2026 · 1 revision

Building the device

This page holds everything you need to build the device yourself: the parts list, the wiring and the assembly.

1. The device and the development build

There is one device specification: a dedicated printed circuit board with the ESP32-S3-WROOM-1 module (v0.7). The development build is not a second device, it is the same module soldered onto a cheap castellated-edge breakout adapter and plugged into a breadboard, so the software can be developed without soldering SMD parts and without buying a separate development kit:

Criterion Breadboard (development) Dedicated PCB (the device)
Cost 25.00-33.00 EUR, no printed board EUR 40 to 60 for one unit, depending on the supplier (includes the board at 5.41 EUR when five are ordered). Shipping and the enclosure are not counted
Soldering Only the module onto the adapter 16 SMD footprints, the rest THT, the whole assembly
Dimensions Larger, modules and jumper wires 130 × 115 mm
Tool power (12 V) None, the tool uses its own supply Yes, pin 16 of the J1962 connector
Purpose Software development and testing Final device, a small series is possible

Note: the microcontroller is the same in both builds, so the source code compiles without a single change, and the wiring differences are covered by a configuration file. The power section with USB-C PD negotiation, the 12 V supply for the diagnostic tool and the USB features (PC link and USB stick) exist only on the dedicated board.

2. Bill of materials (BOM)

Development build (module on an adapter)

Component Description Qty ≈ EUR/pc Suppliers
ESP32-S3-WROOM-1 Module, 8 MB flash (the same one as on the board) 1 3.50 Mouser, DigiKey, LCSC
Breakout adapter For a castellated-edge module, to a 2.54 mm pitch 1 1.00 AliExpress, LCSC
MCP2515 CAN module Ready-made breakout (MCP2515 + TJA1050), SPI 1 2.00 AliExpress, Amazon, eBay
Waveshare 18366, TFT 2.4" ILI9341, 240 × 320 pixels (used in landscape as 320 × 240), SPI, no touch - TME symbol WSH-18366; 8-pin header (no MISO line) 1 9.50 TME, Waveshare, Amazon
Tactile button 6 × 6 mm + an external 10 kΩ pull-up per button 3 + 4 0.10 / 0.05 TME, LCSC
SKRHABE010 Alps 5-way switch (4 directions + click), SMD on a small carrier board, with a 2 × 6.8 kΩ + 2 × 10 kΩ ladder 1 1.29 TME
Incremental encoder BI Technologies EN11-HSB1AQ20, 20 pulses per revolution, with a push button 1 5.49 TME
PESD1CAN CAN bus ESD protection (SOT-23), next to the J1962 connector 1 0.34 TME (PESD1CAN.215)
J1962F connector OBD-II female, MINITOOLS SEP-A-OBD-D2 1 3.98 TME (A-OBD-D)
Resistor 120 Ω CAN termination, 1/4 W 2 0.05 TME, LCSC
Capacitor 100 nF Decoupling next to the CAN module and the MCU 5 0.04 TME, LCSC
Protoboard + Dupont wires For assembling the modules 1 set 4.00 AliExpress, Conrad
Enclosure Hammond or 3D printed 1 5.00 TME, Conrad

Dedicated board (summary)

On top of the CAN/UI/OBD parts listed above, the dedicated build uses: the ESP32-S3-WROOM-1 module (8 MB flash), discrete MCP2515-I/SO + SN65HVD230DR chips with an 8 MHz crystal, the power section USB-C → CH224K (PD sink controller, requests 12 V) → TPS562201 (3.3 V step-down converter), together with the resettable fuse F1 and the TVS diode D2 through which 12 V reaches pin 16 of the connector to power the diagnostic tool, the external NOR flash S25FL128L (16 MB, internal scenario storage with a FAT filesystem) and the USB subsystem: the USB-A socket J4 for a USB stick, the analogue mux TS3USB221 (U9) that switches the single ESP32-S3 USB OTG controller between the USB-C and the USB-A port, and the current limited switch SY6280 (U10) that powers the stick with 5 V from a second step-down converter TPS562201 (U11), because after the PD contract VBUS carries 12 V. For programming there are the service buttons SW4 (BOOT) and SW5 (RESET), the pull-down resistor R15 that keeps the USB mux on the USB-C side during reset (so the ROM bootloader is reachable over USB-C) and the UART header J6 for the serial monitor. The complete BOM with prices is in /hardware/bom/bom-pcb.csv in the repository.

3. Wiring (pin assignment)

The final pin assignment (ESP32-S3-WROOM-1 module, identical in the development and in the final build). All SPI peripherals share the MOSI/MISO/SCK lines and each one has its own CS line.

Signal GPIO Peripheral Note
MOSI GPIO11 all SPI peripherals shared line
MISO GPIO13 MCP2515 and S25FL128L the display (Waveshare) does not use MISO
SCK GPIO12 all SPI peripherals shared line, 40 MHz
CS-CAN GPIO10 MCP2515
INT-CAN GPIO9 MCP2515 interrupt 10 kΩ pull-up, must be a dedicated pin
CS-TFT GPIO14 ILI9341
DC/RS GPIO21 ILI9341 data/command
RST-TFT GPIO47 ILI9341 reset a free output pin
CS-FLASH GPIO15 S25FL128L
USB-SEL GPIO16 USB mux U9 (TS3USB221) dedicated board only
USB-HOST-EN GPIO17 power switch U10 (SY6280) dedicated board only
USB D- / D+ GPIO19 / GPIO20 fixed OTG pins, USB-C J1 / USB-A J4 through U9 dedicated board only
ENC-A GPIO1 encoder ENC1, channel A digital input, internal pull-up
ENC-B GPIO38 encoder ENC1, channel B digital input, internal pull-up
ENC-SW GPIO39 encoder ENC1 push button digital input, active low
JOY-X GPIO2 switch SW6, X axis (ADC1_CH1) three levels through the R26/R28 ladder
JOY-Y GPIO4 switch SW6, Y axis (ADC1_CH3) three levels through the R27/R29 ladder
JOY-SW GPIO5 switch SW6, centre click external 10 kΩ pull-up
SW1 CONFIRM GPIO6 confirm button external 10 kΩ pull-up
SW2 CLEAR GPIO7 clear button external 10 kΩ pull-up
SW3 RETURN GPIO8 return button external 10 kΩ pull-up
BOOT GPIO0 service button SW4 strapping pin, 10 kΩ pull-up (R14)
EN (RESET) - (module EN pin) service button SW5 10 kΩ pull-up (R13) and a 1 µF capacitor (C26)
TX0 / RX0 GPIO43 / GPIO44 UART0, header J6 serial monitor, 115200 baud

⚠️ Learned the hard way: the CAN controller interrupt pin (INT-CAN, GPIO9) has to be a dedicated input pin with a pull-up. Sharing it with other signals causes sporadic loss of CAN interrupts. In earlier revisions that fault was caused by the touch controller, removed in v0.4.

⚠️ SPI on a breadboard: with Dupont wires the bus is not stable at 40 MHz. Shorten the leads and drop the clock to 27 MHz (a setting in the firmware configuration file). On the dedicated board, with traces shorter than 30 mm, the bus runs stably at 40 MHz.

The CAN side

The chain is: MCP2515 (controller) → transceiver (TJA1050 on the module, or SN65HVD230 on the board) → PESD1CAN ESD protection → J1962F connector. The 120 Ω termination resistor between CAN-H and CAN-L is mounted right next to the connector, since the simulator and the diagnostic tool are the two end points of the bus.

4. Manufacturing the dedicated board

  1. Download the ready-made package hardware/gerber/obd2-simulator-v07-for-fabrication.zip (a two-layer board, 130 × 115 mm, nine production layers, no auxiliary ones). The same folder holds the individual layers and a README with the fabrication rules.

  2. Order the fabrication. JLCPCB and PCBWay are suitable (five pieces cost 29.40 USD for this project, that is about 27.00 EUR, 7-10 days delivery), as is the European Aisler (more expensive, faster delivery). Before ordering, check the hole spacing: the smallest is 0.450 mm between different nets, while JLCPCB asks for 0.50 mm in the standard process. This comes from the USB-C connector footprint itself and cannot be avoided without replacing that part. The hole diameter is not a problem, because the smallest hole on the board is 0.30 mm, which is inside the standard process. Until 11.08.2026. there were twelve 0.20 mm thermal vias under module U6, which JLCPCB charged as an extra option, and they have been enlarged.

  3. Paste the text below into the notes field. The board sits right at the process limit in three places and that is deliberate. The danger is not that the fabricator cannot make it, but that their automatic manufacturability check will "fix" those items. The JLCPCB field takes at most 200 characters, this text has 196 and goes in as a single line:

    Do NOT auto-adjust the design. It is intentionally at process limits: hole-to-hole 0.40mm, copper clearance 0.15mm, mask expansion 0 (USB-C mask openings may merge). Fabricate exactly as supplied.

    Everything else, meaning the copper ring, the slots, the non-plated holes and the silkscreen, does not go into the field. You only answer if the review raises the question. Those figures are in hardware/kicad/PRE-FABRICATION-CHECKLIST.md.

  4. Assembly in four steps, in this order, because the board is empty and accessible only at the beginning:

    1. SMD parts - U1, U2, U4, U5, U7, U9, U10, U11, D1, D2, D3, F1 and the SW6 stick, soldered with hot air or an iron. D4 and D5 (USB ESD protection) carry the DNP flag and may be skipped on the first assembly,
    2. The module ESP32-S3-WROOM-1 (U6),
    3. THT passives - all resistors, capacitors and inductors. The electrolytics are polarised, and R38, R39 and R40 stand vertically,
    4. Connectors and interface - J1, J2, J4, J5, J6, encoder ENC1 and the buttons SW1 through SW5.
  5. The J1962F and USB-C connectors are mounted on the top edge of the board so that they come out through the enclosure openings, and the USB-A socket is on the bottom edge.

The board carries eight test points (THT pads 2.0 × 2.0 mm with a 1.0 mm hole) on the 3.3 V, GND, CAN-H, CAN-L, MOSI, MISO, SCK and USB VBUS signals, so measuring is possible without taking the device apart.

5. First power-up (smoke test)

  1. Before soldering the module, check with a multimeter that there is no short between 3.3 V and GND.
  2. Connect a USB-C charger that supports the 12 V PD profile (20 W or more). The charger has to advertise that profile on its label, because the standard leaves it optional. Without it the device runs on 9 V or 5 V and resets periodically. The diagnostic tool is fed from the same voltage through pin 16.
  3. Measure 3.3 V at the power test point.
  4. Upload the firmware over the USB-C port (see Firmware). If the upload does not start on its own, hold BOOT (SW4) and briefly press RESET (SW5). The main menu should appear on the screen. It pays to upload and check the firmware before the connectors are soldered, while the module is still freely reachable.
  5. Connect an ELM327 diagnostic adapter and send the request 0x7DF [02 01 0C]. In the manual profile the simulator returns exactly 0x7E8 [04 41 0C 0C A9], while in the idle profile the value noises around 800 rpm, so the last two bytes differ from one request to the next.

If something does not work, check in this order: the pull-up resistors on the buttons and on the switch centre click, the 120 Ω termination, and the correctly connected encoder channels (GPIO1, GPIO38, GPIO39) and the analogue inputs of the switch axes (GPIO2, GPIO4).

OBD-II Simulator


ESP32-S3 · MCP2515 · SAE J1979 · ISO 15031-5

Clone this wiki locally