Monday, February 9, 2015

Arduino, CAN Bus and 29 bit extended IDs

I noticed in my blog traffic stats that people are searching for information about 29 bit CAN IDs and I have been curious about this topic myself. I haven't come across 29 bit CAN IDs in a vehicle until recently and seeing these extended IDs in use in a car made want to understand how to use them with Arduino boards and MCP2515 CAN controllers. I wrote a blog post back in October 2013 that covers how to send data between two Arduino boards using a CAN bus so you may want to check that out if you aren't familiar with how a CAN bus works. That post is available here. This post is specifically about using 29 bit CAN IDs with an Arduino and the MCP2515 CAN controller chip.

CAN Bus IDs


There are two types of CAN Bus IDs. In the first version of the CAN Bus spec (2.0A) the IDs were made up of 11 bits. These are also known as base frame format messages. This allows for message IDs between 0x000 and 0x7FF. Which works out to be 2048 possible CAN IDs.

Binary, Decimal and Hex representation of the max 11 bit ID
 As CAN Busses were added to heavy equipment and as vehicles became more complex those 2048 possible IDs were not enough to handle the increased number of sensors. CAN 2.0B was created which increased the size of IDs from 11 bits to 29 bits. CAN 2.0B allows for over 536 million different IDs. 29 bit messages are also known as extended frame format messages. 18 bits were added to the original 11 bits in an separate field in a CAN message. There is a flag in the message that signals if a message is an 11 bit or 29 bit message. 11 bit and 29 bit messages can coexist on the same CAN bus.

Binary, Decimal and Hex representation of the max 29 bit ID
There are some trade-offs with 29 bit CAN IDs though. The latency is increased, the messages use more bandwidth and error detection performance is decreased. But if you have run out of IDs I suppose these are worthwhile trade-offs.


11 bit code example


Let's take a look at a very simple example of using an MCP2515 CAN controller with an Arduino and 11 bit CAN IDs. I am using a Seeed Studio CAN-BUS Shield but the MCP2515 is just an SPI chip that can be wired up with minimal external components.
In this 11 bit example I am using a CAN ID of 0x07B in hex (123 in decimal).


Here you can see my receiver Arduino is receiving CAN messages with an ID of 123.



29 bit code example


Next let's look at an example of sending 29 bit CAN IDs. In this example I am using a CAN ID of 0x17F8140E in hex (or 402134030 in decimal).


Here you can see my receiver Arduino is receiving CAN messages with an ID of 402134030.



sendMsgBuf format

The key piece of this example code is the sendMsgBuf function. This function is part of the
MCP_CAN_lib. This is where messages are flagged as 11 bit or 29 bit.

11 bit: CAN.sendMsgBuf(0x07B, 0, 8, canMsg);

29 bit: CAN.sendMsgBuf(0x17F8140E, 1, 8, canMsg);


The format for this function is sendMsgBuf(can_id, id_type, dlc, data_buf)

can_id - id number for your message in hex or decimal.

id_type - flag for 11 or 29 bit message id. 0=11bit, 1=29bit

dlc - Number of bytes in the message data

data_buf - The data transmitted in the message.


If you are going to try out these examples you should download Cory Fowler's fork of the MCP_CAN_lib.


Resources

32 comments:

  1. Hallo Matt,
    I have an identifier xxxxxxx.
    the results in an hexa code 00 01 02 03 04 05 06 07 for example
    Is it possible to write a program to get the correct values from the code or decrypt the code in Arduino Software
    For example a EngineRpm or something.

    best regards

    ReplyDelete
    Replies
    1. Yes that is definitely possible. The hard part is tracking down which can id has the rpm data. Look for a can id that has data that changes with the engine rpm. Once you find the right can id you have to figure out how the data is stored in the message. Each of the 8 bytes in a can message can only store a value between 0-255 decimal or 00-FF hex. RPM data will range from a minimum of 0 to a max of probably 9999. Since that number will be bigger than 255 it will probably be spread across two or more bytes. How this is done really varies from manufacturer to manufacturer. Sometimes two bytes are multiplied together. Could be each digit is a separate byte (though that is somewhat wasteful and unlikely). You have to play around with the numbers until you get what looks like a reasonable value and then compare that to what you are seeing on your gauges.

      Delete
  2. Thanks for your fast answer. I have the can ID and i get the HEX code exactly for RPM of Engine.
    Now I have to encode the HEX. That's very difficult and I don't find anything about it how to write a program to get the real RPM out of the HEX code..:(

    ReplyDelete
    Replies
    1. If you will send me some of the rpm CAN data I'll take a look at it and see if I can figure anything out.

      Delete
  3. ID: 0x280
    HEX: 09 22 28 0A 22 00 22 22

    now i need the result what is the rpm in real DEZ. is there no standard program that i can figure out the values?

    best regards

    ReplyDelete
  4. byte 2 and byte 3 is where the rpm data should stay

    thanks a lot for your help

    ReplyDelete
    Replies
    1. Can you post like 5 or 10 of the CAN messages so I can see the data changing?

      Delete
  5. i will look for more messages tomorrow and then I'll send you some..

    greets..

    ReplyDelete
  6. Hello, thank you for your nice blog. I have the problem, when i read can-bus using can-bus shield and arduino, the messages for steering wheel buttons(which control audio system) absolutely the same, another messages have uniq ID's, but for joystick and audio control for each press different button i receive the same message, can you tell me please what can be wrong? I have volvo s80 II 2008. Thank you

    ReplyDelete
    Replies
    1. It would be helpful if you can post some data to look at. Is it possible the messages have the same can ID but different data in the message?

      Delete
    2. Data is the same, can ID the same too. Maybe i found wrong message, this message can be just response from HU? I will send the message today, later. Thank you

      Delete
    3. Yeah sounds like you might have the wrong CAN id. Probably related but maybe there is a different id with the actions you are looking for.

      Delete

  7. Dear Matt McMillan!!!
    I want to http://ru.aliexpress.com/item/MCP2515-CAN-Bus-Module-TJA1050-Receiver-SPI-Module-for-Arduino/32391372405.html purchase this module !! Do you think it will work ?

    ReplyDelete
    Replies
    1. Do you have quartz on 16 MHz, but on the Chinese clone at 8 MHz. I'm confused about this point.

      Delete
    2. Oh interesting. I didn't look closely at the crystal. Yeah you are right it is an 8 MHz part on the clone. I just checked the data sheet for the MCP2515 and an 8 MHz resonator is acceptable with the right capacitors. Look at page 56 in this document: http://ww1.microchip.com/downloads/en/DeviceDoc/21801G.pdf

      Delete
  8. Hello Matt McMillan,

    I have successfully communicated two arduino using CAN bus by taking your tutorial as a reference.

    Now i want to make communication between three arduino using CAN bus.
    Please guide me, How should i do it?

    ReplyDelete
    Replies
    1. Additional devices can just be connected into the CAN bus. You can T off of the twisted CAN-H and CAN-L wire pair. The only difference is additional devices don't need the termination resistor. All devices need to share a common ground.

      Delete
  9. Thank you for your guidance. I will try it.

    ReplyDelete
  10. Hello Matt,
    I have succesfully communicated a CAN bus shield with an Arduino Mega2560 following one of yours tutorials, now i'm trying to receive messages from a controller that uses two messages in the extended frame format. My problem is that apparently the can bus shield can´t separate well the ID bits of the data bits, so do you know if i have to write an extra code for this or its supposed that the typical receive example should work for this?
    Best Regards!

    ReplyDelete
  11. Hello Matt,
    I have succesfully communicated the CAN bus shield with an arduino Mega2560 following one of yours tutorials, now i have a controller that delivers two types of messages in the extended frame format. My problem is that the receive code that you recommend in other tutorial apparently can´t realize when a new message is arriving, so i have a wrong ID an wrong data bytes, do you know if i have to make some changes in the code for 29 bits identifiers meassages?

    Best regards!

    ReplyDelete
  12. hello ,
    i am working on receiving a data from an ECU and i have a tool called busmaster connected with vector can case and i want to use arduino plus shield i have one which has a clock of 8MHZ . th e ids i am getting are wrong data length also and data all of them are completely different than what gives busmaster can you help me please.

    ReplyDelete
  13. hi, i have this code, how i can convert in 29 bit?




    void loop()
    {
    tCAN message;

    message.id =0x0010A152; //formatted in HEX
    message.header.rtr = 1;
    message.header.length = 7; //formatted in DEC
    message.data[0] = 0xAB ;
    message.data[1] = 0x3F;
    message.data[2] = 0x93;
    message.data[3] = 0x00; //formatted in HEX
    message.data[4] = 0x00;
    message.data[5] = 0x00;
    message.data[6] = 0x00;



    mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0),1);
    mcp2515_send_message(&message);

    delay(100);




    thanks again

    ReplyDelete
  14. remove this "mcp2515_send_message(&message);" and add this line:
    "mcp2515_send_message_J1939(&message);"

    ReplyDelete
  15. Matt, What does your receive code look like? I am using readMsgBuf, but I am having problems receiving 29 bit Identifiers...

    ReplyDelete
    Replies
    1. Looks like the MCP_can library has been updated quite a bit. I haven't used the new version yet. Have you tried the example code included with the library?

      Delete
    2. i am facing the same issue, unable to read a extended CAN ID message
      however, able to send extended CAN ID messages
      i am using sparkfun CAN shield with Arduino UNO and a CAN single wire to double wire converter to talk to a custom engine ECU

      Delete
  16. Hello
    Somebody can help me whether this code is correct or not?

    #include
    #include

    const int SPI_CS_PIN = 10;
    MCP_CAN CAN(SPI_CS_PIN); // Set CS pin

    void setup()
    {
    Serial.begin(115200);
    if(CAN.begin(CAN_100KBPS) ==CAN_OK) Serial.print("can init ok!!\r\n");// init can bus, baudrate: 100k
    else Serial.print("Can init fail!!\r\n");
    }

    void loop()

    {

    // send data:
    unsigned char stmp1[4] = {0x07, 0x00, 0x00, 0x00};//AC key on
    CAN.sendMsgBuf(0x575, 0, 4, stmp1);
    delay(100); // send data per 100ms

    unsigned char stmp2[4] = {0x60, 0x60, 0x00, 0x00}; //button illumination
    CAN.sendMsgBuf(0x635, 0, 4, stmp2);
    delay(100); // send data per 100ms


    }

    ReplyDelete
  17. Anyone figure out how to RECEIEVE 29xtd bit IDs?

    ReplyDelete
  18. Thanks for posting the example on extended bits. Just sent you a donation. I was only off by one change but could have taken hours of looking and hitting your site on my first search saved me lots of headaches. I can now fully control an Audi MIB Navigation system with my own computer program :D

    ReplyDelete
  19. Just looking at your code examples above, does that code work for reading 29bit frames? I am about to start looking at my vehicle to replace the sat-nav and need to read 29bit/extended frames.

    Thanks in advance

    D

    ReplyDelete

Please note all comments are moderated by me before they appear on the site. It may take a day or so for me to get to them. Thanks for your feedback.