Reverse engineering the MQB Electric steering rack

Forum on Volkswagen related hardware, so VW, Audi, Seat, Skoda etc.
Post Reply
Jacobsmess
Posts: 700
Joined: Thu Mar 02, 2023 1:30 pm
Location: Uk
Has thanked: 362 times
Been thanked: 103 times

Reverse engineering the MQB Electric steering rack

Post by Jacobsmess »

I'm looking for a bit of direction in trying to hack this MQB rack from a VW Transporter 6.1.
It works in fail safe but it'd be nicer if it ran with the speed mapping to the level of assist.
I've got some Canlogs from a MK7 Golf (I think) and played them back. I've identified the differences between the two, and there seems to be only one CAN ID required to wake up the rack... 0x0FD ESP_21

When powered up the unit sends out comms on...
086 - 4th and 5th bits change with torque input on the rack, whilt playing the CAN log back at the rack these bits change moreso, 4th bit indicates direction of turn (9F turned CCW and DF/5F when turned CW)
09F - 6th bit changes with torque applied to the rack, I need to map this out but this appears to be the angle of the steering wheel
7th bit changes with direction also (00 for CW and 80 for CCW)
5FC - is a static message when in failsafe mode (no playback, with playback it responds), I need to look into this further but changes occur on the 1st, 2nd, 3rd and 4th bits
32A - need to check this one more but no changes obseved
6C0 - changes at 7th bit from 19 to 11 when having the log played back.

Any pointers on how to narrow things down further?

0FD in the CAN log appears to contain some speed information but I'm sure someone with more experience will be able to shed some some light.

I've cut the CAN log down into sections where it appears there is no driving and parts with driving, as expected, playing back with driving provides more assistance than playing back parts with driving.
Attachments
Driving Log1 7-11-23-shortened with drive.csv
(20.34 MiB) Downloaded 287 times
Driving Log1 7-11-23-shortened no drive from 4286812-262989021.csv
(22.73 MiB) Downloaded 340 times
086-with drive.csv
(228.33 KiB) Downloaded 302 times
086-no drive.csv
(246.52 KiB) Downloaded 314 times
32a-with drive.csv
(66.75 KiB) Downloaded 312 times
32a-no drive.csv
(57.15 KiB) Downloaded 313 times
11d-with drive.csv
(91.4 KiB) Downloaded 298 times
11d-no drive.csv
(115.72 KiB) Downloaded 299 times
09f-with drive.csv
(171.83 KiB) Downloaded 310 times
09f-no drive.csv
(158.46 KiB) Downloaded 326 times
5fc and 6c0-with drive.csv
(79.06 KiB) Downloaded 326 times
5fc and 6c0-no drive.csv
(58.46 KiB) Downloaded 296 times
Jacobsmess
Posts: 700
Joined: Thu Mar 02, 2023 1:30 pm
Location: Uk
Has thanked: 362 times
Been thanked: 103 times

Re: Reverse engineering the MQB Electric steering rack

Post by Jacobsmess »

So I've had a little more time to mess with this.
I'm flying by the seat of my pants as I go here so may be making hard work of what you all would find pretty easy but playing the filtered CAN log back at the rack for 0FD EPS_21 I get assist and speed values showing on ODIS.
I played a log whilst taking a bunch of photos and then laid it out in a graph, removing outlier values of assist (likelihood due to extra torque from steering) and the averageing the results I've got an idea of the levels of assist at different speeds...
image.png
Following on from this, looking at EPS_21 I can see byte 2 starts at 211 and counts up to 223, so I guess that's a counter then that can be seen in green on this flow graph and the DBC ..
image.png

Code: Select all

BO_ 253 ESP_21: 8 Gateway_MQB
 [b]SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] ""  XXX
 SG_ COUNTER : 8|4@1+ (1,0) [0|15] ""  XXX[/b]
 SG_ BR_Eingriffsmoment : 12|10@1+ (1,-509) [-509|509] ""  XXX
 SG_ ESP_PLA_Bremseingriff : 22|1@1+ (1.0,0.0) [0.0|1] ""  XXX
 SG_ ESP_Diagnose : 23|1@1+ (1.0,0.0) [0.0|1] ""  XXX
 SG_ ESC_Reku_Freigabe : 24|1@1+ (1.0,0.0) [0.0|1] ""  XXX
 SG_ ESC_v_Signal_Qualifier_High_Low : 25|3@1+ (1.0,0.0) [0.0|7] ""  XXX
 SG_ ESP_Vorsteuerung : 28|1@1+ (1.0,0.0) [0.0|1] ""  XXX
 SG_ ESP_AWV3_Brems_aktiv : 29|1@1+ (1.0,0.0) [0.0|1] ""  XXX
 SG_ OBD_Schlechtweg : 30|1@1+ (1.0,0.0) [0.0|1] ""  XXX
 SG_ OBD_QBit_Schlechtweg : 31|1@1+ (1.0,0.0) [0.0|1] ""  XXX
[b] SG_ ESP_v_Signal : 32|16@1+ (0.01,0) [0.00|655.32] "Unit_KiloMeterPerHour"  XXX[/b]
 SG_ ASR_Tastung_passiv : 48|1@1+ (1.0,0.0) [0.0|1] ""  XXX
 SG_ ESP_Tastung_passiv : 49|1@1+ (1.0,0.0) [0.0|1] ""  XXX
 SG_ ESP_Systemstatus : 50|1@1+ (1.0,0.0) [0.0|1] ""  XXX
 SG_ ASR_Schalteingriff : 51|2@1+ (1.0,0.0) [0.0|3] ""  XXX
 SG_ ESP_Haltebestaetigung : 53|1@1+ (1.0,0.0) [0.0|1] ""  XXX
 SG_ ESP_MKB_Abbruch_Geschw : 54|1@1+ (1.0,0.0) [0.0|1] ""  XXX
 SG_ ESP_QBit_v_Signal : 55|1@1+ (1.0,0.0) [0.0|1] ""  XXX
 SG_ ABS_Bremsung : 56|1@1+ (1.0,0.0) [0.0|1] ""  XXX
 SG_ ASR_Anf : 57|1@1+ (1.0,0.0) [0.0|1] ""  XXX
 SG_ MSR_Anf : 58|1@1+ (1.0,0.0) [0.0|1] ""  XXX
 SG_ EBV_Eingriff : 59|1@1+ (1.0,0.0) [0.0|1] ""  XXX
 SG_ EDS_Eingriff : 60|1@1+ (1.0,0.0) [0.0|1] ""  XXX
 SG_ ESP_Eingriff : 61|1@1+ (1.0,0.0) [0.0|1] ""  XXX
 SG_ ESP_ASP : 62|1@1+ (1.0,0.0) [0.0|1] ""  XXX
 SG_ ESP_Anhaltevorgang_ACC_aktiv : 63|1@1+ (1.0,0.0) [0.0|1] ""  XXX
The ESP V Signal is noted in "KiloMeterPerHour" so thats likely my speed, starts at byte 5 (bit 32) and is 16 bits long if I am interpreting the DBC correctly...
But I'm uncertain how the data is then cofigured to the speed shown below..
image.png
from the raw data flow graph...
image.png
Jacobsmess
Posts: 700
Joined: Thu Mar 02, 2023 1:30 pm
Location: Uk
Has thanked: 362 times
Been thanked: 103 times

Re: Reverse engineering the MQB Electric steering rack

Post by Jacobsmess »

OK, so the vehicle speed is made up from byte 5 and byte 6 and is calculated by (b5 + b6*253)*0.01.
image.png
Jacobsmess
Posts: 700
Joined: Thu Mar 02, 2023 1:30 pm
Location: Uk
Has thanked: 362 times
Been thanked: 103 times

Re: Reverse engineering the MQB Electric steering rack

Post by Jacobsmess »

So I made a little progress last night after not having done anything on it in a while...
I asked Gemini (googles AI) to help with the checksum for the CAN ID 0X0FD EPS_21...
It managed pretty quickly to crack it and comparing it to the CAN Log I've got appears to be correct which is good news. I've also got it to generate some code (below), but I need to check it over... whilst learning C++ 😄....

Then I'm hoping to merge it into BigPies Canfilter code so I can get it to translate from my VW transporter CAN data to the newer MQB format to satisfy the rack.

I'll bench test it all first but given the rack goes to failsafe mode if it receives invalid data or looses connection I'm confident it should work OK...

Code: Select all

#include <stdint.h>

uint8_t calculateCRC8(const uint8_t *data, size_t length) {
    uint8_t crc = 0x00;
    uint8_t polynomial = 0x07;

    for (size_t i = 0; i < length; i++) {
        uint8_t dataByte = data[i];
        for (uint8_t j = 0; j < 8; j++) {
            uint8_t msb = (crc & 0x80) ? 1 : 0; // Check if MSB of CRC is 1
            crc <<= 1;                           // Shift CRC left by one bit
            if (msb ^ ((dataByte >> (7 - j)) & 0x01)) { // If MSB of CRC XOR current data bit is 1
                crc ^= polynomial;                 // XOR CRC with the polynomial
            }
            crc &= 0xFF; // Ensure CRC remains an 8-bit value
        }
    }
    return crc;
}

// Example usage:
void setup() {
    Serial.begin(115200);
    Serial.println("CRC-8 Calculation Example");

    // Example CAN data (excluding the checksum byte itself)
    uint8_t canData[] = {0xD4, 0x1F, 0x80, 0xB4, 0x29, 0x00, 0x00};
    size_t dataLength = sizeof(canData) / sizeof(canData[0]);

    uint8_t calculatedChecksum = calculateCRC8(canData, dataLength);

    Serial.print("Data: ");
    for (size_t i = 0; i < dataLength; i++) {
        Serial.print(canData[i], HEX);
        Serial.print(" ");
    }
    Serial.println();

    Serial.print("Calculated CRC-8 Checksum: 0x");
    Serial.println(calculatedChecksum, HEX);

    // For the 5th frame in your log, the expected checksum (D1) was 0xCB
    Serial.print("Expected Checksum (from log): 0xCB");
}

void loop() {
    // In your real-time application, you would read CAN data here
    delay(1000);
}
User avatar
uhi22
Posts: 1085
Joined: Mon Mar 14, 2022 3:20 pm
Location: Ingolstadt/Germany
Has thanked: 187 times
Been thanked: 604 times

Re: Reverse engineering the MQB Electric steering rack

Post by uhi22 »

The shown code does not include the alive counter (which should increment with each message), and also does not contain the table with magic bytes. So it cannot produce valid E2E protected messages.
Jacobsmess
Posts: 700
Joined: Thu Mar 02, 2023 1:30 pm
Location: Uk
Has thanked: 362 times
Been thanked: 103 times

Re: Reverse engineering the MQB Electric steering rack

Post by Jacobsmess »

Thanks for looking over it.

If I'm understanding you, the code only calculates the 1st bit. This is the checksum, the counter is a latter bit (I cannot remember which). I gave the AI some data with the first checksum bit removed and asked it calculate the checksum based on the provided data and the checksum bit matched. But I may be misunderstanding how this all works by the sound of it.
User avatar
uhi22
Posts: 1085
Joined: Mon Mar 14, 2022 3:20 pm
Location: Ingolstadt/Germany
Has thanked: 187 times
Been thanked: 604 times

Re: Reverse engineering the MQB Electric steering rack

Post by uhi22 »

The snippet of the DBC above shows that the checksum is at bit 0 and has 8 bits, and the counter starts at bit 8 (means: in the second byte), and has four bits.
The CRC algorithm may be similar to one of the profiles described in the AUTOSAR E2E specification. I described a similar method which Tesla uses, https://github.com/uhi22/tesla-crc

If we have a lot of trace data of an original car, it is possible to find out the missing pieces: the 16-byte table with magic bytes and the CRC polynom.
Jacobsmess
Posts: 700
Joined: Thu Mar 02, 2023 1:30 pm
Location: Uk
Has thanked: 362 times
Been thanked: 103 times

Re: Reverse engineering the MQB Electric steering rack

Post by Jacobsmess »

I've got 2 can logs from a VW Mk7 Golf, both are quite long so theres plenty of data there of thats what you mean by trace data.
User avatar
uhi22
Posts: 1085
Joined: Mon Mar 14, 2022 3:20 pm
Location: Ingolstadt/Germany
Has thanked: 187 times
Been thanked: 604 times

Re: Reverse engineering the MQB Electric steering rack

Post by uhi22 »

Ahh, I just see the attached logs above, I will have a look into them in the next days.
If you have longer logs you could extract the lines with the esp_21 message (eg using linux grep command) and provide the extract.
Jacobsmess
Posts: 700
Joined: Thu Mar 02, 2023 1:30 pm
Location: Uk
Has thanked: 362 times
Been thanked: 103 times

Re: Reverse engineering the MQB Electric steering rack

Post by Jacobsmess »

Yes I can do this
Jacobsmess
Posts: 700
Joined: Thu Mar 02, 2023 1:30 pm
Location: Uk
Has thanked: 362 times
Been thanked: 103 times

Re: Reverse engineering the MQB Electric steering rack

Post by Jacobsmess »

I've filtered the log files for 0x0FD only and attached, thanks again for the help
Attachments
Driving Log1 7-17-23-0fd.csv
(2.28 MiB) Downloaded 306 times
Driving Log1 7-11-23-0fd.csv
(2.69 MiB) Downloaded 297 times
User avatar
uhi22
Posts: 1085
Joined: Mon Mar 14, 2022 3:20 pm
Location: Ingolstadt/Germany
Has thanked: 187 times
Been thanked: 604 times

Re: Reverse engineering the MQB Electric steering rack

Post by uhi22 »

Good news: The CRC algorithm is the same as used in Tesla. Created a program which reads the above two log files, calculates the CRC for each message and compares it with the transmitted CRC. Result: All pass. CRC ok: 91622, CRC fail: 0
Github: https://github.com/uhi22/tesla-crc/tree/main/vag
Jacobsmess
Posts: 700
Joined: Thu Mar 02, 2023 1:30 pm
Location: Uk
Has thanked: 362 times
Been thanked: 103 times

Re: Reverse engineering the MQB Electric steering rack

Post by Jacobsmess »

That's great thanks so much for the help!
Post Reply