OBD-II & SAE J1979
On-Board Diagnostics II is the standardized language every emissions-related ECU speaks. SAE J1979 (a.k.a. ISO 15031-5) defines the request/response messages, engine RPM, vehicle speed, trouble codes, the VIN, that a generic scan tool can read from any compliant vehicle. On a modern car it rides on CAN, transported by ISO-TP.
ISO-TP Transport
OBD-II is an application layer. The bytes travel inside ISO-TP (ISO 15765-2) frames, the same transport UDS uses. sloppyCAN's ISO-TP/UDS tab handles the framing; OBD-II mode gives you one-click buttons instead of typing raw hex. Short requests (1-3 bytes) fit in a single frame; long responses like the VIN arrive as a multi-frame sequence and are reassembled for you.
The transport mechanics, Single Frame, First Frame, Flow Control, Consecutive Frames, are covered in the ISO-TP Explainer.
Connector & CAN Pins
Every OBD-II car has a 16-pin SAE J1962 connector within reach of the driver's seat. On a CAN bus vehicle (mandatory in the US since 2008) the diagnostic CAN pair lives on:
| Pin | Signal |
|---|---|
| 6 | CAN High (CAN-H) |
| 14 | CAN Low (CAN-L) |
| 16 | Battery + (12 V, unswitched) |
| 4 / 5 | Chassis / signal ground |
The diagnostic CAN runs at 500 kbit/s (sometimes 250 kbit/s) with 11-bit identifiers on most vehicles.
Request/Response Flow
A scan tool broadcasts to the functional address 0x7DF.
Any ECU that can answer replies on its own address in the range
0x7E8-0x7EF. The engine ECU almost always answers first, on
0x7E8.
01 0C - "give me current Mode 01, PID 0C (RPM)"41 0C 1A F8 - response SID 0x41, PID 0C, value bytes
The response SID is the request mode + 0x40 (Mode 01 →
0x41), and it echoes the PID so you know which answer is which.
Physical (point-to-point) addressing also exists: request 0x7E0 →
response 0x7E8. The 29-bit equivalents are
0x18DB33F1 (broadcast) and 0x18DAF1xx (responses).
0x7DF is a broadcast, so several ECUs can answer the same request:
engine on 0x7E8, transmission on 0x7E9, and so on. sloppyCAN groups every
responder under the one request, tagged by ID. If a reply spans multiple frames, the
Flow Control the tester sends back must go to that ECU's physical address
(0x7E0), not the broadcast 0x7DF, otherwise a real ECU ignores it.
Modes
OBD-II groups functions into modes (also called services):
| Mode | Meaning | Request |
|---|---|---|
| 01 | Current data (live PIDs) | 01 <pid> |
| 02 | Freeze-frame data (snapshot at fault) | 02 <pid> <frame#> |
| 03 | Stored DTCs | 03 |
| 04 | Clear DTCs & reset MIL | 04 |
| 06 | On-board monitor test results | 06 <mid> |
| 07 | Pending DTCs (this drive cycle) | 07 |
| 08 | Control on-board component | 08 … |
| 09 | Vehicle info (VIN, CalID, CVN) | 09 <pid> |
| 0A | Permanent DTCs | 0A |
Mode 04 is destructive. Clearing DTCs also wipes freeze-frame data and resets the readiness monitors, so the car has to re-run its self-tests before it will pass inspection. sloppyCAN guards this button with a confirmation.
Decoding a PID Value
Each PID has a fixed formula. Take Engine RPM (Mode 01, PID
0x0C). The ECU returns two bytes A and B, and the
standard says:
Response 41 0C 1A F8 → A=0x1A=26, B=0xF8=248 →
((26×256)+248)÷4 = 1726 rpm
Other PIDs use one byte: Vehicle speed (PID 0D) is
A km/h; Coolant temp (PID 05) is
A − 40 °C (the −40 offset lets one unsigned byte cover −40…215 °C).
Percentages are usually A × 100 ÷ 255. sloppyCAN applies these conversions
automatically and shows the engineering value.
Discovering Supported PIDs
A scan tool asks which PIDs exist rather than guessing. PID 0x00 returns a
4-byte bitmask of which PIDs in 0x01–0x20 are supported, MSB
first (the top bit = PID 0x01). If the last bit (PID 0x20)
is set, it means "ask PID 0x20 for the next block," and so on through
0x40 and 0x60.
So PIDs 01, 03, 04, 05, 06, 07 are supported; 02 and 08 are not. The Probe supported PIDs button walks all four blocks and lights the grid.
Trouble Codes (DTCs)
Modes 03, 07 and 0A return Diagnostic Trouble Codes, two bytes each.
Those 16 bits unpack into the familiar P0420 form:
| Bits | Meaning |
|---|---|
| 15–14 | System letter: 00=P (Powertrain), 01=C (Chassis), 10=B (Body), 11=U (Network) |
| 13–12 | First digit (0–3) |
| 11–0 | Remaining three hex digits |
Example 0x0420 → top two bits 00 = P,
next two 00 = 0, low 12 bits 0x420 →
P0420 ("Catalyst System Efficiency Below Threshold, Bank 1").
Try it
Back in sloppyCAN, switch the ISO-TP/UDS tab to OBD-II, click
Demo in the header, then hit Engine RPM or start
Quick Watch on RPM + Speed + Coolant. The demo ECU answers on
0x7E8 with live-ish values so you can see the whole flow without hardware.