How to Request VIN

Hey guys,

Looking to request VIN via an OBD request. I’m generally familiar with J1939 and CAN but I’m stuck with requesting mode 9 pid 2.

Here is how I’m creating my message to be transmitted

void sendObdRequest(){
CANMessage message;
message.id = OBD_CAN_BROADCAST_ID;
message.len = 8; // just always use 8
message.data[0] = 0x02; // 0 = single-frame format, 2  = num data bytes
message.data[1] = 0x09;
message.data[2] = 0x02;
carloop.can().transmit(message);
waitForObdResponse();
}

And then I’m waiting for the message with the following:

void waitForObdResponse(){
bool responseReceived = false;
Serial.println("I made it to wait for obd response");
CANMessage message;
while (carloop.can().receive(message)) {
    Serial.println("message received");
    if(message.data[2] == 0x02) {
	responseReceived = true;
	data0 = message.data[0];
        data1 = message.data[1];
        data2 = message.data[2];
        data3 = message.data[3];
        data4 = message.data[4];
        data5 = message.data[5];
        data6 = message.data[6];
        data7 = message.data[7];
        Serial.println("VIN message data seen");
    return;
	}
    }
}

I’m never entering the “if(message.data[2] == 0x02”

Thanks for the help!

1 Like

I’ll take a look over the weekend and release a sample app to get the VIN.

Nice! Thanks so much. I know its not supported on all vehicles, but in general, request frames that have data across more than one message would be super helpful!

Here’s a progress update.

The protocol for sending OBD messages is called ISO_15765-2. Since CAN doesn’t support message with more than 8 bytes, long data like the Vehicle Identification Number (VIN) are encoded across several messages.

Here’s the full exchange to get my VIN 3FADP4FJ2BM11391. I’ll go into what each message means below. In addition I am working on publishing a class that automates the decoding this protocol.

  can0  7DF   [8]  02 09 02 00 00 00 00 00
  can0  7E8   [8]  10 14 49 02 01 33 46 41
  can0  7E0   [8]  30 00 00 00 00 00 00 00
  can0  7E8   [8]  21 44 50 34 46 4A 32 42
  can0  7E8   [8]  22 4D 31 31 33 39 31 33

You have the right request to get the VIN. It’s a Parameter ID (PID) request (0x09) for the VIN (0x02). You send that as a broadcast message (0x7DF) with a length of 2.

The first message sent in reply by the ECU (ID 0x7E8) starts with 0x1014 which means extended message with a length of 0x14 = 20 bytes. Then 0x49 means a reply to the 0x09 PID request and 0x02 is the PID that was requested. The start of the data follows.

Next the requestor must send a flow control message to say: “OK to continue sending the rest of the message”. The flow control message must be sent with a CAN ID that is the ID of the reply from the ECU minus 8. So the flow control here is sent with ID 0x7E0 with data 0x30 followed by 7 times 0x00.

Then the ECU sends each subsequent piece of data with a frame that starts with 0x2y where y is a sequence number. The other 7 bytes are data.

I generated the exchange using the Carloop in running the socketcan firmware.

I ran these commands on my Linux laptop after flashing the socketcan firmware and connecting the Carloop to my car with the ignition and and to my laptop by USB:

sudo slcand -o -c -s6 /dev/ttyACM* can0
sudo ifconfig can0 up
# See all messages with ID larger than 0x780
candump can0,780:780
# In a different terminal
cansend can0 7df#0209020000000000 && sleep 0.01 && cansend can0 7e0#3000000000000000

I’ll keep working on wrapping this request into a demo app I can share with everybody.

Here’s the beginning of the OBD message decoder class:

To use it you’d do (I have not tested the code yet. I’ll fix errors in this code as soon as I have time to test it):

void setup() {
  carloop.begin();

  CANMessage message;
  message.id = OBD_CAN_BROADCAST_ID;
  message.len = 8; // just always use 8
  message.data[0] = 0x02; // 0 = single-frame format, 2  = num data bytes
  message.data[1] = 0x09;
  message.data[2] = 0x02;
  carloop.can().transmit(message);
}

void loop() {
  static OBDMessage obd;
  CANMessage message;
  if (carloop.can().receive(message)) {
    if (message.id == 0x7E8) {
      // Add the data to our OBD message
      bool needsFlowControl = obd.addMessageData(message);

      if (needsFlowControl) {
        // Sending flow control
        CANMessage flowControl = obd.flowControlMessage();
        carloop.can().transmit(flowControl);
      }

      // Use the data when the message is complete
      if (obd.complete()) {
        for (auto it = obd.data().begin(); it != obd.data().end(); ++it) {
          uint8_t data = *it;
          Serial.printf("%c", data);
        }
        Serial.println("");
        obd.clear();
      }
  }
}
1 Like

I think we are extremely close. Running your code with some slight modifications I was able to receive message id 0x7E8, and adding some print statements, able to see that the code was indeed sending a flow control message.

However, it seems that the obd.complete function never returns true. Hope my trial helps.

1 Like

I had the time to wrap up the code above in an app. Check out the VIN reader app at https://carloop.io/apps/

The app is available on GitHub at GitHub - carloop/app-vin-reader: VIN reader

When I run the code in my car with the ignition on, I get the correct VIN. :tada:

Here’s the debug log through Serial:

Reading VIN
Got reply from ECU
Sent flow control
Got reply from ECU
Got reply from ECU
VIN: 3FADP4FJ2BM113913
Done

You are right that there’s something fishy with the obd.complete() function because at some point while tweaking the Serial.print statements I didn’t get complete() to return true anymore. There must be a bug in the OBDMessage class causing this. :unamused:

1 Like

Nice! I will definitely check it out. I’ve just finished scaling and offsets for all Mode 1 PIDs (I am no programmer by trade, so it’s probably horribly inefficient but it works nonetheless) Hoping I will have time to post a project to hackster.io tomorrow.

1 Like

That would be awesome! The folks from Hackster.io hooked us up with a nice project page, so you could add your Carloop projects here: Hackster.io - The community dedicated to learning hardware.

Hello ,
Please the data D2= 0x49 found in line 2 is always the same for all multiple frames obd messages ?
Regards

@ninfeinous, I think the information you are looking for regarding multi-frame CANbus messages is on Wikipedia here:

The byte of date you are asking about was answered in the details above. It is essentially saying the message is a response to a specific request. This way you can search for the message containing the response you need, out of the many messages going across the CANbus:

Does this help you out?

i am trying to get response from OBD2 through STN chip
here is the response of emulator
0902
7E810144902014D4154
7E82134303330393642
7E8224E4C3030303135
i not getting how to decode can anyone help???

this is for vin pid plz rpy fast

Ascii code of 4D(hex) - 77(DECIMAL) “M” - 41(hex) - 65(DECIMAL) “A”
First 3 byte is CAN ID. After that split that data 2 by 2,
if there is a data on D1 “10” thats means there will come more data. D2 = hex(14) that means total byte will come (14 hex = 20 decimal )
if rows first byte(D1) is 2x that is information byte and you can take all bytes after thats

I did that in excel
you can use HEXTODEC() and CHAR() function on excel

A post was split to a new topic: J1939 Protocol on Carloop

Is 7DF default for any car to get diagnosis ? I’m trying to send data like (cansend can0 7df#0209020000000000) and nothing happens. All can-tools are woking fine. I’m trying it on a Honda 2016 (Brazil) .

Thanks in advance

7DF is the broadcast address for OBD-II, so as long as your car supports OBD-II you should be able to use that mode. You might want to try different CAN bus speeds like 250000 bits/s and 1000000 bits/s.

First, thanks for this post. Great information. When testing my code, I am able to send the 0902 request for the VIN and I receive the initial response, I then send the Flow control message and receive the second frame of the VIN. However, I never can get the third frame of the VIN. I have tried numerous troubleshooting steps to isolate the problem but I am at a loss. No matter what I do, I can only get two thirds of the VIN (2 of 3) frames. Do you have any ideas what could be causing this. My code is in C so its slightly different than the C++ provided. Thanks for any assistance.

@slgtech,

You mentioned specifically sending a Flow control message to request the second frame. That seems to work fine, because you say that you then receive the second frame. However, you do not mention a Flow control message to request the third frame. Can you check to ensure you are sending a request for the third frame? Also, does the Flow control message have a frame number built into it (I do not have the details on-hand at the moment about the Flow control message format, just covering all the possible bases.)?

Look into that and let us know if that helps. If not, we can dig in deeper and try to figure it out.

Fantastic Thread with good explanations…

However I got stuck at a point.

A diagnostic device sends a Remote Transmission Request and
I need to simulate my ECU by sending the VIN via CAN

VIN is: SALLDWBP8DA431032

I converted VIN to HEX as: 53 41 4C 4C 44 57 42 50 38 44 41 34 33 31 30 33 32

So I thougt the ECU (7E8) should respond

(0.1) 7E8 10 14 49 02 01 53 41 4C
(0.2) 7E8 21 4C 44 57 42 50 38 44
(0.3) 7E8 22 41 34 33 31 30 33 32

Is this correct?

Questions: Between the 1st and 2nd message there should be the requestors flow control message… may I ignore that and simply continue transmitting? Bus Speed is 500k

BR
Ralf