Skip to Content

Reading ECU faults (DTC)

This note shows how to configure the device to report which faults the vehicle has —the same codes a workshop scan tool shows— and how to integrate them into a platform.

Until now the device reported whether the vehicle had faults and how many: the equivalent of the dashboard warning light. With the DTC module it reports which ones.

Requires firmware from the 1.09.27 series, which at the time of publishing this note is a T (pre-release) version delivered via FOTA on request. OBD2 support arrived in T9; with an earlier T the device only reads J1939. Check with >QVR< before starting.

Compatibility

💾Firmware:v1.09.27
SP-IOT
SM-IOT

Rinho Zero IoT has no CAN transceiver: it cannot read vehicle faults.


1. What you get

VehicleProtocolWhat it reports
Truck, bus, machinery, agricultureJ1939SPN (which component fails), FMI (how it fails), reporting ECU, occurrence count and dashboard lamps
Car, pickup, light utilityOBD2The full standard code (P0301, P0420, U0100) and the reporting ECU

Everything travels over the device’s normal protocol (UDP/TCP/SMS), with queueing, retries and acknowledgement. No extra hardware required: it uses the CAN connection the device already has, and works the same with the CANBUS Contactless (inductive) accessory.


2. Check the bus protocol

This is the step that prevents most problems. The configured protocol must match the vehicle:

>QCXCAN<
VehicleExpected protocol
Truck, heavy machinery, agricultureJ1939
Car, pickup, light utilityOBDII

If the protocol does not match the vehicle, the module reports zero faults every time, even with the dashboard lit. It is the most frequent cause of “it doesn’t work”.


3. Enable reading

A single command sets everything in motion:

>SCXDTC1,3,0,1,GP<
FieldValueMeaning
1st1Enables reading (factory default is 0)
2nd3Seconds without seeing a code before clearing it
3rd0Reserved (vehicle clearing, no effect yet)
4th1Automatic report on new fault or resolution
5thGPReport destination: main GPRS

Verification: >QCXDTC<RCXDTC1,3,0,1,GP

During commissioning, use LOG as the destination (>SCXDTC1,3,0,1,LOG<): reports are stored in the device and retrieved together with >QDL+< at the end of the trip, without depending on the server being up. Once validated, switch to GP.

With the first field at 0 (factory default) the module is completely inactive: it allocates no memory and does not touch the bus.


4. Query the status

>QDTC<
ResponseMeaning
RDTC0Reading the bus, no active faults — a valid result
RDTC2;J:00:100:1:4;J:00:1761:1:12Two active faults (truck)
RDTC1;O:00:P0301:0:0One active fault (light vehicle)
RDTCNAReading is disabled

On OBD2 the device polls the ECU every 30 seconds: after enabling, wait one cycle before trusting a zero response. On J1939 the ECU broadcasts faults on its own and reading is immediate.


5. What the platform receives

With autorpt=1, every time a new fault appears or all of them clear, a DF report arrives:

>RDF00020826143512;2;J:00:100:1:4;J:00:1761:1:12< │ │ │ │ │ │ │ └─ fault list │ │ └──────── active count (0 = all cleared) │ └─────────────── date and time OF THE EVENT (ddmmyy hhmmss) └────────────────── report number

Three things that simplify integration:

  • Every report is a full snapshot. No state to rebuild on the server side.
  • Date and time are those of the fault, not of transmission: if the vehicle was out of coverage, the report waits in the queue and reports when it actually happened once signal returns.
  • Count of zero = resolution. When the last fault disappears, the notice arrives.

It can also be requested at any moment, without waiting for a fault:

>QDF< // direct response over the asking channel >GDF00H< // queues the report to the configured destination

6. Interpreting the codes

J1939

J:00:100:1:4

The engine ECU (00) reports that oil pressure (SPN 100) is below the normal range (FMI 1), and it occurred 4 times.

The FMI tells the type of fault, and that difference changes the diagnosis:

FMIMeaning
0 / 1Value above / below normal range
2Erratic or intermittent data
3 / 4Short to power / short to ground
5 / 6Open circuit / over-current
7Mechanical system not responding
12Component damaged
31Condition exists, no further detail

Fuel pressure with FMI 1 is genuinely low pressure (filter, pump). With FMI 5 it is an open circuit: the sensor was disconnected or a wire was cut.

Reference SPNs: 100 oil pressure · 110 coolant temperature · 94 fuel pressure · 190 RPM · 168 battery voltage · 651-656 injectors 1 to 6 · 1761 AdBlue/urea level · 3226 NOx sensor (SCR).

OBD2

O:00:P0301:0:0

The engine ECU (00) reports a cylinder 1 misfire (P0301).

LetterSystem
PPowertrain
CChassis (brakes, suspension, steering)
BBody (airbag, comfort)
UNetwork / module communication

The last two fields are zero: FMI and occurrence count are J1939 fields, OBD2 does not transmit them.

Codes come out in standard format (SAE J1939 and J2012). Text descriptions (“Catalyst System Efficiency…”) are resolved on the platform with the public tables of the standard, as everywhere else in the market.


7. Reacting in the vehicle, without the server

Faults are event engine triggers: they combine with ignition, speed, inputs or geofences like any other signal.

SignalActivates when
DTC00There is at least one active fault
DTC01A new fault appeared
DTC02A dashboard lamp is on (J1939 only)
DTC03All faults were cleared
// New fault → immediate report to the server >SRL05E;TRG=DTC01+;ACC={GDF00H}< // Dashboard lamp on → output to a buzzer in the cabin >SRL07E;TRG=DTC02+;ACC={SSSXP0011}< // New fault with ignition on → SMS notice to the supervisor >SRL08E;TRG=DTC01+;CND=IGN;ACC={GTX01H;@SM0;TXT=Active fault}<

For numeric conditions there are the EVAL functions:

>EVAL DTCN()< // number of active faults >EVAL DTCH(100)< // 1 if oil pressure is in fault (J1939) >EVAL DTC(2)< // 1 if a dashboard lamp is on

And the 'DTC' token inserts the full list into any user report:

>SUC00 $ID faults:'DTC'<

8. If no fault shows up

In order, most frequent first:

  1. The protocol does not match the vehicle>QCXCAN<: J1939 on a truck, OBDII on a light vehicle.
  2. Reading is disabled>QDTC< answers RDTCNA. Enable it with SCXDTC.
  3. The firmware T is earlier than 9 and the vehicle is light>QVR<. OBD2 support arrived in 1.09.27.T9.
  4. The 30-second OBD2 cycle has not elapsed — wait one more round.
  5. The vehicle has no active faultsRDTC0 is a correct result. Cross-check with the dashboard or a scan tool.
  6. The ECU does not publish faults — not all of them broadcast on the bus (J1939) or answer Mode 03 (OBD2), the same as with the VIN. Confirm by checking whether other engine data arrives (RPM, temperature) with ECU.

If faults appear in >QDTC< but no report arrives: check the 4th field of SCXDTC (must be 1) and the 5th, the destination. With LOG the report does not go over the network: it stays in the device and is retrieved with >QDL+<.


9. Current scope

FunctionStatus
Active J1939 faults, one or several ECUs, one or several codes
Active OBD2 faults, one or several ECUs
Automatic, on-demand and rule-driven reporting
Signals, EVAL functions and template token
Clearing the device list (CDTC)
Clearing faults on the vehicle (DM11 / Mode 04)❌ Planned
Stored or pending faults (DM2 / Mode 07)❌ Planned
Dashboard lamps on OBD2❌ J1939 only
DTCH() over OBD2 codes❌ J1939 only (searches by SPN)

Limits: up to 32 simultaneous faults in the device table and about 15 per frame (the reported count is always the real one). On J1939 the module is listen-only and transmits nothing on the bus; on OBD2 it polls every 30 seconds, just like a scan tool plugged into the diagnostic connector.


See Also

Last updated