ESP32-S3 Touch OBD2: A Live Round-Display Motorcycle Dashboard on BLE ELM327

TL;DR: ESP32-S3 Touch OBD2 is a free MIT firmware that turns the Waveshare 1.85 inch round touch board into a live ten-page motorcycle dashboard over a BLE ELM327 adapter, with RPM, estimated gear, lean angle, tyre sensors, fault codes and SD card ride logs plus an offline chart website. Needs ESP-IDF 5.5, a Euro 5 era bike that answers standard OBD2, and a bike profile header. Full page tour, install guide, protocol depth and honest limits inside.

What This Project Is

ESP32-S3 OBD2 dashboard is a live motorcycle instrument add-on that runs on the round 1.85 inch touch screen of the Waveshare ESP32-S3-Touch-LCD-1.85B, talks to the bike ECU through a cheap Bluetooth LE ELM327 adapter, and shows what the engine reports across ten swipeable pages with ride logging to microSD.

That is the whole pitch, and the repository delivers it with unusual polish for a version with a single commit. The project lives at https://github.com/Gnzlt/ESP32-S3-Touch-OBD2 by Gnzlt, MIT licensed, with a demo GIF that cycles all ten pages, real framebuffer screenshots, five documentation files, host-side unit tests and a complete field-tested bike profile for a 2022 Honda CB500X next to the generic template. It doesn’t replace the bike instruments or warning lights, the README says so in bold, and it should be mounted where it can’t distract you and never operated while riding.

ESP32-S3 Touch OBD2 dashboard round display showing Ride Engine and Lean pages over BLE ELM327
Ride, Engine and Lean pages on the 360×360 round LCD. Screenshots: Gnzlt ESP32-S3-Touch-OBD2 project, MIT.

The Hardware: Board, Adapter and Cable

Three parts make the system, and each choice is deliberate.

The board is the Waveshare ESP32-S3-Touch-LCD-1.85B, the B version, at https://www.waveshare.com/esp32-s3-touch-lcd-1.85b.htm: a 360×360 ST77916 round LCD with touch, an ESP32-S3R8 with 16 MB flash and 8 MB octal PSRAM, a QMI8658 IMU for lean and G, a PCF85063 real-time clock, a BQ27220 battery gauge, a speaker driven by ES8311 audio, and a microSD slot. Round matters here. A motorcycle cockpit has round clocks, and a round display with an RPM rim gauge looks like it belongs. The IMU, RTC, gauge and card slot aren’t decoration, they are the lean math, the timestamps, the power guard and the logging.

The adapter must be Bluetooth Low Energy ELM327. Field-tested reference is the Vgate iCar Pro BLE and 2S on the 18F0 service layout, with the FFF0 and FFE0 layouts supported too, which covers OBDLink CX, Veepeak, LELink, Konnwei and most BLE clones. Classic Bluetooth SPP and WiFi adapters are explicitly not supported. Note the overlap with phone apps: this is the same adapter family the OpenOBD Android scanner is built around, so one Veepeak style dongle serves both the phone in your pocket and the dashboard on your bars.

The cable is the part car people never think about. Most bikes have no 16-pin car socket. Honda and Kawasaki use a 6-pin plug, Yamaha a 3 or 4-pin, KTM 6-pin, BMW 10-pin, so you need a bike-to-OBD2 adapter cable for your make. Then the Euro 5 question: bikes sold in the EU since Euro 5, 2020 to 2021, must answer standard OBD2 requests, mostly over ISO 15765-4 CAN, which is what this was developed on. The ELM327 also speaks the older K-line protocols, so some earlier bikes work. Many pre-Euro 5 bikes speak only the maker own diagnostics and will never answer. The fastest compatibility test costs nothing: pair the adapter with a phone app like Car Scanner or OBD Fusion, and if it shows live RPM, this dashboard will too. Anything your ECU doesn’t report shows as two dashes, no drama.

Ten Pages of Live Data

Swipe left and right, or use the BOOT button: press for next, double-press for previous, hold for the page long-press action, with a split gauge on the bottom rim showing position. Ride puts RPM around the rim with the red zone, big speed digits, throttle on an inner arc and the estimated gear. Engine shows coolant with cold, normal, warm and hot zones plus a ten-minute sparkline, battery voltage with charging state, and intake air temperature. Tyres draws a motorcycle whose wheels are the gauges, each with pressure, temperature and sensor battery, tap a wheel for alerts, long-press to pair. Performance covers throttle, load, manifold pressure, ignition advance, short-term fuel trim and open or closed loop. Lean and G shows lean angle with left and right maxima plus a G-ball with a trail above 15 km/h. Trip totals distance, engine time, average and max speed, max RPM and coolant, min voltage, with hold to reset. Fuel estimates used fuel and range since the last fill-up with consumption, and the Filled up action records a fill-up that calibrates the model. Status shows adapter, ECU, protocol, replies per second, board battery and temperatures, the SD card and all settings. From Status, Rides lists logged rides with stats, and Diagnostics shows the malfunction light, stored and pending codes with descriptions, readiness monitors and Clear codes, which is refused while the engine runs.

Over everything sit four behaviours. Alerts fire a full-screen pulse with beeps for overheating, charging faults, new fault codes, tyre pressure loss, or the board itself overheating or running flat, tap to dismiss. A connection pill reports searching, connecting, ignition off or connected. A parked screen dims to the bike plus board battery after two minutes without the ECU. A battery saver drops to a dim status-only screen, automatically on low cell or high heat, because an IPS panel saves nothing with black pixels, the saving comes from backlight and skipped rendering.

Gears, Lean and Fuel: Estimated Honestly

Three numbers on this dashboard are computed, not read, and the docs are candid about each. OBD2 has no gear PID, so gear comes from RPM divided by speed against your profile ratios, with a tools/fit_gears.py script that fits the estimate from a logged ride. Lean needs no calibration and works however the board is mounted: it comes from the turn itself, speed times yaw rate over gravity, fused with gyro roll rate, and the board learns which way is up within seconds of riding because a steady turn averages to the bike own vertical. Fuel is estimated from engine load since most bikes report no fuel rate or level, and every fill-up you enter calibrates it. Lean gates below 15 km/h, gyro bias is learned at standstill, jolts over 200 degrees per second are rejected, and maxima must hold a full second so a pothole never becomes the ride record.

The ELM327 Session Under the Hood

The protocol core is plain C with host tests, and docs/how-it-works.md reads like a field manual. One command in flight always, a reply ends at the prompt, stray replies are dropped never misattributed, only ECU-advertised PIDs are polled, and disconnects are treated as normal because key-off kills adapter power. Setup runs the classic init string with adaptive timing, locks the ECU address, and reads the supported-PID bitmaps. ECU-off needs six failed requests plus three silent seconds, so a few NO DATA answers can’t kill a session while RPM still answers. Polling interleaves by urgency: RPM and speed every 50 ms, throttle and load at 150 ms, coolant and intake at one second, fuel status and voltage at two seconds, the rest at thirty, with multi-PID grouping into single CAN frames where the ECU allows. Against a Vgate adapter that is about 30 requests a second with RPM and speed at 16 to 20 Hz, and the live rate sits on the Status page. Fault codes come from Mode 03 and 07 at connect and on change, Mode 09 grabs VIN, calibration IDs and verification numbers once per session into the ride record.

Power and memory get the same care. The BQ27220 gauge drives a green, amber and red battery icon with alerts at 20 and 10 percent, dual heat sensors warn at 80 degrees chip or 50 battery area and go critical at 90 or 58, and a board guard writes a last event, closes the ride, unmounts the card and deep sleeps on empty cell or critical heat, waking every five minutes to recheck. Internal RAM is the 340 KB squeeze every ESP32-S3 BLE project feels: a single 40-row draw band, the LVGL heap moved to PSRAM, measured stack sizes and flash-resident ISRs recover over 100 KB combined, leaving about 150 KB free with BLE scanning while the UI holds 60 fps.

Build It, Profile It, Ride It

Install ESP-IDF 5.5 from the Espressif guide and export it, then clone, build and flash. The board starts in demo mode playing a synthetic five-minute ride geared to your profile, staging an overheat, a fault code and an engine stop each loop, so every page, alert and the clear-codes flow can be tried on the desk with no bike at all.

git clone https://github.com/Gnzlt/ESP32-S3-Touch-OBD2.git
cd ESP32-S3-Touch-OBD2
idf.py build
idf.py -p <port> flash monitor

Then make your bike profile. Copy main/bike/profiles/generic.h to your bike name, fill in rev range, red zone, gear ratios or the K factor from primary, final drive and rear tyre size, displacement, tank size and cold tyre pressures, and select it under OBD2 dashboard in idf.py menuconfig, documented fully in docs/configure-your-bike.md. On the bike, plug in the adapter, ignition on, close any phone app holding the adapter connection, swipe to Status, switch demo mode off, and the board scans, connects and remembers adapter and protocol. A profile pull request for your bike would be welcome upstream.

Logs That Become a Website

With a FAT32 microSD card in, about 5 MB per riding hour, every ride gets a folder: trip.csv at five samples a second, events.csv, ride.json totals and the raw adapter bytes in obd_raw.log. Over USB, pull_logs.py copies the rides and builds a static site with an overview plus zoomable per-ride charts that opens by double-click with no server. The format reference lives in docs/ride-logs.md. Protocol and sensor logic ship with host tests played back from real ELM327 transcripts plus a Python test for the site builder, so the clever math is checkable on a PC without flashing anything.

Tyre Sensors and Other Options

Optional BLE tyre sensors, valve-cap or in-wheel broadcast types, pair from the Tyres page with settings in tpms.cfg on the card, with eight decoded formats and the full list in docs/tyre-sensors.md. Optional extras are a 3.7 V LiPo on the 2-pin connector to keep the clock alive and run off USB, and menuconfig switches for adapter name lock, demo logging, one-time SD format, framebuffer screenshot capture, auto-tour and the LVGL performance overlay.

Against the Alternatives

Item ESP32-S3 Touch OBD2 Phone app (Car Scanner, Torque, OpenOBD) Dedicated bike display (OEM TFT, aftermarket) Bare ELM327 plus laptop terminal
Display Round 360×360 touch, bar mounted Phone screen, mount dependent Integrated or add-on None, text only
Always-on riding view Yes, ten pages, alerts, parked screen Yes with foreground app, battery cost Yes No
Gear, lean, fuel estimates Built in, profile calibrated Partial via plugins and PIDs Some models Manual math
Tyre pressure BLE TPMS on the Tyres page Some apps via add-ons Some OEM systems No
Ride logging and charts SD card plus offline website Trip export in some apps Rare, usually cloud Manual capture
Fault codes Read, describe, clear when stopped Read, describe, clear Dealer tool or app Raw mode commands
Cost Board plus adapter plus cable Adapter only Hundreds and up Adapter plus cable
Openness MIT firmware, ESP-IDF, host tests Proprietary apps, open protocols Closed Open tools
Best for Tinkerers wanting a permanent cockpit Quick checks with hardware on hand Fit and forget riders Protocol debugging

The honest read: a phone app wins for occasional checks and costs only the adapter, and an OEM display wins for zero-effort riders. This project wins for the builder who wants a permanent round cockpit, real logging with charts, and every line of firmware auditable. Pair it with the phone app workflow: verify the bike with the phone first, then commit to the dashboard build.

Why Riders and Hams Should Care

Touring riders get the obvious wins: charging faults caught before a dead battery strands a group, coolant trends on a loaded climb, tyre pressure loss flagged early, fault codes read at a petrol station instead of a dealer. For radio amateurs the overlap is the vehicle itself. SOTA and POTA dashes, EmComm moto volunteers, club ride-outs and rally support all depend on bikes and support vehicles that must get there and back. A dashboard that logs every ride also logs the machine health story across a season, and the same BLE adapter family already serves the phone scanner workflow. The build skills transfer too: ESP-IDF, LVGL, BLE and SD logging are the same stack as countless ham gadgets.

Honest Limits

Scope it plainly. One commit means a young codebase, however polished, with five stars and two forks of community testing so far. Euro 5 era ECUs are the supported world, older bikes are try-and-see. Only BLE adapters, no classic Bluetooth or WiFi. Fuel and gear are estimates with a profile to maintain. The SD card wants FAT32 and the format option erases. The safety line stands: informational display only, mount it out of the distraction path, never operate it while riding. Troubleshooting lives in docs/troubleshooting.md for the rest.

Sources and Further Reading

73 de 9M2PJU

Post Comment