J1939 Diagnostics: DM1, DM2 and the Structure of a DTC
Anyone reading out the fault memory of a commercial vehicle, an engine or an agricultural machine inevitably ends up with three abbreviations: SPN, FMI and OC. Together they form a Diagnostic Trouble Code (DTC), and it is transported by the diagnostic messages DM1 and DM2 defined in SAE J1939-73. This article explains how those two parameter groups are built, how to decompose a DTC correctly, and where hand-written parsers regularly get it wrong.
DM1 — active faults
The parameter group DM1 (Active Diagnostic Trouble Codes) carries PGN 65226 (0xFECA) and is sent with the default priority 6. It is a broadcast message in PDU2 format — the PF value 0xFE is above 240, so there is no destination address but a group extension. Every device on the network can listen in on DM1 without being addressed.
As long as at least one fault is active, the ECU transmits DM1 cyclically once per second. This is where DM1 differs fundamentally from an event log: a DM1 is not a fault entry but a snapshot of all faults currently present. Once a fault clears, it simply no longer appears in the next DM1.
Important for receivers: even when no fault is active, a standard-compliant device keeps transmitting DM1 cyclically — with the lamps off and a DTC field containing SPN 0, FMI 0 and occurrence count 0. The absence of DM1 therefore does not mean “no faults”, it means “the device is not responding”. A receiver that does not model this distinction will miss failed ECUs.
When the fault state changes, DM1 may be transmitted once immediately; after that the one-second cycle applies again. An ECU that pushes out DM1 every few milliseconds while a sensor value flutters violates the specification and loads the bus for no reason.
The lamp status in bytes 1 and 2
The first two bytes of DM1 do not describe the fault but the indication in the cab. Byte 1 holds the status of four lamps, two bits each:
| Bits in byte 1 | Lamp | Meaning |
|---|---|---|
| 8–7 | Malfunction Indicator Lamp (MIL) | emissions-related fault |
| 6–5 | Red Stop Lamp | stop the vehicle |
| 4–3 | Amber Warning Lamp | warning, operation may continue |
| 2–1 | Protect Lamp | condition outside engine operation, e.g. coolant |
The values are 00 for off, 01 for on and 11 for not available. Byte 2 has exactly the same structure but describes the flash behaviour of the same four lamps: slow flash, fast flash or no flashing.
That second byte is the one most often ignored in practice. Bytes 1 and 2 have to be evaluated together — only both combined yield the statement “amber warning lamp flashing slowly”. A diagnostic tool that displays byte 1 only withholds information that, for the engine manufacturer, may well distinguish different fault classes.
The DTC in four bytes
The first DTC follows from byte 3 onwards. It always occupies exactly four bytes and contains four fields:
| Field | Width | Position |
|---|---|---|
| SPN (Suspect Parameter Number) | 19 bit | bytes 3 and 4 in full, plus the upper 3 bits of byte 5 |
| FMI (Failure Mode Identifier) | 5 bit | lower 5 bits of byte 5 |
| SPN conversion method (CM) | 1 bit | most significant bit of byte 6 |
| Occurrence count (OC) | 7 bit | lower 7 bits of byte 6 |
The SPN identifies the affected parameter, i.e. what is faulty — the coolant temperature, say, or a particular pressure sensor. The mapping from SPN to parameter is given in SAE J1939-71 and in the J1939 Digital Annex. Manufacturer-specific SPNs are permitted, so an unknown value is not automatically a parser error.
The FMI identifies the failure mode, i.e. how the parameter is faulty. The value range 0 to 21 is defined in J1939-73, and 31 means “condition exists” without further specification. The complete table belongs in the standard rather than in a blog article, but it is worth knowing the groups:
- Electrical faults — voltage above normal or shorted high (3), voltage below normal or shorted low (4), current below normal or open circuit (5), current above normal (6). These are the codes that point at wiring rather than at the application.
- Plausibility faults — data valid but above or below the normal range, each in three severity levels. The value is measured cleanly but is implausible.
- Signal behaviour — data erratic or incorrect (2), abnormal update rate (9), abnormal rate of change (10).
- Communication faults — received network data in error (19). The single most important FMI for network integrators, because it points at another device rather than at the reporting one.
The occurrence count records how often the fault has become active since the last reset. The counter saturates at 126, and 127 means “not available”. It does not count down — an OC of 40 on a fault that is currently active strongly suggests an intermittent loose contact rather than a failed component.
The SPN conversion method — the most common parser bug
The CM bit has historical roots and is the cause of most incorrectly decoded fault codes. In the early days of J1939 there were several ways of distributing the 19 bits of the SPN across three bytes. Only one of them applies today, and it is indicated by CM = 0: byte 3 holds the least significant byte of the SPN, byte 4 the middle one, and the upper three bits of byte 5 hold the three most significant bits.
A CM = 1 signals one of the older methods. Those cannot be told apart from each other, so a generic receiver cannot reliably reconstruct the SPN in that case. For new designs, only CM = 0 is permitted.
The practical mistake happens elsewhere: many hand-written parsers read the SPN as a 24-bit value from bytes 3 to 5 and mask off the lower five bits — which leaves the three SPN bits from byte 5 in the wrong position. The result is SPN values that happen to look right for faults below 65536 and are systematically wrong above it. Anyone who only uses small SPNs during testing will never notice.
Several faults at once
If several faults are active, further DTCs are simply appended in four-byte blocks. Two DTCs already make 10 bytes — the parameter group then no longer fits into a single CAN frame and has to be transported by the transport protocol.
Since DM1 is a broadcast, the Broadcast Announce Message (BAM) is used rather than the handshake procedure CMDT. That has two consequences which are often underestimated during design: BAM requires gaps of at least 50 ms between data frames, so a DM1 carrying many faults needs several hundred milliseconds of transmission time. And BAM has no flow control — a receiver that cannot keep up loses the message silently.
For the implementation this means the DM1 receive path has to handle the transport protocol case from the start. A parser that only processes 8-byte frames with a single DTC works flawlessly on the bench and fails precisely when several faults coincide in the field.
DM2 and clearing
DM2 (Previously Active Diagnostic Trouble Codes), PGN 65227 (0xFECB), contains faults that occurred and are no longer present — the actual fault memory. Format and lamp fields are identical to DM1; the decisive difference is the transmission behaviour: DM2 is not sent cyclically but only on request, via the request parameter group (PGN 59904).
Two services are available for clearing: DM11 (PGN 65235) resets the active faults, DM3 (PGN 65228) clears the previously active ones, i.e. the DM2 content. Both are sent as a request and acknowledged by the device. What matters is the expectation: a DM11 on a fault whose cause still exists will make that fault active again immediately — with the occurrence count incremented by one.
Evaluation in practice
A DM1 with three active faults consists of a BAM announcement frame and three data frames, with lamp status and DTCs spread across packet boundaries. Assembling those bytes by hand and reconstructing the SPN from three fields is tedious and error-prone.
The emotas CANinterpreter with the J1939 extension does it for you: it reassembles the transport protocol transfer, decomposes each DTC into SPN, FMI and occurrence count, and shows the lamp status in plain text. For field troubleshooting the recording and replay functions matter as well, because intermittent faults by their nature cannot be reproduced on demand — a long-term recording that you can search afterwards for the moment the DTC appeared is what helps here.
For device manufacturers
Three recommendations that save the integrators of your device a great deal of work:
- Always set CM to 0 and pack the SPN according to the current method. Anything else cannot be decoded by generic tools.
- Transmit DM1 in the fault-free state as well, so receivers can distinguish “all fine” from “device gone”.
- Document the SPNs you use, in particular the manufacturer-specific ones. An SPN without documentation is just a number to the user — and generates exactly the support requests you wanted to avoid.
