Skip to content

Latest commit

 

History

History
146 lines (100 loc) · 5.2 KB

File metadata and controls

146 lines (100 loc) · 5.2 KB

🕵️‍♂️ Chapter 4: Error Management and OBD-II (Vehicle Diagnostics)

Industrial systems do not have the right to give a "Blue Screen". If one sensor fails, the whole factory must not stop. CAN Bus has the ability to detect a faulty device and kick it off the network (Bus Off).

Also in this chapter, we will see how to read your car's engine RPM and speed via the OBD-II port.


4.1 Error States: Yellow Card and Red Card 🟨🟥

Every CAN controller has an internal "Error Counter".

  • TEC: Transmit Error Counter
  • REC: Receive Error Counter

The system goes through 3 stages:

  1. Error Active (Healthy): Error counter < 127. The device works normally. If it finds an error, it sends an "Error Flag" (6 Dominant bits) to warn everyone.
  2. Error Passive (Yellow Card): Error counter > 127. The device is now considered so unreliable that even if it finds an error, it is not allowed to scream. It just takes notes silently.
  3. Bus Off (Red Card): Error counter > 255.
    • The controller shuts itself down completely.
    • It disconnects electrically from the bus (Stays in Logic 1 / Recessive mode).
    • It cannot speak again without software intervention (Reset).

🛠️ Field Scenario: If your device works intermittently (starts and stops), it is probably falling into the "Bus Off" state. You can bring it back to life with the twai_initiate_recovery() command.


4.2 What is OBD-II? 🚗

OBD (On-Board Diagnostics) is a protocol standard on all cars since 2001. It is essentially a "Question-Answer" layer running on top of CAN Bus.

  • Request ID: 0x7DF (The engine ECU listens to messages sent to this ID).
  • Response ID: 0x7E8 (Usually the response from the engine ECU).

Standard Request Packet (8 Bytes)

Byte 0 Byte 1 Byte 2 Byte 3-7
Length Service (Mode) PID (Code) Empty
0x02 0x01 (Current Data) 0x0C (RPM) 0x55 (Don't Care)

4.3 Example: Reading Engine RPM 🏎️

To read engine RPM, PID 0x0C is used.

Step 1: Send Request

ID: 0x7DF -> Data: 02 01 0C 00 00 00 00 00

Step 2: Decode Response

The car replies with something like this: ID: 0x7E8 -> Data: 04 41 0C 1A F8 00 00 00

  • 04: 4 Bytes of valid data.
  • 41: Response to Service 01 (01 + 40 = 41).
  • 0C: The requested PID (RPM).
  • 1A F8: Actual Value (Hex).

Formula: $$RPM = \frac{(A \times 256) + B}{4}$$

$$RPM = \frac{(0x1A \times 256) + 0xF8}{4} = \frac{(26 \times 256) + 248}{4} = 1726 \text{ rpm}$$

sequenceDiagram
    participant ESP32 as ESP32 (Tester)
    participant ECU as Vehicle Brain (ECU)

    Note over ESP32: Request: Service 01, PID 0C (RPM)
    ESP32->>ECU: ID: 0x7DF [02 01 0C 00...]
    
    Note over ECU: Calculates Data
    ECU-->>ESP32: ID: 0x7E8 [04 41 0C 1A F8...]
    
    Note over ESP32: Apply Formula: ((A*256)+B)/4
    Note over ESP32: Result: 1726 RPM
Loading

4.4 Practical Code (OBD-II Reader) 💻

The code below asks the vehicle "What is your speed?" every second. (Speed PID: 0x0D)

void getVehicleSpeed() {
    // 1. Prepare Request
    twai_message_t tx_msg;
    tx_msg.identifier = 0x7DF; // Broadcast Request ID
    tx_msg.extd = 0;           // Standard 11-bit
    tx_msg.data_length_code = 8;
    
    tx_msg.data[0] = 0x02; // Data Length (Mode + PID)
    tx_msg.data[1] = 0x01; // Service 01 (Show Current Data)
    tx_msg.data[2] = 0x0D; // PID 0D (Vehicle Speed)
    
    // Fill the rest with 0x55 (Padding)
    for(int i=3; i<8; i++) tx_msg.data[i] = 0x55; 

    // 2. Transmit
    twai_transmit(&tx_msg, pdMS_TO_TICKS(100));

    // 3. Wait for Response (Timeout: 100ms)
    twai_message_t rx_msg;
    if (twai_receive(&rx_msg, pdMS_TO_TICKS(100)) == ESP_OK) {
        // Did the response come from 0x7E8? And is it PID 0x0D?
        if (rx_msg.identifier == 0x7E8 && rx_msg.data[2] == 0x0D) {
            int speed = rx_msg.data[3]; // Formula for speed is just 'A'
            printf("Vehicle Speed: %d km/h\n", speed);
        }
    }
}

✅ CAN Series Summary

Congratulations! You have mastered the world of CAN Bus.

  1. Physical: Don't forget the 120 Ohm resistor. Differential signals are immune to noise.
  2. Arbitration: Small ID (0x000) always wins, big ID shuts up.
  3. Filter: Use Mask and Code to save the processor from unnecessary load.
  4. Error: Recover a device that went "Bus Off" using initiate_recovery.
  5. OBD-II: Ask 0x7DF, get answer from 0x7E8, apply formula.


Chapter 3: Integration Main Menu Support