Arduino sketch to send diagnostic frames to PSA cars
The serial console is used to send raw diagnostic frames, start it using 115200 baud rate. The sketch is meant to be used with line feed (LF) - new line - and without carriage return (CR) for each command.
You have to choose the ECU you want to communicate with by inputing its diagnostic frame IDs in hexadecimal:
>CAN_EMIT_ID:CAN_RECV_ID
Telematic unit (UDS) access example:
>764:664
To access LIN ECUs (LIN over UDS) you must input diagnostic frame IDs in hexadecimal as well as ECU code
DGT7CFF LVDS Screen (LIN) access example:
>736:716
L47
Check out ECU_LIST.md inside the repo for other ECUs IDs pair
Once you are on the chosen ECU you can unlock it easily using this shortcut:
:UNLOCK_KEY:UNLOCK_SERVICE:DIAG_SESSION_ID
UNLOCK_SERVICE (HEX) | Protocol | Detail | Equivalent command |
---|---|---|---|
01 | UDS | Download | 2701 |
03 | UDS | Coding | 2703 |
83 | KWP | Download/Coding | 2783 |
DIAG_SESSION_ID (HEX) | Protocol | Detail | Equivalent command |
---|---|---|---|
02 | UDS | Download | 1002 |
03 | UDS | Coding | 1003 |
C0 | KWP | Download/Coding | 10C0 |
NAC Telematic unit (UDS) unlock for coding example:
:D91C:03:03
AMPLI_AUDIO Amplifier unit (KWP) unlock for coding example:
:A7D8:83:C0
Check out ECU_KEYS.md for other ECUs keys
Command | Description |
---|---|
3E00 | Keep-Alive session |
190209 | List of current faults |
14FFFFFF | Clear faults |
37 | Flash autocontrol (Unit must be unlocked first) |
1001 | End of communication |
1002 | Open Download session |
1003 | Open Diagnostic session |
1103 | Reboot |
2701 | Unlocking service for download (Diagnostic session must be enabled first) - SEED |
2703 | Unlocking service for configuration (Diagnostic session must be enabled first) - SEED |
2702XXXXXXXX | Unlocking response for download - XXXXXXXX = KEY - Must be given within 5 seconds after seed generation |
2704XXXXXXXX | Unlocking response for configuration - XXXXXXXX = KEY - Must be given within 5 seconds after seed generation |
22XXXX | Read Zone XXXX (2 bytes) |
2EXXXXYYYYYYYYYYYY | Write Zone XXXX with data YYYYYYYYYYYY (Unit must be unlocked first) |
3101FF0081F05A | Empty flash memory for .cal upload (Unit must be unlocked first) - F05A = Tool Signature |
3101FF0082F05A | Empty flash memory for .ulp upload (Unit must be unlocked first) - F05A = Tool Signature - WARNING: If you don't upload a valid file your device will be temporarily bricked |
3103FF00 | Empty flash memory (Unit must be unlocked first) |
3481110000 | Prepare flash writing for .cal upload (Unit must be unlocked first) |
3482110000 | Prepare flash writing for .ulp upload (Unit must be unlocked first) |
348244XXXXXXXXYYYYYYYY | Prepare flash writing for .ulp upload in Full UDS mode (Unit must be unlocked first) - XXXXXXXX = Block Address, YYYYYYYY = Block Size |
3101FF04 | Empty ZI Zone (Unit must be unlocked first) |
3103FF04 | Empty ZI Zone (Unit must be unlocked first) |
3483110000 | Prepare ZI zone writing (Unit must be unlocked first) |
Command | Description |
---|---|
3E | Keep-Alive session |
17FF00 | List of current faults |
14FF00 | Clear faults |
1081 | End of communication |
10C0 | Open Diagnostic session |
31A800 | Reboot |
31A801 | Reboot 2 |
2781 | Unlocking service for download (Diagnostic session must be enabled first) - SEED |
2783 | Unlocking service for configuration (Diagnostic session must be enabled first) - SEED |
2782XXXXXXXX | Unlocking response for download - XXXXXXXX = KEY - Must be given within 5 seconds after seed generation |
2784XXXXXXXX | Unlocking response for configuration - XXXXXXXX = KEY - Must be given within 5 seconds after seed generation |
21XX | Read Zone XX (1 byte) |
3BXXYYYYYYYYYYYY | Write Zone XX with data YYYYYYYYYYYY (Unit must be unlocked first) |
318181F05A | Empty flash memory for .cal upload (Unit must be unlocked first) - F05A = Tool Signature |
318101 | Empty flash memory for .cal upload (Unit must be unlocked first) |
348100000D07 | Prepare flash writing for .cal upload (Unit must be unlocked first) |
Command | Description |
---|---|
3E | Keep-Alive session |
17FF00 | List of current faults |
14FF00 | Clear faults |
82 | End of communication |
81 | Open Diagnostic session |
2781 | Unlocking service for download (Diagnostic session must be enabled first) - SEED |
2783 | Unlocking service for configuration (Diagnostic session must be enabled first) - SEED |
2782XXXXXXXX | Unlocking response for download - XXXXXXXX = KEY - Must be given within 5 seconds after seed generation |
2784XXXXXXXX | Unlocking response for configuration - XXXXXXXX = KEY - Must be given within 5 seconds after seed generation |
21XX | Read Zone XX (1 byte) |
34XXYYYYYYYYYYYY | Write Zone XX with data YYYYYYYYYYYY (Unit must be unlocked first) |
Answer | Description |
---|---|
7E00 | Keep-Alive reply |
54 | Faults cleared |
7103FF0001 | Flash erasing in progress |
7103FF0003 | Flash not erased: error |
7101FF0401 | ZI erased successfully |
7103FF0402 | ZI erasing in progress |
7103FF0403 | ZI not erased: error |
77 | Flash autocontrol OK |
5001XXXXXXXX | Communication closed |
5002XXXXXXXX | Download session opened |
5003XXXXXXXX | Diagnostic session opened |
5103 | Reboot OK |
62XXXXYYYYYYYYYYYY | Successfull read of Zone XXXX - YYYYYYYYYYYY = DATA |
6701XXXXXXXX | Seed generated for download - XXXXXXXX = SEED |
6703XXXXXXXX | Seed generated for configuration - XXXXXXXX = SEED |
6702 | Unlocked successfully for download - Unit will be locked again if no command is issued within 5 seconds |
6704 | Unlocked successfully for configuration - Unit will be locked again if no command is issued within 5 seconds |
6EXXXX | Successfull Configuration Write of Zone XXXX |
741000 | Download Writing ready |
74200802 | Download Writing ready in Full UDS mode |
76XX02 | Download frame XX injected with success |
76XX0A | Invalid checksum on download frame XX |
Answer | Description |
---|---|
7F3478 | Download Writing in progress |
7F3778 | Flash autocontrol in progress |
7FXX78 | XX = Service - In progress |
7F2231 | Configuration Read - Request out of range |
7F2233 | Configuration Read - Security Access Denied |
7F2712 | Unlocking - Subfunction not supported |
7F2722 | Unlocking - Conditions not correct |
7F2724 | Unlocking - Request Sequence Error |
7F2736 | Unlocking - Exceeded number of attempts |
7F2737 | Unlocking - Required time delay not expired |
7F2713 | Unlocking - Invalid SEED Answer (KEY) |
7F2E78 | Configuration Write in progress |
7F2E72 | Configuration Write - General Programming Failure |
7F2E13 | Configuration Write - Invalid Zone data |
7F2E7E | Configuration Write - Unit is locked |
7F2E31 | Configuration Write - Request out of range |
7F2EYY | Failed Configuration Write - YY = Response code |
7F2E31 | Request out of range |
7F22YY | Failed Configuration Read - YY = Response code |
7FXXYY | Error - XX = Service / YY = Response code |
Answer | Description |
---|---|
7E | Keep-Alive reply |
5081 | Communication closed |
50C0 | Diagnostic session opened |
71A801 | Reboot |
71A802 | Reboot 2 |
57XXYYYYZZ | XX = Number of DTC, YYYY = DTC code, ZZ = DTC data |
61XXYYYYYYYYYYYY | Successfull read of Zone XX - YYYYYYYYYYYY = DATA |
6781XXXXXXXX | Seed generated for download - XXXXXXXX = SEED |
6783XXXXXXXX | Seed generated for configuration - XXXXXXXX = SEED |
6782 | Unlocked successfully for download - Unit will be locked again if no command is issued within 5 seconds |
6784 | Unlocked successfully for configuration - Unit will be locked again if no command is issued within 5 seconds |
Answer | Description |
---|---|
7E | Keep-Alive reply |
C2 | Communication closed |
C1XXXX | Diagnostic session opened |
57XXYYYYZZ | XX = Number of DTC, YYYY = DTC code, ZZ = DTC data |
61XXYYYYYYYYYYYY | Successfull read of Zone XX - YYYYYYYYYYYY = DATA |
6781XXXXXXXX | Seed generated for download - XXXXXXXX = SEED |
6783XXXXXXXX | Seed generated for configuration - XXXXXXXX = SEED |
6782 | Unlocked successfully for download - Unit will be locked again if no command is issued within 5 seconds |
6784 | Unlocked successfully for configuration - Unit will be locked again if no command is issued within 5 seconds |
Answer | Description | Possible reasons |
---|---|---|
7F0000 | Invalid Length | Space at the end of the command ? Carriage return (CR) enabled ? |
7F3E03 | ECU Connection lost | No resistor ? CAN-BUS wires bad ? |
None | CS_PIN_CAN0 correctly setup ? CAN_FREQ correctly setup ? |
After each configuration writing you must write 2901 zone for the so called "Secured Traceability" to avoid B1003 DTC error in the ECU
Command | Zone | Site | Signature | Day | Month | Year |
---|---|---|---|---|---|---|
2E | 2901 | FD | 000000 | 01 | 01 | 01 |
Write | Traceability | Aftersales | Factory | 01 | January | 2001 |
Quick & dirty command that works everytime:
2E2901FD000000010101
Each time you write the traceability zone a counter in increased inside C000 zone, this zone can't be rewrited
22C000
Command | Zone | Number of secured writings | Number of non-secured writings |
---|---|---|---|
62 | C000 | 2A | 00 |
Answer | Traceability | 42 | 0 |
After each configuration writing you must write A0 zone for the so called "Secured Traceability" to avoid F303 DTC error in the ECU
Command | Zone | Site | Signature | Day | Month | Year | Number of secured writings | Number of non-secured writings | |
---|---|---|---|---|---|---|---|---|---|
3B | A0 | FF | FD | 000000 | 01 | 01 | 01 | 2A | 00 |
Write | Traceability | Aftersales | Factory | 01 | January | 2001 | 42 | 0 |
Number of secured writings "should" be increased after each writing
Quick & dirty command that works everytime:
3BA0FFFD0000000101010000
Algorithm can be found here with some example source code
CAN-BUS is limited to 8 bytes per frame, to send larger data PSA automotive industry via ISO 15765-2 chose a simple algorythm to truncate the data into multiple parts
Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 | Byte 8 |
---|---|---|---|---|---|---|---|
Full Data Length | Data[0] | Data[1] | Data[2] | Data[3] | Data[4] | Data[5] | Data[6] |
Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 | Byte 8 |
---|---|---|---|---|---|---|---|
0x10 | Full Data Length | Data[0] | Data[1] | Data[2] | Data[3] | Data[4] | Data[5] |
Byte 1 | Byte 2 | Byte 3 |
---|---|---|
0x30 | 0x00 | Delay between consecutive frames in ms |
ID starting at 0x21 and increasing by 1 for every extra frame needed, after 0x2F reverting back to 0x20
Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 | Byte 8 |
---|---|---|---|---|---|---|---|
0x21 | Data[6] | Data[7] | Data[8] | Data[9] | Data[10] | Data[11] | Data[12] |
Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 | Byte 8 |
---|---|---|---|---|---|---|---|
0x22 | Data[13] | Data[14] | Data[15] | Data[16] | Data[17] | Data[18] | Data[19] |
Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 | Byte 8 |
---|---|---|---|---|---|---|---|
Full Data Length | Data[0] | Data[1] | Data[2] | Data[3] | Data[4] | Data[5] | Data[6] |
Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 | Byte 8 |
---|---|---|---|---|---|---|---|
0x10 | Full Data Length | Data[0] | Data[1] | Data[2] | Data[3] | Data[4] | Data[5] |
Byte 1 | Byte 2 | Byte 3 |
---|---|---|
0x30 | 0x00 | Delay between consecutive frames in ms |
ID starting at 0x21 and increasing by 1 for every extra frame needed, after 0x2F reverting back to 0x20
Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 | Byte 8 |
---|---|---|---|---|---|---|---|
0x21 | Data[6] | Data[7] | Data[8] | Data[9] | Data[10] | Data[11] | Data[12] |
Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 | Byte 8 |
---|---|---|---|---|---|---|---|
0x22 | Data[13] | Data[14] | Data[15] | Data[16] | Data[17] | Data[18] | Data[19] |
Received frames could be out-of-order, ID must be used to append parts at the correct position into the final data whose size is known
Type of file : Motorola S-record - https://en.wikipedia.org/wiki/SREC_(file_format)
1h = 1 HEX Byte or 2 characters in the .cal/.ulp file
TYPE | LENGTH | ADDRESS | LENGTH2 | ZONE | DATA | CHECKSUM | CHECKSUM2 |
---|---|---|---|---|---|---|---|
1h | 1h | 3h | 2h | 2h | Variable Length | 2h | 1h |
TYPE | LENGTH | ADDRESS | LENGTH2 | DATA | CHECKSUM | CHECKSUM2 |
---|---|---|---|---|---|---|
1h | 1h | 4h | 2h | Variable Length | 2h | 1h |
TYPE | LENGTH | NOT_USED | FAMILY_MUX_CODE | ISO_LINE | INTERBYTE_TX | INTERBYTE_RX | INTER_TXRX | INTER_RXTX | CAL_TYPE | LOGICAL_MARK | K_LINE_MANAGEMENT | CHECKSUM2 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
1h | 1h | 2h | 1h | 1h | 1h | 1h | 1h | 1h | 1h | 1h | 2h | 1h |
TYPE | LENGTH | NOT_USED | FLASH_SIGNATURE | UNLOCK_KEY | SUPPLIER | SYSTEM | APPLICATION | SOFTWARE_VERSION | SOFTWARE_EDITION | CAL_NUMBER | CHECKSUM2 |
---|---|---|---|---|---|---|---|---|---|---|---|
1h | 1h | 2h | 2h | 2h | 1h | 1h | 1h | 1h | 2h | 3h | 1h |
TYPE | LENGTH | NB_FRAMES | CHECKSUM2 |
---|---|---|---|
1h | 1h | Variable Length | 1h |
TYPE | LENGTH | ADDRESS | CHECKSUM2 |
---|---|---|---|
1h | 1h | Optional | 1h |
TYPE | LENGTH | ADDRESS | CHECKSUM2 |
---|---|---|---|
1h | 1h | Optional | 1h |
TYPE | LENGTH | ADDRESS | CHECKSUM2 |
---|---|---|---|
1h | 1h | Optional | 1h |
Line Part | Line Detail |
---|---|
TYPE | S0 = Hardware info / S1 = ZI Zone / S2 / S3 / S8 |
LENGTH | Hex Length of ADDRESS+ZONE+DATA+CHECKSUM+CHECKSUM2 |
ADDRESS | 16bits / 24bits / 32bits |
LENGTH2 | Hex Length of ZONE+DATA+CHECKSUM |
ZONE | |
DATA | |
CHECKSUM | CRC-16/X-25(DATA) with this order CRC[1] CRC[0] |
CHECKSUM2 | CRC-8/2s_complement(ADDRESS+ZONE+DATA+CHECKSUM) - 1 |
FAMILY_MUX_CODE | Family Code |
ISO_LINE | 00h: CAN / 01h: LIN / 05h: ISO 5 / 08h: ISO 8 |
INTERBYTE_TX | Delay between bytes sending (0.1ms step) |
INTERBYTE_RX | Delay between bytes receiving (0.1ms step) |
INTER_TXRX | Delay between sent and received frames (1ms step) |
INTER_RXTX | Delay between received and sent frames (1ms step) |
CAL_TYPE | 81h: .cal / 82h: .ulp / 92h: .ulp new gen |
LOGICAL_MARK | |
K_LINE_MANAGEMENT | 0000h: yes / 0FXXh: no, timeout of XXs |
FLASH_SIGNATURE | Flash Signature |
UNLOCK_KEY | ECU Unlock key |
SUPPLIER | Supplier ID |
SYSTEM | |
APPLICATION | |
SOFTWARE_VERSION | |
SOFTWARE_EDITION | FF.XX |
CAL_NUMBER | 96 XXXXXX 80 |
Checksums have to be computed by converting HEXADECIMAL to BINARY
This sketch also provides a way to dump Diagbox frames (read & write) very easily, it is merging split CAN-BUS frames together to have a clean and "human readable" output. Just enable it this way in the source code:
bool Dump = true;
You can also use the serial console typing:
X
To revert into normal mode:
N
You can build yourself that kind of cable using an OBD2 Extender cable to use both the Arduino and PSA Interface:
PIN | Description |
---|---|
3 | CAN-BUS Diagnostic High |
8 | CAN-BUS Diagnostic Low |
Original PINOUT is used for DoIP (Diagnostic over IP)
PIN | Description |
---|---|
6 | CAN-BUS Diagnostic High |
14 | CAN-BUS Diagnostic Low |
Reminder: In Dump mode the termination resistor should not be activated