justin 58305cded4
Build binaries / linux-amd64 (push) Failing after 31s
Build binaries / linux-arm64 (push) Failing after 59s
Build binaries / macos (push) Successful in 1m9s
Build binaries / windows (push) Failing after 3m0s
CI: build cross-platform binaries + tagged release
.gitea/workflows/release.yml builds the PySide6 GUI with PyInstaller on each
self-hosted runner and, on a v* tag, publishes a Gitea Release with every
platform binary attached:
- windows-latest  -> OBDash-windows.exe   (onefile, --windowed)
- self-hosted-mac -> OBDash-macos.zip     (.app bundle, ditto-zipped)
- docker (linux)  -> OBDash-linux-x86_64  (onefile + patchelf/GL libs)
- arm64 (Pi)      -> OBDash-linux-aarch64
Uses softprops/action-gh-release with the auto GITEA_TOKEN; manual dispatch
build-only (no release).

profiles/ is bundled via --add-data; obdcore.profile.profiles_dir() now
resolves sys._MEIPASS when frozen so the binary finds its vehicle profiles.

Validated locally on Linux: PyInstaller onefile builds (88MB), launches
offscreen, and loads bundled profiles (6 found). Build artifacts gitignored.
Added .claude/gitea-ship.json.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016yT89n4zR4qbrySoSiEyZs
2026-06-30 16:04:56 -04:00
2026-06-30 15:37:47 -04:00

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 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 https://www.python.org/downloads/ (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.
  • Linuxch341 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 12 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 Gauge view

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 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 12 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.

S
Description
OBDash — open-source, vehicle-agnostic OBD-II scanner (Python/Qt). Live multi-axis graphs, car-style gauges, DTC read/clear, JSON vehicle profiles.
Readme MIT 1.8 MiB
v0.1.0 Latest
2026-06-30 16:53:36 -04:00
Languages
Python 99.7%
Batchfile 0.3%