LANE PILOT

Field note

Mode 09 with several modules: whose calibration ID is whose

A 2014 Suburban listed its CalIDs and CVNs in different module orders, and on a 2009 BMW the parser turned clean CalIDs into garbage. How to pair them.

By Reed, a technician with 17 years in the bay ·

2009 BMW E93 · 2014 Chevrolet Suburban · 2017 Toyota Prius · 2025 BMW X3

Mode 09 is where a scan tool gets a car's identity: the VIN, the calibration IDs (CalIDs), the calibration verification numbers (CVNs) and the ECU names. Each of those is its own request, sent as a broadcast, and every module that supports it answers. So each reply can carry several modules, in whatever order they happened to answer. This note covers four cars where that went wrong, or nearly did, and how to keep the IDs attached to the right module.

Headers off: a 2009 BMW E93's IDs came out as garbage

The same car was scanned twice. With the key off, only the transmission computer answered:

ECU Name: TCM-TransmisCtrl
CalID: 000007614313 | 000007634251

With the key on, the engine and transmission computers both answered:

ECU Name: ECMtD4VvT6G&G&647G&
CalID: 7624@#C | c0

With headers off, an ELM327-style adapter prints each module's multi-frame reply as a three-character length line followed by numbered data lines. Nothing in that output says which module sent which block. The parser at the time joined every line into one hex string, and that swept the second module's length line in with the data. Three hex characters is an odd count, so every byte after it was shifted by half a byte. Instead of failing outright, valid text turned into printable garbage.

The VIN on the same scan came through fine, most likely because only one module answered that request.

The fix: run identity requests with headers on (AT H1), so every line carries the address of the module that sent it, and split the reply by that address before decoding anything.

Headers on, still a trap: a 2014 Chevrolet Suburban

Three modules answered the identity requests, and the lines did not list them in the same order:

LineOrder the line listed them in
CalIDs7E8, 7EA, 7EB
CVNs7E8, 7EB, 7EA
ECU namesECM, FPCM, TCM

The ECU name line was the only one shown without addresses. Paired with the CalID line by position, it swaps the transmission (TCM) and the fuel pump control module (FPCM). Paired with the CVN line it happens to come out right, because the names arrived in the same order as the CVNs did that time. Nothing guarantees that. The module-by-module walk later in the same scan settled it: 7EA is the TCM and 7EB is the FPCM.

That scan also had eight CalIDs from the engine computer alone. A module can legitimately report several, so "one CalID per module" is not a safe assumption either.

The fix: on CAN cars, where the identity requests run with headers on, the scan's identity log puts an address on every element of every line whenever two or more modules answer, so nothing has to be paired by position. A single responder still shows a plain name, because there is nothing to mix up.

The same thing on a hybrid: a 2017 Toyota Prius

Four modules answered. The CalID line came back as 7E8, 7EB, 7EA, 7EE, and the CVN line as 7E8, 7EA, 7EB, 7EE, with the middle two swapped. With an address on every element, the ECU names came back as:

Paired by position, the second module on the CalID line (7EB, the battery module) would sit next to the second module on the CVN line (7EA, the hybrid control module).

A 2025 BMW X3 (G45)

Its CalID line came back as 7E8, 7E9, 7EF, and its CVN line as 7E8, 7EF, 7E9: the same reordering on a current model. One more detail from that car: 9 of its 10 CalID values were identical to its CVN values, from two separate requests. Do not assume the two lists carry different information on every make.

A lost frame can invent an ID

Calibration IDs arrive in fixed 16-character fields across several CAN frames. If one frame goes missing, every field after it is cut at the wrong place. In a test built from one module reporting two real calibration IDs, MQ4PB5060R000000 and PYB2TC000PY0B011, losing one frame made the decoder print MQ4PB5060RYB2TC0: printable, plausible, and matching neither of the two real IDs. Nothing about the result looks wrong. Lane Pilot now drops a responder whose reply arrived short instead of decoding it.

What to take from this

  1. Run Mode 09 identity requests with headers on, and split every reply by the responding address before decoding.
  2. Key every CalID, CVN and ECU name by that address. Never pair lines by position: they do not come back in the same order.
  3. Expect several CalIDs from one module.
  4. Drop a module's reply if it arrived shorter than it said it would be.
  5. If a read is clean with one module awake and garbage with several, suspect the splitting before you suspect the car.

More field notes