# OBDash Minimal **ELM327 OBD-II code reader** with a **Ford 6.0L Power Stroke no-start triage**, built for a cheap CH340 ELM327 USB adapter. Works on any OBD-II vehicle for generic codes/PIDs; the triage notes are 6.0-specific. Created as a stopgap while [forscan.org](https://forscan.org) was offline — it covers reading/clearing codes and the basics, not Ford-enhanced diesel PIDs (see Scope below). ## Features - Read **stored** (mode 03), **pending** (mode 07), **permanent** (mode 0A) DTCs - Decode P/C/B/U codes, with common **6.0 codes** described and **no-start suspects flagged** - **Clear** codes (mode 04) — guarded behind `--clear` + a typed `CLEAR` confirmation, then re-reads to show any code that returns immediately (active fault) - Key **live values** (coolant, IAT, MAP, module voltage, RPM, load, throttle) + battery voltage - 6.0 Power Stroke **no-start triage** checklist (FICM, ICP, cam/crank, batteries, fuel) ## Setup Runs on **Windows, macOS, and Linux** (Python + pyserial). The only per-OS difference is the CH340 USB driver: - **Windows** — install WCH `CH341SER`; adapter shows as `USB-SERIAL CH340 (COMx)` in Device Manager → Ports. Install Python from (tick **Add Python to PATH**), or just double-click `RUN_OBD.bat`. - **macOS** — install WCH `CH34xVCPDriver` (Mac App Store or wch.cn). Port appears as `/dev/cu.wchusbserial*`. `pip install pyserial`. - **Linux** — `ch341` driver is built into the kernel (no install). Port is `/dev/ttyUSB0`; add yourself to the `dialout` group for access (`sudo usermod -aG dialout $USER`, then re-login). `pip install pyserial`. The tool auto-detects the port on all three; pass it explicitly if needed (`COM5`, `/dev/cu.usbserial-1420`, `/dev/ttyUSB0`). ## Usage ``` python obd_reader.py # auto-detect the COM port python obd_reader.py COM5 # force a port python obd_reader.py COM5 9600 # force port + baud (default 38400) python obd_reader.py COM5 --clear # read, then optionally clear (asks to confirm) python obd_reader.py COM5 -v # verbose: show raw ELM327 traffic ``` ### Crank monitor (dedicated no-start view) — `--crank` The one to use for a crank-but-won't-start. Big ICP readout with a wide bar (the `|` marks the 500-psi firing threshold), a **rolling ASCII trace** of the ICP build-up, **peak-hold**, FICM/battery/RPM with sag tracking, and a pass/fail verdict. Start it, then crank. ``` python obd_reader.py COM5 --crank # crank monitor python obd_reader.py COM5 --crank --dash-log crank.csv # + record a CSV ``` ``` ICP [#################################|##----] 539.8 psi PEAK 540 psi FIRING PRESSURE REACHED FICM Main 47.5V (min 47.5) [DOC] Batt 12.6V (min 10.7) RPM 200 ICP trace (psi vs time, last 16 samples) 600 | 500 |----------------------------------------------#### <- firing line | ###### | ######## +-------------------------------------------------- ``` **Read it:** ICP should climb **past 500 psi within 1–2 s** of cranking (`FIRING PRESSURE REACHED`, green). If it **stalls below 500** (red, trace flat under the line), that's the high-pressure oil bleed-off — STC fitting / oil-rail O-rings. On exit it prints the peak and a verdict. `q` quits, `r` resets. ## Graphical app (preview) A cross-platform desktop GUI (PySide6 + pyqtgraph). Vehicle-agnostic — all PIDs, scaling, DTCs, and presets come from the JSON profiles in `profiles/`. ``` pip install -r requirements-gui.txt python run_gui.py # tick "Mock" + Connect to explore with no adapter ``` Features so far: - **PID browser** (left) grouped by system, live values, confidence badges - **Graph view** with **true multi-axis** overlay — one Y scale per unit (psi/V/rpm/…), or a Normalize (% of range) mode - **Gauge view** — arc gauges with peak-hold, one per signal - **Table view** — value + min/max + confidence - **Diagnostics** — read/clear DTCs (guarded), no-start codes flagged - **Profile menu** — switch/import/edit vehicles; **File menu** — record/replay/export captures ![Multi-axis graph](docs/gui-p2-multiaxis.png) ![Gauge view](docs/gui-p2-gauges.png) The whole app runs against simulated data (`MockLink`), so it can be developed on any machine and only needs the vehicle for real captures. See [ARCHITECTURE.md](ARCHITECTURE.md) for the roadmap. --- ### Live dashboard (real-time gauges) Updates in place as you crank or run the engine — color-coded, with live min/max so a crank's **peak ICP** is captured. No extra dependencies (ANSI; works on any Windows 10+ terminal). `q` quits, `r` resets min/max. ``` python obd_reader.py COM5 --dash # vitals preset (ICP, FICM, IPR, batt, RPM, temps) python obd_reader.py COM5 --dash crank # cranking preset: ICP / FICM main / batt / RPM (fastest) python obd_reader.py COM5 --dash full # every PID python obd_reader.py COM5 --dash crank --dash-log crank.csv # + write a CSV while you watch ``` **No-start use:** run `--dash crank`, then crank. A healthy 6.0 builds **~500+ psi ICP within 1–2 s**; if ICP stalls below 500 (red), that confirms the high-pressure oil bleed-off. FICM Main should hold ~48V. The `--dash-log` CSV is your streaming log — paste it back for analysis. Note: the FICM PIDs (`09xx`) are `[DOC]` (not yet confirmed on this truck); if they read `--`, they auto-drop after a few frames so the refresh rate stays up. Or just double-click **`RUN_OBD.bat`** on Windows (auto-installs `pyserial`). On the truck: plug into the OBD port under the dash, key to **RUN** (engine off is fine for codes), then run the tool. ## Scope / honesty A generic ELM327 reads standard OBD-II only: codes, generic PIDs, port voltage. It does **not** read Ford-enhanced diesel PIDs (ICP, FICM main/sync voltage, IPR%) — those need FORScan. For FICM/ICP numbers, measure at the FICM with a meter, or use FORScan when it's available. Default baud is 38400 (measured on the CH340 adapter); try 9600 if you get garbage. ## Requirements `pyserial` (`pip install pyserial`). Tested against a QinHeng CH340 ELM327 v1.5 clone.