Ryan Malloy 8ba53630c0 Add OBD-II K-line support (ISO 9141/14230) with scanner example
New protocol handler alongside BMW I/K-Bus:
- KLineObd2: 5-baud slow init, fast init (TiniPulse), request/response
  with half-duplex echo clearing, PID convenience wrapper
- Obd2Pids.h: ~20 common PIDs with SAE J1979 decode helpers
- obd2_scanner.cpp: polls RPM, speed, coolant, throttle, voltage

Build config changes:
- config.h: KLINE_* defaults (10400/8N1/MOD256/no idle detect)
- platformio.ini: build_src_filter separates sketches, new
  [env:obd2-scanner] environment with KLINE_TX_INVERT=0
2026-02-13 05:46:07 -07:00

142 lines
5.4 KiB
C++

#pragma once
// OBD-II PID constants and decode helpers (SAE J1979)
// Covers the most common Mode 01 (current data) PIDs.
#include <Arduino.h>
namespace obd2 {
// --- Diagnostic modes ---
constexpr uint8_t MODE_CURRENT = 0x01; // current data
constexpr uint8_t MODE_FREEZE = 0x02; // freeze frame
constexpr uint8_t MODE_DTC = 0x03; // stored DTCs
constexpr uint8_t MODE_CLEAR_DTC = 0x04; // clear DTCs
constexpr uint8_t MODE_O2_TEST = 0x05; // O2 sensor monitoring
constexpr uint8_t MODE_TEST_RESULTS = 0x06; // on-board monitoring test results
constexpr uint8_t MODE_PENDING_DTC = 0x07; // pending DTCs
constexpr uint8_t MODE_CONTROL = 0x08; // control of on-board system
constexpr uint8_t MODE_VEHICLE_INFO = 0x09; // vehicle information (VIN, etc.)
constexpr uint8_t MODE_PERMANENT_DTC = 0x0A; // permanent DTCs
// --- Mode 01 PIDs ---
constexpr uint8_t PID_SUPPORTED_01_20 = 0x00; // supported PIDs [01-20]
constexpr uint8_t PID_DTC_STATUS = 0x01; // monitor status since DTCs cleared
constexpr uint8_t PID_FUEL_STATUS = 0x03; // fuel system status
constexpr uint8_t PID_ENGINE_LOAD = 0x04; // calculated engine load (%)
constexpr uint8_t PID_COOLANT_TEMP = 0x05; // engine coolant temperature (C)
constexpr uint8_t PID_SHORT_FUEL_TRIM_1 = 0x06; // short term fuel trim bank 1 (%)
constexpr uint8_t PID_LONG_FUEL_TRIM_1 = 0x07; // long term fuel trim bank 1 (%)
constexpr uint8_t PID_INTAKE_PRESSURE = 0x0B; // intake manifold pressure (kPa)
constexpr uint8_t PID_RPM = 0x0C; // engine RPM
constexpr uint8_t PID_SPEED = 0x0D; // vehicle speed (km/h)
constexpr uint8_t PID_TIMING_ADVANCE = 0x0E; // timing advance (degrees BTDC)
constexpr uint8_t PID_INTAKE_TEMP = 0x0F; // intake air temperature (C)
constexpr uint8_t PID_MAF_RATE = 0x10; // MAF air flow rate (g/s)
constexpr uint8_t PID_THROTTLE = 0x11; // throttle position (%)
constexpr uint8_t PID_OBD_STANDARD = 0x1C; // OBD standards compliance
constexpr uint8_t PID_RUN_TIME = 0x1F; // run time since engine start (s)
constexpr uint8_t PID_SUPPORTED_21_40 = 0x20; // supported PIDs [21-40]
constexpr uint8_t PID_FUEL_LEVEL = 0x2F; // fuel tank level input (%)
constexpr uint8_t PID_BARO_PRESSURE = 0x33; // barometric pressure (kPa)
constexpr uint8_t PID_SUPPORTED_41_60 = 0x40; // supported PIDs [41-60]
constexpr uint8_t PID_CONTROL_VOLTAGE = 0x42; // control module voltage (V)
constexpr uint8_t PID_FUEL_TYPE = 0x51; // fuel type
constexpr uint8_t PID_OIL_TEMP = 0x5C; // engine oil temperature (C)
constexpr uint8_t PID_FUEL_RATE = 0x5E; // engine fuel rate (L/h)
// --- K-line protocol constants ---
constexpr uint8_t SYNC_BYTE = 0x55; // ECU sync response
constexpr uint8_t DEFAULT_TARGET = 0x33; // ISO 9141 default ECU address
constexpr uint8_t TESTER_ADDR = 0xF1; // external test equipment
constexpr uint8_t FUNC_ADDR = 0x33; // functional addressing
// --- ISO 14230 (KWP2000) header formats ---
constexpr uint8_t KWP_FMT_NO_ADDR = 0x00; // no address info
constexpr uint8_t KWP_FMT_PHYS_ADDR = 0x80; // physical addressing
constexpr uint8_t KWP_FMT_FUNC_ADDR = 0xC0; // functional addressing
// --- Decode helpers ---
// All formulas from SAE J1979 / ISO 15031-5
// PID 0x04: Calculated engine load (0-100%)
inline float decodeEngineLoad(uint8_t a) {
return a * (100.0f / 255.0f);
}
// PID 0x05: Engine coolant temperature (-40 to 215 C)
inline int16_t decodeCoolantTemp(uint8_t a) {
return (int16_t)a - 40;
}
// PID 0x06/0x07: Short/long term fuel trim (-100 to 99.2%)
inline float decodeFuelTrim(uint8_t a) {
return (a / 1.28f) - 100.0f;
}
// PID 0x0B: Intake manifold pressure (0-255 kPa)
inline uint8_t decodeIntakePressure(uint8_t a) {
return a;
}
// PID 0x0C: Engine RPM (0-16383.75 RPM) — 2 bytes
inline float decodeRpm(uint8_t a, uint8_t b) {
return ((a * 256.0f) + b) / 4.0f;
}
// PID 0x0D: Vehicle speed (0-255 km/h)
inline uint8_t decodeSpeed(uint8_t a) {
return a;
}
// PID 0x0E: Timing advance (-64 to 63.5 degrees BTDC)
inline float decodeTimingAdvance(uint8_t a) {
return (a / 2.0f) - 64.0f;
}
// PID 0x0F: Intake air temperature (-40 to 215 C)
inline int16_t decodeIntakeTemp(uint8_t a) {
return (int16_t)a - 40;
}
// PID 0x10: MAF air flow rate (0-655.35 g/s) — 2 bytes
inline float decodeMafRate(uint8_t a, uint8_t b) {
return ((a * 256.0f) + b) / 100.0f;
}
// PID 0x11: Throttle position (0-100%)
inline float decodeThrottle(uint8_t a) {
return a * (100.0f / 255.0f);
}
// PID 0x1F: Run time since engine start (0-65535 s) — 2 bytes
inline uint16_t decodeRunTime(uint8_t a, uint8_t b) {
return (uint16_t)(a * 256) + b;
}
// PID 0x2F: Fuel tank level input (0-100%)
inline float decodeFuelLevel(uint8_t a) {
return a * (100.0f / 255.0f);
}
// PID 0x33: Barometric pressure (0-255 kPa)
inline uint8_t decodeBaroPressure(uint8_t a) {
return a;
}
// PID 0x42: Control module voltage (0-65.535 V) — 2 bytes
inline float decodeControlVoltage(uint8_t a, uint8_t b) {
return ((a * 256.0f) + b) / 1000.0f;
}
// PID 0x5C: Engine oil temperature (-40 to 210 C)
inline int16_t decodeOilTemp(uint8_t a) {
return (int16_t)a - 40;
}
// PID 0x5E: Engine fuel rate (0-3212.75 L/h) — 2 bytes
inline float decodeFuelRate(uint8_t a, uint8_t b) {
return ((a * 256.0f) + b) / 20.0f;
}
} // namespace obd2