lunes, 17 de octubre de 2011

FIS: Seat Leon Cupra

.

 


The info sent by Eduard about controlling the messages of his Seat Leon's FIS (Driver Information System) detailed below.... enjoy it!


NOTE, i do not take any responsibility on consequences of below. Be careful when sending commands on the can bus!

Introduction

For some time i have been looking for a tool that can help me monitor the can bus network of my Seat Leon Cupra 2009. I had already played around with the ELM 327 on the OBD II port but got bored as it limits you to reading predefined PID´s. I wanted to know more about the ongoing car communication on the can bus so i could read values and present them on the instrument cluster in the car. Yes i know, i can buy products that already do so but that is too easy and would not give me the joy of understanding the car communication. Luckily i found the SECUduino blog page that could present me with a can bus shield and Arduino library enabling me to start my project easily.



Step 1 - Connection 

So first of you need to understand what combination of messages that will make your instrument cluster LCD display text. To do so i started of by connecting the SECUduino/arduino to the infotainment can bus as it is located in a convenient accessible spot under the passenger seat in my car. I simply connected to the can bus cables that run to the OEM bluetooth, see pictures below
The black box contains an arduino UNO and the SECUduino shield.




Step 2 – Monitoring can bus

I started off by monitoring all communication on the can bus that I had connected to in BYTE format. I assumed that the RDS radio information displayed in the audio menu of the instrument cluster had to be communicated on the can bus from the OEM radio unit. Below code gave me the findings I was looking for when changing between different preset radio stations with RDS information on the OEM radio.

#include <CAN.h>

void setup(){
  Serial.begin(115200); 
  CAN.begin(100);  //infotainment can bus speed  
}

void loop(){
  

  if (CAN.CheckNew()) {
    
    CAN.ReadFromDevice(&CAN_RxMsg); 
    
      //Print message via Serial Port
      Serial.print(CAN_RxMsg.id,HEX);
      Serial.print(";");
      Serial.print(CAN_RxMsg.data[0],BYTE); 
      Serial.print(";");
      Serial.print(CAN_RxMsg.data[1], BYTE); 
      Serial.print(";");
      Serial.print(CAN_RxMsg.data[2], BYTE); 
      Serial.print(";");
      Serial.print(CAN_RxMsg.data[3], BYTE); 
      Serial.print(";");
      Serial.print(CAN_RxMsg.data[4], BYTE); 
      Serial.print(";");
      Serial.print(CAN_RxMsg.data[5], BYTE); 
      Serial.print(";");
      Serial.print(CAN_RxMsg.data[6], BYTE); 
      Serial.print(";");
      Serial.println(CAN_RxMsg.data[7], BYTE); 
  }
}



Message ID 680 & 681 where the ones I was looking for, this should be the same for all VAG cars with a OEM standard stereo. Changed the serial print state from BYTE back to HEX and added filtering so I would only see 680 & 681 ID messages. See below update of the void loop to do so.



if (CAN.CheckNew()) {
    
    CAN.ReadFromDevice(&CAN_RxMsg); 
    
    if ( (CAN_RxMsg.id=0x680) || (CAN_RxMsg.id=0x681) ) {

      //Print message via Serial Port
      Serial.print(CAN_RxMsg.id,HEX);
      Serial.print(";");
      Serial.print(CAN_RxMsg.data[0],HEX); 
      Serial.print(";");
      Serial.print(CAN_RxMsg.data[1],HEX); 
      Serial.print(";");
      Serial.print(CAN_RxMsg.data[2],HEX); 
      Serial.print(";");
      Serial.print(CAN_RxMsg.data[3],HEX); 
      Serial.print(";");
      Serial.print(CAN_RxMsg.data[4],HEX); 
      Serial.print(";");
      Serial.print(CAN_RxMsg.data[5],HEX); 
      Serial.print(";");
      Serial.print(CAN_RxMsg.data[6],HEX); 
      Serial.print(";");
      Serial.println(CAN_RxMsg.data[7],HEX); 
    }
}




Step 3 – Understanding message ID 680

First we need to sort out the difference between the 680 message ID and the 681 message ID.
680 – Used by the OEM radio to forward text to the instrument cluster
681 – Used by the Instrument cluster to reply the radio OEM



Above communication record is the result of me selecting the preset radio station called POP FM on my OEM radio unit. Note that when you attempt to record 680 and 681 you need to close all doors and set the instrument cluster in the AUDIO mode, otherwise this data will not appear on the can bus. Try this in the CD mode, changing tracks generates similar 680/681 message id activity. Now, above nice colored example took me some time to understand and yet I am not clear on what all hexadecimal bytes do. The message contains two text messages to the instrument cluster, first the FM preset channel station number and then the radio RDS station information.
The green and blue rows is data that keeps on looping, D0 bytes are A1 for message 681 and A3 for message ID 680. Whenever text messages are communicated on the can bus the D0 byte for the message 680 and 681 will change to other then A3 or A1.

I focused on the second part that sends the radio station RDS information. Started of by sending the same sequence but no luck, on occasions it just made my Audio menu disappear from the instrument cluster and then get back shortly. Some more testing in all type of strange ways finally gave me the result I wanted. =)



If you look at the sheet I provide above you can see that the second nibble of the D0 (pink cells) byte keeps changing. It does so from 0 to F (0-15) and then back to 0 again for the next cycle. This sequence enables the instrument cluster to keep track of message order I assume. Note, there are two sequences (dark and light pink cells), the last value of the sequence will be used for next attempt to display something in the instrument cluster. If the pink sequence is not in order when you try to write to the instrument cluster you cannot display any text.

Step 4 – Arduino code

This work is in progress, I am optimizing my code. Below code gives you an example of how I displayed “Eduard” on the instrument cluster lcd. It is important to know what the last used dark pink and light pink sequence nibbles are. I used the pink sequences from above example to give you a better understanding how to do it, compare on your own. Trying to display something in the instrument cluster will be hard if you have tuned in a radio channel that keeps on sending RDS information at the same time. Either you manually set the frequency of the OEM radio to something that is out of a existing station reach or use the CD mode with no disc in the player. Use the monitor code I posted above and select CD or radio mode, record the sequences and use to populate below code. Do not push any buttons in between as it will change the sequences.




#include <CAN.h>



void setup() {
  
  CAN.begin(100);
  Serial.begin(115200);
  
  CAN_TxMsg.id=0x680;     
  CAN_TxMsg.header.rtr=0;
  CAN_TxMsg.header.length=8;

}



void loop(){
  
  // 680;2C;9;0;60;9;0;0;0
  CAN_TxMsg.data[0]=0x2C;
  CAN_TxMsg.data[1]=0x09;  
  CAN_TxMsg.data[2]=0x00; 
  CAN_TxMsg.data[3]=0x60;
  CAN_TxMsg.data[4]=0x09;
  CAN_TxMsg.data[5]=0x00;
  CAN_TxMsg.data[6]=0x00;
  CAN_TxMsg.data[7]=0x00;
  CAN.send(&CAN_TxMsg);
  delay(5);
  
  // 680;2D;14;0;6E;0;37;0;61  
  CAN_TxMsg.data[0]=0x2D;
  CAN_TxMsg.data[1]=0x14;  
  CAN_TxMsg.data[2]=0x00; 
  CAN_TxMsg.data[3]=0x6E;
  CAN_TxMsg.data[4]=0x00;
  CAN_TxMsg.data[5]=0x37;
  CAN_TxMsg.data[6]=0x00;
  CAN_TxMsg.data[7]=0x61;
  CAN.send(&CAN_TxMsg);
  delay(5);
  
  // 680;2E;C;10;0;37;0;23;0
  CAN_TxMsg.data[0]=0x2E;
  CAN_TxMsg.data[1]=0x0C;  
  CAN_TxMsg.data[2]=0x10; 
  CAN_TxMsg.data[3]=0x00;
  CAN_TxMsg.data[4]=0x37;
  CAN_TxMsg.data[5]=0x00;
  CAN_TxMsg.data[6]=0x23;
  CAN_TxMsg.data[7]=0x00;
  CAN.send(&CAN_TxMsg);
  delay(5);
  
  // 680;1F;45;44;55;41;52;44;8
  CAN_TxMsg.data[0]=0x1F;
  CAN_TxMsg.data[1]=0x45;  
  CAN_TxMsg.data[2]=0x44; 
  CAN_TxMsg.data[3]=0x55;
  CAN_TxMsg.data[4]=0x41;
  CAN_TxMsg.data[5]=0x52;
  CAN_TxMsg.data[6]=0x44;
  CAN_TxMsg.data[7]=0x08;
  CAN.send(&CAN_TxMsg);
  delay(5);
  
  // 680;B7;E0;E0;0;0;2B;40;0  
  CAN_TxMsg.data[0]=0xB7;
  CAN_TxMsg.data[1]=0xE0;  
  CAN_TxMsg.data[2]=0xE0; 
  CAN_TxMsg.data[3]=0x00;
  CAN_TxMsg.data[4]=0x00;
  CAN_TxMsg.data[5]=0x2B;
  CAN_TxMsg.data[6]=0x40;
  CAN_TxMsg.data[7]=0x00;
  CAN.send(&CAN_TxMsg);
  delay(5);
  
  
  delay(999999); //no need to print same message again
    
}









More coding examples and explanations to come!




BY: Eduard Popov

3 comentarios:

Anónimo dijo...

I am waiting on more

jmds dijo...

gran trabajo, gracias por publicarlo

k dijo...

Do you have idea if you send the wrong (right) command you can fire the airbags.

I am asking this because hacking the CANbus implies lots of trial and error.

Thanks

Publicar un comentario