On-board diagnostics (OBD-II)

OBD (On-Board Diagnostics) is a standardized way of accessing vehicle data. It was first required in 1988 in California, and has since been revised several times. OBD-II was introduced in 1996 and became mandatory in the United States; Europe introduced similar EOBD requirements later.

OBD-I was introduced as a means to ensure emission control systems would function during the whole life of the vehicle. The goal was to read out emissions-related data from the vehicle every year during an annual inspection. However, because the reporting of emissions-specific data was not standardized, it wasn't very successful. It also didn't help that every manufacturer used its own connector and own set of DTCs.

To solve OBD-I's problems, OBD-II was introduced. In the new standard, the connector, electrical signaling, and DTCs were specified.

Europe followed in 2001 when they introduced EOBD for petrol cars, and in 2004 for diesel cars. EOBD is essentially the European implementation of the same emissions-focused diagnostics concept.

History

  • 1988 — OBD-I is required in California.
  • 1996 — OBD-II is made mandatory in the United States for cars and light trucks.
  • 2001 — EOBD is made mandatory in Europe for petrol cars.
  • 2004 — EOBD is made mandatory in Europe for diesel cars.
  • 2005 — OBD-II is made mandatory in the United States for medium duty vehicles.
  • 2008 — OBD-II must use CAN in the United States.
  • 2010 — OBD-II is made mandatory in the United States for heavy duty vehicles.

SAE J1962 Connector

The connector used for OBD-II is the SAE J1962 diagnostic link connector. There is a Type A connector for 12 V vehicles, and a Type B for 24 V vehicles. The connector has 16 pins, some of which are part of the standard while others can be used at the manufacturer's discretion.

On newer vehicles that expose DoIP on the OBD-II connector, some of the manufacturer-specific pins are used for Ethernet. There are two possible pinouts, Option 1 and Option 2 — by measuring the voltage on pin 8 (the DoIP Activation Line), the tester can determine which pinout is in use.

OBD-II — J1962 Type A

12+3456H7K891011121314L15L16
FunctionMnemonicPinsDescription
SAE J1850 BusJ18502, 10Two-wire J1850 PWM/VPW bus.
Chassis GroundCGND4Chassis ground reference.
Signal GroundSGND5Signal ground reference.
CAN BusCAN6, 14ISO 15765 CAN bus. Mandatory in the US since 2008.
ISO 9141 K/L-LineK/L7, 15K-Line and L-Line for ISO 9141-2 / KWP2000.
Battery (+)+VB16+12 V (Type A) or +24 V (Type B), permanent.
Manufacturer-specific1, 3, 8, 9, 11, 12, 13OEM-defined functions. Not part of the standard.

Signal Protocols

The OBD-II standard allows for implementing one or more of the following signaling protocols. Since 2008, CAN is mandatory in the United States.

  • SAE J1850 PWM — Two-wire PWM-based signal running at 41.6 kbit/s. Most commonly used in older Ford vehicles.
  • SAE J1850 VPW — One-wire VPW-based signal. After every bit the level on the bus changes. The length of the high pulse determines the value of the bit: 64 µs for a logical 1, 128 µs for a logical 0. Due to the variable length of each bit there is no fixed data rate. Most commonly used in older General Motors vehicles.
  • ISO 9141 (K-Line) — UART-based signal running at 10.4 kbit/s. Used in EU, Chrysler, and Asian cars from 2000 until 2004.
  • ISO 14230 (KWP2000) — Same physical layer as ISO 9141. Common after 2003.
  • ISO 15765 (CAN) — Mandatory in the United States since 2008. Uses ISO-TP as a transport layer.

Service IDs (SIDs)

The protocol itself was standardized as SAE J1979 (also published as ISO 15031-5) and defines a set of services that must be supported. These "services" used to be called "modes". A successful response starts with the SID ORed with 0x40 (e.g. SID 0x01 becomes a response of 0x41). On error, the reply starts with 0x7F, followed by the SID and a UDS-style negative response code.

The PID, OBDMID, TID and INFOTYPE values referenced below are catalogued in the SAE J1979-DA digital annex.

0x01 — Show current data

Reads a live emissions-related parameter. The request carries a 1-byte PID; the response echoes the PID followed by 1 to 4 data bytes (named A, B, C, D). PID 0x00 is special: it reports a bitmap of which PIDs in the range 0x010x20 the ECU supports. The same trick (PID 0x20, 0x40, 0x60, …) walks the rest of the table.

0x01 — Request current powertrain diagnostic data

TesterECU
01PID
FieldMnemonicValueDescription
Service IDSIDRQ01Request current powertrain diagnostic data SID.
parameterIdentifierPIDPID1-byte PID (see SAE J1979-DA).
ECUTester
41PID1–4 bytes (Data A–D)
FieldMnemonicValueDescription
Response SIDSIDPR41Request SID ORed with 0x40.
parameterIdentifierPIDPIDEchoed PID.
dataRecordDREC1–4 bytes (Data A–D)PID-specific value. Format and length depend on the PID.

0x02 — Show freeze frame data

Reads emissions data captured at the moment a DTC was stored. Same shape as Service 0x01, but with an extra "frame number" byte. Frame 0x00 is the freeze frame associated with the DTC that triggered storage.

0x02 — Request powertrain freeze frame data

TesterECU
02PIDframe
FieldMnemonicValueDescription
Service IDSIDRQ02Request powertrain freeze frame data SID.
parameterIdentifierPIDPID1-byte PID.
frameNumberFRNOframeFreeze frame number. 0x00 = freeze frame stored when the DTC was set.
ECUTester
42PIDframe1–4 bytes (Data A–D)
FieldMnemonicValueDescription
Response SIDSIDPR42Request SID ORed with 0x40.
parameterIdentifierPIDPIDEchoed PID.
frameNumberFRNOframeEchoed frame number.
dataRecordDREC1–4 bytes (Data A–D)PID-specific value captured at freeze-frame time.

0x03 — Show stored diagnostic trouble codes

Reads "confirmed" emission-related DTCs. The request has no payload. On CAN (ISO 15765-4) the response starts with a count byte; on the older protocols the count comes from PID 0x01 instead. Each DTC takes two bytes; see the DTC encoding section below.

0x03 — Request stored emission-related DTCs

TesterECU
03
FieldMnemonicValueDescription
Service IDSIDRQ03Request stored DTCs SID. No payload.
ECUTester
43count2 bytes per DTC
FieldMnemonicValueDescription
Response SIDSIDPR43Request SID ORed with 0x40.
numberOfDTCs#OFDTCcountNumber of DTCs that follow (CAN only). 0x00 = no DTCs stored.
dtcRecordDTC2 bytes per DTCTwo bytes per DTC, repeated for each stored code.

0x04 — Clear diagnostic trouble codes and stored values

Clears confirmed and pending DTCs, freeze frame data, on-board monitor results, MIL state, distance/time-with-MIL counters, etc. Permanent DTCs (Service 0x0A) are not affected. The request and response have no payload. Most ECUs require ignition ON with the engine off and otherwise return NRC 0x22 conditionsNotCorrect.

0x04 — Clear/reset emission-related diagnostic information

TesterECU
04
FieldMnemonicValueDescription
Service IDSIDRQ04Clear/reset SID. No payload.
ECUTester
44
FieldMnemonicValueDescription
Response SIDSIDPR44Request SID ORed with 0x40. The clear was accepted.

0x05 — Oxygen sensor monitoring test results (non-CAN only)

Reports oxygen sensor test results addressed by a Test ID. Defined for ISO 9141-2, ISO 14230-4 and SAE J1850 only — on CAN this functionality is folded into Service 0x06.

0x05 — Request oxygen sensor monitoring test results

TesterECU
05TIDO2 sensor
FieldMnemonicValueDescription
Service IDSIDRQ05Request oxygen sensor monitoring test results SID.
testIdentifierTIDTIDTest ID identifying the oxygen sensor parameter.
o2SensorIdO2SO2 sensorOxygen sensor identifier (bank/sensor). Optional depending on Test ID.
ECUTester
45TIDO2 sensortest value bytes
FieldMnemonicValueDescription
Response SIDSIDPR45Request SID ORed with 0x40.
testIdentifierTIDTIDEchoed Test ID.
o2SensorIdO2SO2 sensorEchoed sensor identifier.
dataRecordDRECtest value bytesTest result, format defined per Test ID.

0x06 — On-board monitoring test results

Reports test values, minimum and maximum limits for on-board monitors (catalyst, EVAP, misfire, oxygen sensors on CAN, …). Each monitor is addressed by an OBDMID; each monitor can have multiple Test IDs. The Unit and Scaling ID tells the tester how to interpret the 16-bit value and limits.

0x06 — Request on-board monitoring test results

TesterECU
06OBDMID
FieldMnemonicValueDescription
Service IDSIDRQ06Request on-board monitoring test results SID.
monitorIdentifierOBDMIDOBDMIDOn-Board Diagnostic Monitor ID.
ECUTester
46OBDMIDTIDUAS ID2 bytes2 bytes2 bytes
FieldMnemonicValueDescription
Response SIDSIDPR46Request SID ORed with 0x40.
monitorIdentifierOBDMIDOBDMIDEchoed OBDMID.
testIdentifierTIDTIDStandardized or manufacturer-defined Test ID.
unitAndScalingIdUASIDUAS IDEncodes the unit and scaling for the test value and limits.
testValueTV2 bytesTest result, 16-bit big-endian.
minTestLimitMINTL2 bytesMinimum test limit, 16-bit big-endian.
maxTestLimitMAXTL2 bytesMaximum test limit, 16-bit big-endian.

0x07 — Pending DTCs

Reads "pending" DTCs detected during the current or last completed driving cycle, before the MIL is illuminated. Useful to verify a repair after clearing DTCs without waiting for several driving cycles. Same wire format as Service 0x03.

0x07 — Request pending DTCs from current/last driving cycle

TesterECU
07
FieldMnemonicValueDescription
Service IDSIDRQ07Request pending DTCs SID. No payload.
ECUTester
47count2 bytes per DTC
FieldMnemonicValueDescription
Response SIDSIDPR47Request SID ORed with 0x40.
numberOfDTCs#OFDTCcountNumber of DTCs that follow (CAN only).
dtcRecordDTC2 bytes per DTCTwo bytes per DTC, same format as Service 0x03.

0x08 — Control on-board component / system

Drives an on-board component or test routine — for example, commanding an EVAP leak test. Each TID has its own request/response data layout, defined in SAE J1979-DA.

0x08 — Request control of on-board system, test or component

TesterECU
08TID0–5 bytes (Data A–E)
FieldMnemonicValueDescription
Service IDSIDRQ08Request control SID.
testIdentifierTIDTIDTest ID identifying the system, test or component.
dataRecordDREC0–5 bytes (Data A–E)Optional Test ID-specific parameters (e.g. ON/OFF, duration).
ECUTester
48TID0–5 bytes (Data A–E)
FieldMnemonicValueDescription
Response SIDSIDPR48Request SID ORed with 0x40.
testIdentifierTIDTIDEchoed Test ID.
dataRecordDREC0–5 bytes (Data A–E)Test ID-specific status / test result.

0x09 — Request vehicle information

Reads identification data such as the VIN, Calibration ID(s), Calibration Verification Number(s) and the in-use performance tracking (IPT) counters. The INFOTYPE selects what to read; the response includes a "number of data items" byte so the tester knows how many records (e.g. multiple Calibration IDs) follow.

0x09 — Request vehicle information

TesterECU
09INFOTYPE
FieldMnemonicValueDescription
Service IDSIDRQ09Request vehicle information SID.
infoTypeINFTYPINFOTYPE1-byte INFOTYPE (e.g. 0x02 = VIN, 0x04 = Calibration ID, 0x06 = CVN).
ECUTester
49INFOTYPEcountINFOTYPE-specific bytes
FieldMnemonicValueDescription
Response SIDSIDPR49Request SID ORed with 0x40.
infoTypeINFTYPINFOTYPEEchoed INFOTYPE.
numberOfDataItemsNODIcountNumber of data items in the response.
dataRecordDRECINFOTYPE-specific bytesFor INFOTYPE 0x02 (VIN), 17 ASCII bytes. Other INFOTYPEs use their own format.

0x0A — Permanent DTCs

Reads DTCs with "permanent" status — confirmed DTCs that the ECU stores in non-volatile memory. They cannot be cleared by Service 0x04 or by disconnecting the battery; only the ECU's own monitor can clear them, after observing the fault is no longer present. This is intended to stop drivers from passing emissions inspections by clearing codes right before the test. Same wire format as Service 0x03.

0x0A — Request DTCs with permanent status

TesterECU
0A
FieldMnemonicValueDescription
Service IDSIDRQ0ARequest permanent DTCs SID. No payload.
ECUTester
4Acount2 bytes per DTC
FieldMnemonicValueDescription
Response SIDSIDPR4ARequest SID ORed with 0x40.
numberOfDTCs#OFDTCcountNumber of permanent DTCs that follow.
dtcRecordDTC2 bytes per DTCTwo bytes per DTC, same format as Service 0x03.

Parameter IDs (PIDs)

PIDs identify the values readable through Service 0x01 (current data) and 0x02 (freeze frame data). The full list lives in the SAE J1979-DA digital annex; a small selection is shown below.

Each PID has a fixed response format. The data bytes are conventionally named A, B, C, D and combined per PID into a physical value via a fixed formula. Most PIDs return 1 to 4 data bytes; a few return larger records.

PIDs 0x00, 0x20, 0x40, … are markers: each returns a 4-byte bitmap of which PIDs in the next 32-PID block the ECU supports. Walking these markers lets a tester enumerate every supported PID without prior knowledge of the ECU.

PIDBytesDescriptionMinMaxUnitFormula
0x004PIDs supported (0x01 – 0x20)Bit encoded
0x041Calculated Engine Load0100%A / 2.55
0x051Engine coolant temperature-40215°CA − 40
0x0C2Engine speed016383.75rpm(256·A + B) / 4
0x0D1Vehicle speed0255km/hA
0x204PIDs supported (0x21 – 0x40)Bit encoded
0xA64Odometer0429496729.5km(A·2²⁴ + B·2¹⁶ + C·2⁸ + D) / 10

Diagnostic Trouble Codes (DTCs)

Another important part of the OBD-II standard are the Diagnostic Trouble Codes (DTCs). These are a standardized way of reporting issues with a vehicle. Each DTC is encoded as a two-byte value. A list of stored DTCs is requested using service 0x03 without any payload.

The first two bits of the 2-byte value indicate the type of DTC: 0b00 for P(owertrain), 0b01 for C(hassis), 0b10 for B(ody), and 0b11 for U (Network). The next two bits encode the first digit of the DTC. The final three sets of 4 bits encode the second, third, and fourth digit of the DTC. For example, the value 0xC158 decodes to the DTC U0158. The DTC U0158 means "Lost Communication With Head Up Display".

CAN Arbitration IDs

For OBD-II over CAN, the Arbitration ID 0x7DF is used, which acts as a broadcast address. ECUs both listen to the broadcast address and to their own address in the range 0x7E0 through 0x7E7. They respond on their own address + 8, so 0x7E8 through 0x7EF.

Some cars use 29-bit Arbitration IDs for OBD-II instead of the standard 11-bit Arbitration ID. The 29-bit broadcast address is 0x18DB33F1, and the ECU addresses are in the range 0x18DAF1xx, responding on 0x18DAxxF1 (swap last two bytes).