ECU Diagnostics – part 13.2 : OBD-II

The OBD-II diagnostic protocol is well defined and information about it can be found in On-board Diagnostics. It’s a mish-mash of many diffrerent standards, both physical and electrical, that I’ll refer to as OBD-II. There’s also a complete breakdown of the Services and PIDs (see below) that can be found in On-board Diagnostic PIDs.

I’ll talk a little bit about the protocol here but the main point of this post is to say what OBD-II data the Catheram MBE 9A4 ECU supports and what that looks like on the CAN bus.

OBD-II can be broken down into three main data types:

  • Services (previously called “modes”),
  • Parameter IDentifiers (PIDs) and,
  • OBD-II data

You can find all the relevant standards defined in the first link above… but many of them are behind a pay-wall. So unless you’re prepared to pay for the documents then you have to glean what you can from Google searches like I did.

Fundamentally, the bog-standard OBD-II diagnostic protocol uses a single CAN bus frame (max 8 bytes, but usually less), to request, and then get a response, for a single data value (variable) from the car’s ECU. It is a request response protocol, meaning a scanner, or active device, requests a data value and the ECU responds with the result. Both request and response take up one CAN bus frame.

The basics of the protocol request and response are as follow:

OBD-II CAN Bus Request Frame        
Byte 0 Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6 Byte 7
LENGTH SERVICE ID Data 0 Data 1 Data 2 Data 3 Data 4 Data 5
OBD-II CAN Bus Response Frame        
Byte 0 Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6 Byte 7
LENGTH SERVICE ID + 0x40 Data 0 Data 1 Data 2 Data 3 Data 4 Data 5

The important points here, from a 9A4 perspective, are:

  • LENGTH: First byte of request or response is the number of additional bytes in the message. Note that this is “additional” bytes, in addition to the length byte itself. So, for instance a request for engine coolant temp (PID = 0x05, byte 2) and service ID of 0x01 (byte 1) requires a length of 2, i.e. two bytes (Service ID + PID) in addition to the length byte (byte 0).
  • SERVICE ID: See OBD-II and OBD-II PIDs for a list of possible service ID’s. I’ve only verified that a 9A4 only responds to a service ID of 1 so far
  • SERIVE ID + 0x40: When responding to a request 0x40 is added to the service ID, so a request with service ID of 0x01 will get a response service ID of 0x41.
  • The ECU always responds with 8 bytes (seems to pad with 0xff)
  • 9A4 ECU responds with a CAN ID of 0x18daf101
  • Only some 15 PIDs are supported by our ECUs, see below for a list

An example request and response for coolant temp might be:

OBD-II CAN Bus Request Frame : Coolant Temp    
Byte 0 Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6 Byte 7
0x02 0x01 0x05          

… and the response:

OBD-II CAN Bus Response Frame : Coolant Temp    
Byte 0 Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6 Byte 7
0x03 0x41 0x05 0x3d        

We can see here that the ECU responded with a coolant temperature of 0x3d. We then need to refer to the offset and scaling algorithm found again here. For a PID of 0x05, Coolant Temp, the formula is ( Result-40 ), i.e.

Coolant Temp = 0x3d – 40 = 61 -40 = 21 C 

There’s not a lot of resolution there, just an integer. That’s one of the reason’s we might like to use either of the MBE Simple or MBE ISOTP diagnostic protocols, with the later providing a lot more detail.

PID Discovery

With all these PIDs supported by the standard and cars not having to support them all, there needs to be a way of figuring out what each car can support. This is done with PIDs 0x01, 0x20, 0x40, 0x60, 0x80, 0xx0 and 0xc0.

When a request is made to each of these PIDs, the ECU responds with a bit-field showing which of the next 32 (0x20) PIDs are supported in the 4 data bytes returned in the response, including whether the next+1 set of 32 PIDs are supported at all.

So for our ECUs we get the following communication at the start of a scanning cycle:

1672 16.267925833 0x18db33f1 02 01 00 ff ff ff ff ff
1673 16.269274940 0x18daf101 06 41 00 d8 36 80 19 ff
1724 16.776437588 0x18db33f1 02 01 20 ff ff ff ff ff
1726 16.778090875 0x18daf101 06 41 20 20 00 20 01 ff
1777 17.284954491 0x18db33f1 02 01 40 ff ff ff ff ff
1778 17.287421616 0x18daf101 06 41 40 40 10 00 00 ff

Decoding that a bit, we can see that the 9A4 ECU supports:

PID=0x00 -> 0x01-0x20: 0xd8368019
PID=0x20 -> 0x21-0x40: 0x20002001
PID=0x40 -> 0x41-0x60: 0x40100000

And if we unwrangle all the bits then we’re shown that these ECUs support the following PIDs (definitions reproduced from Wikipedia):

PID
(hex)
Data bytes returned Description Min value Max value Units Formula
00 4 PIDs supported [01 – 20]       Bit encoded
  4 Monitor status since DTCs cleared.        Bit encoded
02 2 Freeze DTC        
04 1 Calculated engine load 0 100 % (or )
05 1 Engine coolant temperature -40 215 °C
0B 1 Intake manifold absolute pressure 0 255 kPa
0C 2 Engine RPM 0 16,383.75 rpm
0E 1 Timing advance -64 63.5 ° before TDC
0F 1 Intake air temperature -40 215 °C
11 1 Throttle position 0 100 %
1C 1 OBD standards this vehicle conforms to       Bit encoded
1D 1 Oxygen sensors present (in 4 banks)       Similar to PID 13, but [A0..A7] == [B1S1, B1S2, B2S1, B2S2, B3S1, B3S2, B4S1, B4S2]
20 4 PIDs supported [21 – 40]       Bit encoded
23 2 Fuel Rail Gauge Pressure (diesel, or gasoline direct injection) 0 655,350 kPa
33 1 Absolute Barometric Pressure 0 255 kPa
40 4 PIDs supported [41 – 60]       Bit encoded
42 2 Control module voltage 0 65.535 V
4C 1 Commanded throttle actuator 0 100 %

Example OBD-II Communications

Here’s one full cycle of output that my scanner pulled from the car. Obviously, the scanner is attempting to show “real time” data and so repeatedly sends requests for each of the data values that the ECU supports, then repeats again and again to give the impression of “real time” output.

Here’s the Raw CAN bus frames first followed by what Wireshark decodes the packets as.

#    Time         CAN ID     Data
1891 18.384234117 0x18db33f1 02 01 02 ff ff ff ff ff
1892 18.386480284 0x18daf101 04 41 02 22 26 ff ff ff
1948 18.932752338 0x18db33f1 02 01 04 ff ff ff ff ff
1949 18.933708266 0x18daf101 03 41 04 00 ff ff ff ff
2004 19.480255834 0x18db33f1 02 01 05 ff ff ff ff ff
2006 19.482689349 0x18daf101 03 41 05 3d ff ff ff ff
2061 20.029324990 0x18db33f1 02 01 0b ff ff ff ff ff
2062 20.031880206 0x18daf101 03 41 0b c8 ff ff ff ff
2118 20.578419385 0x18db33f1 02 01 0c ff ff ff ff ff
2119 20.581109100 0x18daf101 04 41 0c 00 00 ff ff ff
2175 21.127303969 0x18db33f1 02 01 0e ff ff ff ff ff
2176 21.128371192 0x18daf101 03 41 0e 80 ff ff ff ff
2231 21.674841186 0x18db33f1 02 01 0f ff ff ff ff ff
2233 21.676107628 0x18daf101 03 41 0f 38 ff ff ff ff
2288 22.222260164 0x18db33f1 02 01 11 ff ff ff ff ff
2289 22.224313834 0x18daf101 03 41 11 39 ff ff ff ff
2345 22.771129266 0x18db33f1 02 01 1c ff ff ff ff ff
2346 22.773691168 0x18daf101 03 41 1c 06 ff ff ff ff
2402 23.320629505 0x18db33f1 02 01 1d ff ff ff ff ff
2403 23.323019928 0x18daf101 03 41 1d 01 ff ff ff ff
2459 23.869724288 0x18db33f1 02 01 23 ff ff ff ff ff
2460 23.872168914 0x18daf101 04 41 23 00 f0 ff ff ff
2515 24.419230119 0x18db33f1 02 01 33 ff ff ff ff ff
2517 24.421439008 0x18daf101 03 41 33 00 ff ff ff ff
2572 24.968236310 0x18db33f1 02 01 42 ff ff ff ff ff
2573 24.969567270 0x18daf101 04 41 42 2d ad ff ff ff
2629 25.516453162 0x18db33f1 02 01 4c ff ff ff ff ff
2630 25.518540406 0x18daf101 06 41 4c 00 ff ff ff ff

… and here’s how Wireshark decodes those raw CAN bus frames:

#    Time         ID         Info
1891 18.384234117 [18db33f1] Freeze DTC
1892 18.386480284 [18daf101] Freeze DTC: < 22 26 >
1948 18.932752338 [18db33f1] Calculated engine load
1949 18.933708266 [18daf101] Calculated engine load: 0.00 %
2004 19.480255834 [18db33f1] Engine coolant temperature
2006 19.482689349 [18daf101] Engine coolant temperature: 21 °C
2061 20.029324990 [18db33f1] Intake manifold absolute pressure
2062 20.031880206 [18daf101] Intake manifold absolute pressure: 200 kPa
2118 20.578419385 [18db33f1] Engine RPM
2119 20.581109100 [18daf101] Engine RPM: 0.00 rpm
2175 21.127303969 [18db33f1] Timing advance
2176 21.128371192 [18daf101] Timing advance: 0.00 °BTDC
2231 21.674841186 [18db33f1] Intake air temperature
2233 21.676107628 [18daf101] Intake air temperature: 16 °C
2288 22.222260164 [18db33f1] Throttle position
2289 22.224313834 [18daf101] Throttle position: 22.35 %
2345 22.771129266 [18db33f1] OBD standards
2346 22.773691168 [18daf101] OBD standards: EOBD
2402 23.320629505 [18db33f1] Oxygen sensors present (4 banks)
2403 23.323019928 [18daf101] Oxygen sensors present (4 banks): Bank1 sensors: 1 , Bank2 sensors: None, Bank3 sensors: None, Bank4 sensors: None
2459 23.869724288 [18db33f1] Fuel Rail Gauge Pressure
2460 23.872168914 [18daf101] Fuel Rail Gauge Pressure: 2400 kPa
2515 24.419230119 [18db33f1] Absolute Barometric Pressure
2517 24.421439008 [18daf101] Absolute Barometric Pressure: 0 kPa
2572 24.968236310 [18db33f1] Control module voltage
2573 24.969567270 [18daf101] Control module voltage: 11.693 V
2629 25.516453162 [18db33f1] Commanded throttle actuator
2630 25.518540406 [18daf101] Commanded throttle actuator: 00

So, the MBE 94A’s support the OBD-II diagnostic protocol. It’s not a huge amount of info that can be gleaned from the car, but it’s more than is available from the default broadcast MBE Simple protocol.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.