Forum Rule: Always post complete source code & details to reproduce any issue!
Page 1 of 3 1 2 3 LastLast
Results 1 to 25 of 75

Thread: Reading data from CAN bus volkswagen

  1. #1
    Junior Member
    Join Date
    Sep 2020
    Posts
    4

    Reading data from CAN bus volkswagen

    Hello, I am new to microcontroller programming. But I really want to create an additional monitor with information output to the car (Volkswagen Jetta 6). I have Teensy 4.0 and have already been able to connect a 240x240 display. But here's how to get information from the CAN bus of a car - I don't have enough knowledge. Perhaps someone was engaged in a similar task, I will be grateful for any advice and hint. Sincerely.

  2. #2
    Senior Member
    Join Date
    Oct 2019
    Posts
    354
    I have experience with the MQB platform, but as your Jetta is on the PQ35 platform, I can't provide you with my request response sample as it's not the same.
    What kind of data do you want to display on your tft?

    What I suggest you do is purchase a VCDS HEX-CAN V2 from Aliexpress and do some can sniffing using the T4 hooked up to the OBD port with a Y splitter (don't forget to use a CAN transceiver between the T4 and the OBD port)
    Set VCDS to poll a single parameter and catch the messages with the Teensy vis Serial monitor to see what a request looks like and what a response looks like.
    Here is what it looks like:
    Click image for larger version. 

Name:	IMG_5070.jpg 
Views:	423 
Size:	365.1 KB 
ID:	21720

    But you really need to learn how the CAN bus application layer works, and how UDS works.
    Here are some links that will help you:
    https://en.wikipedia.org/wiki/Unifie...ostic_Services
    https://en.wikipedia.org/wiki/OBD-II_PIDs

    I built a data monitor that does exactly what you are looking for


    I can try help you out more once you've gotten the basic knowledge to pull the data from the car.

  3. #3
    Junior Member
    Join Date
    Sep 2020
    Posts
    4
    Rezo, you have a good project and it looks like this is exactly what I need! I want to display coolant temperature, transmission oil temperature and possibly a few more parameters. My dashboard doesn't display this information
    The principle of working with a CAN bus through a getway is roughly clear to me, a request for a certain parameter is made and a response is obtained with data on it.
    But I still can't find examples of the implementation of reading for T4.
    Which transceiver should you use?
    How to connect it to T4 and how to programmatically receive data?
    I would be very grateful to you for such information and an example of your implementation of the code and connecting the transceiver to T4 and to the CAN bus. As for the difference in car platforms (on my Jetta PQ25, unfortunately), I think there should be no problems. PIDs must be the same.

  4. #4
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    4,078
    standard pids are fine, but not OEM specific. each car and year can be different. Some data is already in stream while you have the option to request them. But not all requested pids are available, and require reverse engineering the stream or using UDS, which are manufacturer specific. Breakout boards are available for T4, you'll likely use 2 busses anyways (comfort bus and high speed bus) so you may look into those since theyre 12v ready to plug and play. Rezo may be using different hardware, but they all should work the same. Some transceivers have been shown to not be compatible though

  5. #5
    Senior Member
    Join Date
    Oct 2019
    Posts
    354
    As Tony mentioned, UDS is not easy to understand and it's not documented anywhere but it's got more enhanced data than standard OBD2 PIDs - that's why can sniffing individual PID's is the best option IMO to find what you are looking for over UDS.

    This is my setup to do CAN sniffing:
    Click image for larger version. 

Name:	canSniff_setup.jpg 
Views:	233 
Size:	86.4 KB 
ID:	21730
    1. HEX V2 used with VCDS to send requests and see realtime data
    2. Teensy 3.2 + TI sn65hvd230 CAN transceiver placed in an OBD2 connector
    3. Y splitter that connects to both devices to the cars OBD port

    I use a simple sketch on the Teensy that print's every CAN frame it see's (from either end: car or VCDS) onto the Arduino serial monitor. I then log each frame (request/response) and value.

    I must note, on the PQ25 you most probably have a Bosch MED ECU and it's not as fast as the MQBs Continental Simos, so request poll speed might have to be lower in your case.
    I know for a fact that the MQB UDS requests don't work with the PQ35 platform as I have plugged my device into a VW Scirocco and it failed to return any positive UDS responses.


    For the Teensy 4 I used the TI sn65hvd230 CAN transceiver on CAN1 (pins 22 and 23).
    Here is a simple sketch that will request engine coolant temp and save it into a variable and print it out in your serial monitor:
    Code:
    #include <FlexCAN_T4.h>
    FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> Can0;
    
    int engineCoolantTemp = 0; // Save the data here
    
    void setup(){
      while (!Serial && millis() < 5000);
      Serial.begin(115200);
      Can0.begin();
      Can0.setBaudRate(500000);
      Can0.setMBFilter(REJECT_ALL);
      Can0.setMBFilter(MB1, 0x7E8);
      Can0.enableMBInterrupt(MB1);
      Can0.onReceive(canSniff);
    
    }
    
    const long loopDelay1 = 500; // Make a request every 500ms
    unsigned long timeNow1 = 0;
    void loop(){
      Can0.events();
      if (millis() > timeNow1 + loopDelay1)
        {
          timeNow1 = millis();
          canTx_OBD(); // Query data from CAN BUS via OBD
          //canTx_UDS(); // Query data from CAN BUS via UDS
    
        }
    }
    
    
    void canSniff (const CAN_message_t &msg){ // Global callback to catch any CAN frame coming in
      Serial.println(" ");
      Serial.print("MB: ");
      Serial.print(msg.mb);
      Serial.print("  ID: 0x");
      Serial.print(msg.id, HEX);
      Serial.print("  EXT: ");
      Serial.print(msg.flags.extended);
      Serial.print("  LEN: ");
      Serial.print(msg.len);
      Serial.print(" DATA: ");
      for (uint8_t i = 0; i < 8; i++)
        {
          Serial.print(msg.buf[i], HEX);
          Serial.print(" ");
        }
        if (msg.buf[1] == 0x01 && msg.buf[2] == 0x05){
            engineCoolantTemp = msg.buf[3] - 40;
            Serial.println(" ");
            Serial.printf("OBD: Engine Coolant Temp: %d c", engineCoolantTemp);
        }
    
        if (msg.buf[1] == 0x22 && msg.buf[2] == 0xf4 && msg.buf[3] == 0x05){
            engineCoolantTemp = msg.buf[4] - 40;
            Serial.println(" ");
            Serial.printf("UDS: Engine Coolant Temp: %d c", engineCoolantTemp);
        }
    
    }
    
    
    void canTx_OBD(){ // Request function to ask for Engine Coolant Temp via OBD request
      CAN_message_t msgTx, msgRx;
        msgTx.buf[0] = 0x02; 
        msgTx.buf[1] = 0x01;
        msgTx.buf[2] = 0x05;
        msgTx.buf[3] = 0; 
        msgTx.buf[4] = 0;
        msgTx.buf[5] = 0; 
        msgTx.buf[6] = 0;
        msgTx.buf[7] = 0;
        msgTx.len = 8;            // number of bytes in request
        msgTx.flags.extended = 0; // 11 bit header, not 29 bit
        msgTx.flags.remote = 0;
        msgTx.id = 0x7E0; // request header for OBD
        Can0.write(msgTx);
        Serial.println("canTx_OBD REQ sent"); 
      }
    
     void canTx_UDS(){ // Request function to ask for Engine Coolant Temp via UDS request
      CAN_message_t msgTx, msgRx;
        msgTx.buf[0] = 0x03; 
        msgTx.buf[1] = 0x22;
        msgTx.buf[2] = 0xf4;
        msgTx.buf[3] = 0x05; 
        msgTx.buf[4] = 0;
        msgTx.buf[5] = 0; 
        msgTx.buf[6] = 0; 
        msgTx.buf[7] = 0;
        msgTx.len = 8;            // number of bytes in request
        msgTx.flags.extended = 0; // 11 bit header, not 29 bit
        msgTx.flags.remote = 0;
        msgTx.id = 0x7E0; // request header for OBD
        Can0.write(msgTx); 
        Serial.println("canTx_UDS REQ sent"); 
      }
    You can try first the OBD method of request, then you can try the UDS method by commenting out the OBD request and uncommenting the UDS request in the main loop.

  6. #6
    Junior Member
    Join Date
    Sep 2020
    Posts
    4
    Rezo, thank you very much for the information, fortunately I have this transceiver. Today I will try to connect according to your example.

  7. #7
    Senior Member
    Join Date
    Oct 2019
    Posts
    354
    By the way, I plug into the OBD port, not directly to any of the available busses in the car. I was after true P&P

  8. #8
    Junior Member
    Join Date
    Sep 2020
    Posts
    4
    Rezo, thanks for the hints and code, this works and I'm glad it does!
    Well, I'm continuing to work on the project.
    Click image for larger version. 

Name:	IMG_5868.jpg 
Views:	216 
Size:	45.6 KB 
ID:	21733
    Click image for larger version. 

Name:	IMG_5871.jpg 
Views:	200 
Size:	361.0 KB 
ID:	21734
    Click image for larger version. 

Name:	IMG_5873.jpg 
Views:	210 
Size:	284.4 KB 
ID:	21735

  9. #9
    Senior Member
    Join Date
    Oct 2019
    Posts
    354
    vgopaitsa I'm really glad it's working for you!

    If you want to make a nice GUI, I can suggest the following:
    Ring gauge - this is fairly easy to adapt to your current display library, and looks cool with little effort
    LVGL - this is complex to set up but looks really great, I've just started to port my own project to this graphics library


    Show us the progress as you move along!

  10. #10
    Junior Member
    Join Date
    Jul 2022
    Posts
    17
    Hello, I am trying to read some data from my car (Honda Civic 2015) and I am following all the inrofmation you are giving but I don't succeed. Here I post my code, hoping you can see where I am wrong.

    I am already tried a lot of request id and changing from 11 to 29 bits with "can_MsgTx.flags.extended = 0" tried with 0 and 1 but no answer from Canbus, I always have random numbers doesn't matter if I request something or not.

    //CANBUS Library
    #include "FlexCAN.h"
    #include "kinetis_flexcan.h"

    // Specify CAN baudrate
    FlexCAN CANbus(500000);//1000000);//500000);
    static CAN_message_t rxmsg;


    #define PID_REQUEST 0x7DF
    #define PID_REPLY 0x7E8
    #define ENGINE_COOLANT_TEMP 0x05

    void setup() {


    //Initialize CAN
    CANbus.begin();

    Serial.begin(115200); //CANBUS Serial
    (!Serial);

    while (!Serial){
    Serial.print("Waiting connection \n");
    }


    Serial.print("Start reading \n");
    }

    elapsedMillis DisplayTime; //Establish a timer to prevent unnecessary screen rewrite

    void loop(void) {

    ///////////////Look for CAN broadcasts///////////////
    CAN_message_t can_MsgTx;

    can_MsgTx.buf[0] = 0x02;
    can_MsgTx.buf[1] = 0x01;
    can_MsgTx.buf[2] = ENGINE_COOLANT_TEMP;
    can_MsgTx.buf[3] = 0;
    can_MsgTx.buf[4] = 0;
    can_MsgTx.buf[5] = 0;
    can_MsgTx.buf[6] = 0;
    can_MsgTx.buf[7] = 0;
    can_MsgTx.len = 8;
    //can_MsgTx.ext = 0;
    can_MsgTx.flags.extended = 0;
    can_MsgTx.flags.remote = 0;
    can_MsgTx.id = PID_REQUEST;
    //can_MsgTx.id = 0x222;
    //can_MsgTx.id = 0x7E0;
    // can_MsgTx.timeout = 500;
    CANbus.write(can_MsgTx);

    while ( CANbus.read(rxmsg) ) {
    if ((rxmsg.id == PID_REPLY) or (rxmsg.buf[0] == ENGINE_COOLANT_TEMP) or (rxmsg.buf[1] == ENGINE_COOLANT_TEMP) or (rxmsg.buf[2] == ENGINE_COOLANT_TEMP)){
    Serial.print("Answered \t");
    Serial.print(rxmsg.buf[2]);
    Serial.print("\t");
    Serial.print(rxmsg.buf[3]);
    Serial.print("\n");
    if (rxmsg.buf[2] == 0x05){
    Serial.print("Engine coolant temp: \t");
    Serial.print(rxmsg.buf[3] - 40);
    Serial.print("\n");
    }
    }
    }


    // if ( DisplayTime < 150 ) return;
    // DisplayTime = 0;
    }
    Thank you

  11. #11
    Senior Member PaulS's Avatar
    Join Date
    Apr 2015
    Location
    Netherlands
    Posts
    910
    Hi Sandra, you may want to invest into a CAN bus analyzer like this one, it saved me a lot of time while debugging a Teensy-based CAN bus device.

    Paul

  12. #12
    Senior Member PaulS's Avatar
    Join Date
    Apr 2015
    Location
    Netherlands
    Posts
    910
    Took me some fiddling and using the CAN analyzer to get your code working.
    Apparently the way the FlexCan library is invoked/called makes a difference.
    Here is the working code:
    Code:
    //CANBUS Library
    #include "FlexCAN.h"
    //#include "kinetis_flexcan.h"
    
    // Specify CAN baudrate
    //FlexCAN CANbus(500000);//1000000);//500000);
    static CAN_message_t rxmsg;
    static CAN_filter_t allPassFilter;
    
    
    #define PID_REQUEST 0x7DF
    #define PID_REPLY 0x7E8
    #define ENGINE_COOLANT_TEMP 0x05
    
    void setup() {
      //Initialize CAN
      allPassFilter.flags.extended = 0;  // 1 for extended/29 bit IDs
      Can0.begin(500000, allPassFilter);
    
      Serial.begin(115200); //CANBUS Serial
    //  (!Serial);
    //
    //  while (!Serial) {
    //    Serial.print("Waiting connection \n");
    //  }
      Serial.print("Start reading \n");
    }
    
    //elapsedMillis DisplayTime; //Establish a timer to prevent unnecessary screen rewrite
    
    void loop() {
    
      ///////////////Look for CAN broadcasts///////////////
      CAN_message_t can_MsgTx;
    
      can_MsgTx.buf[0] = 0x02;
      can_MsgTx.buf[1] = 0x01;
      can_MsgTx.buf[2] = ENGINE_COOLANT_TEMP;
      can_MsgTx.buf[3] = 0;
      can_MsgTx.buf[4] = 0;
      can_MsgTx.buf[5] = 0;
      can_MsgTx.buf[6] = 0;
      can_MsgTx.buf[7] = 0;
      can_MsgTx.len = 8;
      //can_MsgTx.ext = 0;
      can_MsgTx.flags.extended = 0;
      can_MsgTx.flags.remote = 0;
      can_MsgTx.id = PID_REQUEST;
      //can_MsgTx.id = 0x222;
      //can_MsgTx.id = 0x7E0;
      // can_MsgTx.timeout = 500;
      Can0.write(can_MsgTx);
    
      if (Can0.read(rxmsg)) {
        if ((rxmsg.id == PID_REPLY) or (rxmsg.buf[0] == ENGINE_COOLANT_TEMP) or (rxmsg.buf[1] == ENGINE_COOLANT_TEMP) or (rxmsg.buf[2] == ENGINE_COOLANT_TEMP)) {
          Serial.print("Answered \t");
          Serial.print(rxmsg.buf[2]);
          Serial.print("\t");
          Serial.print(rxmsg.buf[3]);
          Serial.print("\n");
          if (rxmsg.buf[2] == 0x05) {
            Serial.print("Engine coolant temp: \t");
            Serial.print(rxmsg.buf[3] - 40);
            Serial.print("\n");
          }
        }
      }
    
      delay(500);
      // if ( DisplayTime < 150 ) return;
      // DisplayTime = 0;
    }
    This is the serial monitor output:

    Click image for larger version. 

Name:	Serial monitor.png 
Views:	38 
Size:	17.1 KB 
ID:	28957

    I had the CAN bus analyzer set to auto-answer whenever a PID_REQUEST frame came in and send out a PID_REPLY frame with rxmsg.buf[2] set to 0x05:

    Click image for larger version. 

Name:	analyzer.png 
Views:	79 
Size:	54.7 KB 
ID:	28958

    Hope this helps.
    Paul

  13. #13
    Senior Member PaulS's Avatar
    Join Date
    Apr 2015
    Location
    Netherlands
    Posts
    910
    Here is a photo of the setup I used for testing:

    Click image for larger version. 

Name:	setup.jpg 
Views:	48 
Size:	86.0 KB 
ID:	28959

    And yes, you do need a CAN bus transceiver, like this.

    Paul

  14. #14
    Junior Member
    Join Date
    Jul 2022
    Posts
    17
    Thank you for you answer PaulS, I was checking and no luck but finally I change my transceiver for a new one (I alredy had it but I didn't remember) and now it connects and I have some communication, but the results are not the desired ones.
    I would like to have the ones you have on your post but mine are different, for ENGINE_COOLANT_TEMP I gost this:

    Click image for larger version. 

Name:	Captura.JPG 
Views:	32 
Size:	39.8 KB 
ID:	28961

    I tried to changed to RPM (0X0C) and I got something better:

    Click image for larger version. 

Name:	Captura2.JPG 
Views:	29 
Size:	30.6 KB 
ID:	28962

    the thing is that when the car is off I get the pid on buf 2 but when engine is on I get the pid on buf 3, the numbers seem to be good ones.

    code is the same but just printing all id and bufs as seen in the image, so first number is id, next one is buf[0] and so on...:

    Serial.print("Answered \t");
    Serial.print(rxmsg.id);
    Serial.print("\t");
    Serial.print(rxmsg.buf[0]);
    Serial.print("\t");
    Serial.print(rxmsg.buf[1]);
    Serial.print("\t");
    Serial.print(rxmsg.buf[2]);
    Serial.print("\t");
    Serial.print(rxmsg.buf[3]);
    Serial.print("\t");
    Serial.print(rxmsg.buf[4]);
    Serial.print("\t");
    Serial.print(rxmsg.buf[5]);
    Serial.print("\t");
    Serial.print(rxmsg.buf[6]);
    Serial.print("\t");
    Serial.print(rxmsg.buf[7]);
    Serial.print("\n");
    Thanks

  15. #15
    Senior Member PaulS's Avatar
    Join Date
    Apr 2015
    Location
    Netherlands
    Posts
    910
    From this page I read: "1 - 1,0C,2,"Engine RPM",0,16383.75,rpm,((A*256)+B)/4".
    It's apparently generic OBD2. The RPM PID 0x0C only returns 2 bytes, so buf[0] and buf[1]. You can verify that by printing Serial.print(rxmsg.len);.
    The formula is given as ((A*256)+B)/4. When I fill in buf[1] for A and buf[0] for B, I got something like 769RPM. Sounds reasonable.

    Paul

  16. #16
    Junior Member
    Join Date
    Jul 2022
    Posts
    17
    Thanks for your answer PaulS, I am not able to get this 769rpm, getting any of the buf combination. As far as I can read on wikipedia and some other pages buf[0] is the number of additional bytes in the response, buf[1] should be 0x41 as it's the mode I am reading on, buf[2] should return the pid I asked for, in this case 0x0C and buf[3] and 4 should be the answer applying the formula.

    https://en.wikipedia.org/wiki/OBD-II...le_information

    Click image for larger version. 

Name:	Captura2.JPG 
Views:	37 
Size:	119.7 KB 
ID:	28972

    But this is the answer I get (first number is the len of the answer):

    Click image for larger version. 

Name:	Captura.JPG 
Views:	28 
Size:	30.2 KB 
ID:	28973

    I don't get the reply code (id) I should, on the buf[0] I get 4 additional bytes which seems reasonable, 2 are the answer, one the pid I asked for and the other one the method I am using to get the data. But on buf[1] I should get 0x41 which is 65 and I get the pid I asked for, on buf[2] I get nothing, and on buf 3 and 4, where I should get the data I get numbers that using the formula are bigger than 2000 when my car ir just beow 1000 (around 900).

    On the webage you posted the link I realized that I cannot check the coolant temp (unfortunatelly) but,rpm should workd.

    Thanks

  17. #17
    Senior Member PaulS's Avatar
    Join Date
    Apr 2015
    Location
    Netherlands
    Posts
    910
    Quote Originally Posted by Sandra View Post
    code is the same but just printing all id and bufs as seen in the image, so first number is id, next one is buf[0] and so on...:
    That is a good idea. But do you still have this line in?
    Code:
    if ((rxmsg.id == PID_REPLY) or (rxmsg.buf[0] == ENGINE_COOLANT_TEMP) or (rxmsg.buf[1] == ENGINE_COOLANT_TEMP) or (rxmsg.buf[2] == ENGINE_COOLANT_TEMP)) {
    Perhaps you should change that to:
    Code:
    if ((rxmsg.id == PID_REPLY){
    And print out the length of the CAN reply message as well for diagnostic purposes:
    Code:
    Serial.print(rxmsg.len);
    Serial.print("\t");
    Paul

  18. #18
    Junior Member
    Join Date
    Jul 2022
    Posts
    17
    Quote Originally Posted by But do you still have this line in?
    [CODE
    if ((rxmsg.id == PID_REPLY) or (rxmsg.buf[0] == ENGINE_COOLANT_TEMP) or (rxmsg.buf[1] == ENGINE_COOLANT_TEMP) or (rxmsg.buf[2] == ENGINE_COOLANT_TEMP)) {[/CODE]
    Yes I have it, if I remove all or conditions and just leave rxmsg.id nothing is showed. No answer as the reply is not the one it should.

  19. #19
    Senior Member PaulS's Avatar
    Join Date
    Apr 2015
    Location
    Netherlands
    Posts
    910
    Hmm, if you don't get a PID_REPLY at all, then something else is wrong. Perhaps it's a hardware/wiring issue?
    I think you really need a CAN analyzer now to debug the issue.

    Paul

  20. #20
    Junior Member
    Join Date
    Jul 2022
    Posts
    17
    Thanks for the help, I will try to get one and check. I was thinking it could be something regarding the hardware/wiring but I was already using this hardware/wiring on another project and it worked using canbus.

  21. #21
    Junior Member
    Join Date
    Jul 2022
    Posts
    17
    Hello,

    I already got an analyzer and I am trying to test, once I was able to see the data on the program and everything was good but when I tried to configure a result I lost all communication and now I cannot see anything on the analyzer (welll, the green light of receiving is blinking correctly), maybe I forgot something on the configuration of the analyzer.

    Click image for larger version. 

Name:	Captura.JPG 
Views:	38 
Size:	126.8 KB 
ID:	29044

    Thanks

  22. #22
    Senior Member PaulS's Avatar
    Join Date
    Apr 2015
    Location
    Netherlands
    Posts
    910
    Your screen looks similar to my screen in message #12. Did you click the "Set and Start" button?
    If it is still not working, exit the program. Unplug and replug the USB cable of the analyzer. Then start the program again.
    Check the correct COM port [don't confuse it with the Teensy COM port] and click the "Open" button. Then click the "Set and Start" button.
    That should be it.

    Paul

  23. #23
    Junior Member
    Join Date
    Jul 2022
    Posts
    17
    It's strange, I was able to see the values once but now only green led is blinking and no way to see anything , without changing any wires, I will keep trying.
    Thanks

  24. #24
    Senior Member PaulS's Avatar
    Join Date
    Apr 2015
    Location
    Netherlands
    Posts
    910
    A few weeks ago, my USB CAN analyzer acted up weird.
    I then resetted the analyzer as described here and it was working normally again.
    Perhaps give that a try?

    Paul

  25. #25
    Junior Member
    Join Date
    Jul 2022
    Posts
    17
    Dear Paul,

    thank you for your answer, I was on a busniess trip and no way to test it. I did the reset and worked again, now I see the arduino code is ok, as it is working with CAN analyzer, so I need to figure out what's happening so it's not working with my car.

    Thank you

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •