Thursday, October 10, 2013

Arduino - Sending data over a CAN bus

I have been tinkering with CAN buses due to my interest in cars. It's fascinating to me that packets are flying around a modern vehicle controlling nearly everything. Gauges, lights, locks, engine sensors, etc. To have a better understanding of the basics of a CAN bus I wanted to build the simplest possible setup to send and receive CAN messages. I chose two Arduino Uno's with a Seeed Studio CAN-BUS shield attached to each Uno. The Seeed shield is very straight forward and inexpensive. The Sparkfun CAN-BUS shield has an SD card slot, LCD connector and GPS connector. All of which are cool but drive up the price and complexity. The Seeed shield only does CAN bus and includes screw terminals which are handy for testing.

Arduino Uno R3Seeed CAN-BUS Shield

What I wanted to do with this experiment was transmit the value of an analog pin hooked up to a linear potentiometer. The data would be sent from one Arduino to another over a CAN bus and then display that value on an LCD connected to the second Arduino. Here is a picture of my setup. (Ignore the Mega2560 above the LCD. It's not used here.)


And here is a Fritzing diagram minus the CAN-BUS shields.



CAN bus termination

A CAN bus requires 120 Ohm termination resistors at each end of the bus. The Seeed Studio shields have built in termination resistors. When you connect two Seeed CAN bus shields togther like I did in this example you will have a properly terminated CAN bus. If you plan on connecting into an existing CAN bus that already has termination you can disable the built in termination resistors. To disable termination you can cut trace P1 or you can desolder resistor R1.


Close up view of the Seeed CAN bus shield
 termination resistors.
**Note: I have recently discovered the Seeed Studio CAN-BUS shield v1.0 uses a 60 ohm termination resistor for R3. While that worked for this small demo I later ran into issues when trying to use this shield with other nodes on a CAN bus. This 60 ohm resistor caused me many hours of frustration. If you are going to use this shield with on a bus with multiple nodes I would recommend desoldering R3 and using the correct 120 ohm resistance at the ends of your bus. 

Connecting into an existing CAN bus

If you are planning on connecting into an existing CAN bus (like in a car) you need to remove/disable the termination resistor on the shield as explained above. The CAN bus in a vehicle already has termination resistors. Adding a new node with a termination resistor will cause errors and disrupt communication on the bus.

Another important step is to connect a common ground between your Arduino board and the vehicle. If you are connecting at the OBD2 port pin 5 provides a signal ground. If you can't find a signal ground wire a chassis ground will suffice.

CAN bus messages

So I should probably explain a bit about CAN bus messages. Each message is made up of an id and some data. The id's in hex start at 0x000 and go to 0x7FF or 0 to 2047 in decimal. In most systems lower id values are considered more important. The bus handles collisions by letting the lower id win the collision. The data can be between 1 and 8 bytes for each message. Each byte can have a value from 0 to 255 or in hex 0x00 to 0xFF. When you send a CAN bus message you transmit the id, how many bytes you are sending (this is called DLC) and the actual data. The receiver will only read the number of bytes you said should be in the message. So if you send a DLC of 4 but the message contains 8 bytes the receiver will only read the first 4 bytes. Eight bytes per message is a bit limiting but the tradeoff is the high reliability of the bus. So sometimes you have to be creative with stuffing data into those bytes. If the value you are sending is less than 255 you can just use a single byte. Larger numbers will require using multiple bytes. Ascii codes can be sent but only eight characters per message. Whatever method you use to stuff the data in will also have to be used to un-stuff the data on the receiver. In my simple example here I did some math to limit the range of values to 0-255. An analog pin produces values between 0-1024. I simply divided the result by four to give me data I could send in a single byte.
CAN buses can operate at several different speeds up to 1 Mbit/s. Typical rates are 100 kbit/s, 125 kbit/s and 500 kbit/s. Slower rates allow for longer length buses. All devices on a bus must transmit at the same speed. The CAN bus wikipedia page is a good place to start if you want to learn more about the CAN protocol.


Code

I started with the example code provided by Seeed and modified it to add in the LCD output on the 'receiver' device and added reading of the potentiometer on A0 for the value that is transmitted. They have basic examples for send and receive. You can find some good info on their wiki page. Their libraries are available here. On my Mac I created the directory ~/Documents/Arduino/libraries/CAN_BUS_Shield for the library files. I unzipped the file and copied over the .h and .cpp files into that new directory. The zip file also contains the send and receive examples.

Note that normally devices on a CAN bus are both receivers and transmitters of data. This is a simplified example where each device is only doing one task.



Sender code


Receiver code


Video




[Updated 2014-05-25: Noted value of A0 potentiometer in the Fritzing diagram]
[Updated 2014-07-21: Added section about termination resistors]
[Updated 2014-09-25: Added note about incorrect value of resistor R3 on Seeed's shield]
[Updated 2015-03-10: Added additional notes about termination resistors]
[Updated 2017-03-27: Added new section 'Connecting into an existing CAN bus']
[Updated 2018-06-15: Fixed broken links for Seeed-Studio wiki and libraries]



125 comments:

  1. what kind of potentiometer did you use???

    ReplyDelete
  2. Hi
    great little intro into the canBus
    I am trying to communicate with the volvo can bus which uses a longer can Id.
    Do you by any chance know how to change the size of the ID .
    any help would be appreciated.

    ReplyDelete
    Replies
    1. I read through the SeeedStudio mcp_can library and it looks like it supports the longer 29 bit CAN messages. I would recommend trying the generic receive.ino example that comes with their Arduino library and see if that works. Also make sure you are using the correct CAN bus speed for your vehicle.

      Delete
    2. hi Matt, I find it difficult to send CAN messages and send the same messages to serial port. Have you experiences something like this before?

      Delete
    3. jis, I haven't run into that myself. Actually I don't think I have tried doing that. Are you trying to just display the CAN messages on the serial console?

      Delete
    4. yes,i have to send around 10 CAN messages and receive 4 messages periodically.the same need to be displayed on my serial console

      Delete
  3. Good work! I happened to have a J1939 CAN generator and tested it with your code, it works fine. So this CAN shield should definitely work with extended CAN 2.0B or so called J1939 protocol. Just one question I am little bit confused with your code, seems you are using the digital input No.2 as a interruption trigger to read the CAN message,
    How does that happen? was that DI triggered by the CAN shield when it receives something or it has to be controlled by some external wiring?

    ReplyDelete
    Replies
    1. Jason, man I just realized I didn't answer your question and it has been almost a year! Sorry about that. The shield does connect to digital pin 2. The MCP2515 CAN controller chip on the shield has pin called 'INT' which goes low when it has messages in it's buffer to be read. This is used to trigger the interrupt on the Arduino. Digital 2 on the Arduino is configured as an external interrupt which triggers the code to read messages. The CAN-Bus shield is built to be used this way. When all messages have been read from the buffer the line goes high again and the code stops trying to read messages from the CAN controller.

      Delete
  4. Where did you define the id of each arduino?

    ReplyDelete
    Replies
    1. The Arduino's don't have an id. Each CAN bus message contains an id. Line 37 of the sender code contains the id of the message which is '0x7B' in hex or '123' in decimal:

      CAN.sendMsgBuf(0x07B, 0, 8, canMsg);

      CAN bus messages can have any id between decimal 0 and 255. Any device connected to the CAN bus can transmit messages with any id number. If you wanted to identify a particular device as the source of a message then you decide to only transmit certain CAN bus id's from certain Arduino's. The receiver device just listens for all messages on the bus.

      Delete
    2. Is it possible to use the Sparkfun shield with an arduino Mega?

      Delete
    3. I looked through the comments for that board on the Sparkfun site and it seems to be possible if you redefine the SPI pins in the MCP2515 library to use the proper SPI pin numbers for the Mega. The Uno uses 10,11,12,13 for SPI and the Mega uses 50,51,52,53.

      Delete
  5. Hi, this work fine. i havent got seeedstudio can bus shield. i have sparkfun can bus shield. if i use your code, will i run?? thanks

    ReplyDelete
    Replies
    1. It looks like the SparkFun board uses the same CAN bus transceiver and controller chips. I can't say for sure because I don't have one of the SparkFun boards but it might work. It certainly wouldn't hurt anything to try.

      Delete
    2. thanks your answer,
      Did you use 120 ohm resistance in this work??

      Delete
    3. Ah, you bring up a very good point. Yes a CAN bus requires 120 ohm resistors at each end of the bus. The Seeed Studio shields have built termination resistors. They can be disabled by cutting trace P1 or unsoldering resistor R3. If the Sparkfun shields don't have the built in termination resistors you would need to add them to each end of the bus. Thanks for pointing this out. I am going to update this post with that information.

      Delete
  6. Hi, small question. How many pins on the arduino board are used by the seeed shield? I mean, how many digital io and analog ports do I have left to use?
    Thanks

    ReplyDelete
    Replies
    1. The seeed shield communicates over SPI so on an Arduino UNO it uses pins D11, D12, D13 for SPI and D10 for CS. All other pins should be available.

      Delete
    2. I missed something in my previous reply. The Seeed shield also uses Digital pin 2.

      Delete
  7. Great write up Matt, I would like to invite you to my website cansniffer.com please contact me if you ever need any help or products.

    ReplyDelete
  8. Hi Matt McMillan, more or less i am working on a same project. i made a weight scale circuit using strain guages and instrumental amplifier. the output of instrumental amplifier are going to pin A2 and A3 on arduino and if i change the weights i can easily see the values on lcd like 30grams, 40grams,50grams...............

    Now i want to send these values from one can bus shield to another can bus shield.... could you please help me in this regards.

    Regards:
    Tahir Muzaffar

    ReplyDelete
    Replies
    1. Are you wanting to send the weight data from one Arduino to another?

      Delete
    2. yes exactly from one arduino to another using can bus

      Delete
    3. Well my example code above should give you most of what you need. What sort of help are you looking for?

      Delete
  9. a complete code to send the weight data from one Arduino to another !!

    ReplyDelete
    Replies
    1. Sorry man I don't have time to write code for you unless you are going to pay me to do it. Good luck with your project.

      Delete
  10. You lack the initialisation of the can object in both files:
    MCP_CAN CAN = MCP_CAN(10);
    where 10 or 9 is decided by the solder jumper on the board.
    Also CAN is bad naming, since it's an object it should start with a small letter, like can_bus or something.
    Thanks for the rest though

    ReplyDelete
    Replies
    1. Well Mr. Anonymous the initialization objects you are referring to are only used in coryjfowler's MCP2515 library not Seeed Studio's version of the library. This post is using Seeed Studio's library. Also the 'CAN' naming came straight from Seeed's example code so you'll have to take that issue up with them if you want to complain some more.

      Delete
  11. Hi, I've been trying to make this work with a Megasquirt 3 but haven't been successful.
    I'm using an Arduino UNO with your same CAN-Bus shield and I'm trying to send data from the Arduino to the Megasquirt 3. I'm guessing my problem is the termination resistor? Any help?

    ReplyDelete
    Replies
    1. Oh neat. I have an MS3Pro system on my truck but I haven't done anything with the CAN Bus yet. So are you trying to send sensor info to the Megasquirt? I read through the Megasquirt CAN documentation and it says they are running at 500k which would definitely need proper termination. The docs say the Megasquirt board has a 120 ohm termination resistor on it. If you don't have any other CAN devices on the bus (like a jbperf I/O extender) your CAN-Bus shield will need to provide termination for the other end of the bus. Like I mentioned in the blog post, the v1.0 of the Seeed CAN-Bus shield only has a 60 ohm termination resistor so that would need to be removed and you need to add a 120 ohm resistor. I have put the 120 resistor across the screw terminals and screwed it down with the CAN-H and CAN-L wires.

      If you are indeed trying to send CAN info to the Megasquirt, I would recommend first just trying to read the broadcast data to make sure your bus is working properly. You have to enable the CAN broadcast data in your config.

      You may have read through these docs already but if not there is a lot of good info:

      http://www.megamanual.com/com/CAN.htm
      http://www.msextra.com/doc/pdf/Megasquirt_CAN_Broadcast.pdf
      http://www.msextra.com/doc/pdf/Megasquirt_29bit_CAN_Protocol-2015-01-20.pdf

      Delete
    2. I feel so stupid, I was trying to do this without the 2 wires that go inside the megasquirt3 to enable CAN. So after long nights I finally got it working.. Was able to send analog data. NOW my mission is broadcasting data from the megasquirt to the Arduino. For some reason my CanBus shield's Recieving indicator LED and Recieving Int Indicator LED are both always on. The Int Led is brighter though.. I still have the 62 ohm resistor on it. Might it be that???

      Delete
    3. Way cool! Would you mind sharing your Arduino code you are using to send analog data to the megasquirt3? I'm very interested. That 62 ohm resistor could be causing problems. I would recommend removing the 62 ohm resistor and use a 120 ohm. Having different resistor values at each end of the bus is going to cause weird behavior.

      Delete
  12. This comment has been removed by the author.

    ReplyDelete
  13. Thank you for the great tutorial. Do you have any suggestions to send a CAN message with the full 1024 but resolution of the analog input pin instead of dividing it by 4?

    ReplyDelete
    Replies
    1. The simplest thing to do is use two bytes. You use one byte to store the number of times the other byte has rolled over past 255. This give you the ability to store a number up to 65,280 in two bytes.

      For example a value of 925 would be stored in a CAN message as:
      [160, 3, 0, 0, 0, 0, 0, 0]

      To get the value out it would be (3*255)+160

      Does that make sense?

      Delete
  14. Hi me again. I was wondering what CAN library are you using. Cause I see in your Reciever code you have #include "mcp_can.h" instead of .... I don't know if this makes a difference. But i'm interested to know because your code is the only one I find online that seems to work in your video and also you answer to your posts pretty quick. Been looking for help and you seem to be the only one answering so thank you!

    ReplyDelete
    Replies
    1. I this post I used the library published by SeeedStudio which can be downloaded here: https://github.com/Seeed-Studio/CAN_BUS_Shield

      In other posts on my blog I switched to CoryJFowler's fork of the library which can be downloaded here: https://github.com/coryjfowler/MCP_CAN_lib

      Cory's fork adds the ability to declare the CS pin in the code versus editing the library.

      Either one is included by using the statement #include "mcp_can.h"

      Delete
    2. do you mind explaining what this: "#define INT8U unsigned char" and this "INT32U canId = 0x000;" do in the code? I'm having trouble understanding it...

      Delete
    3. This code came from Seeed Studio's examples and all I did was modifiy the receiver code to output to an lcd display. Seeed used syntax that is more C specific syntax than 'Arduino' syntax.

      The line "INT32U canId = 0x000;" creates an unsigned integer variable 32 bits in size and fills it with the hex value of 0x000. Most Arduino coders would probably use the 'unsigned long' variable type instead of INT32U but they do the same thing. I think specifying the the bit size makes the code more portable.

      As for "#define INT8U unsigned char"... looking at the code again now that actually is not needed at all. lol. Must be something left over from Seeed's code that I removed when I modified their example code. This again is C code that being very specific about the size of the variable.

      That is my best understanding of those lines of syntax. Take that with a grain of salt as I am a hobbyist/terrible programmer!

      Delete
    4. That's ok. I just wanted to make sure. Thanks a lo for the help. I'm still waiting for my 120 ohm resistor to arrive to see if I'm able to send data from the Megasquirt to the Arduino. I'll keep you posted!

      Delete
  15. This comment has been removed by the author.

    ReplyDelete
  16. Hi Matt, do you know why im not getting any data to my CAN bus sniffer?

    I have a UNO and the shield https://www.sparkfun.com/products/10039 - i read this post and added a 120 ohm resistor to both the High and Low but this made no

    ReplyDelete
    Replies
    1. Mark are you connecting into a CAN bus in a car? If so you most likely don't need the 120 ohm resistor. Have you tried different CAN bus speeds?

      Delete
  17. I have a question:-
    We're working with an ECU, with a datasheet of data and message IDs. We wanna get the speed from the ECU, we can get the correct message ID and the bits that we need. We're unsure on how to calculate the speed though.

    Here is the information about the speed:
    Data is in big endian format.
    Message ID: 0x00200080
    Byte 6-7 are for speed.
    Bits 7-0

    Vehicle Speed
    Resolution: 1/256 MPH/bit, 0 offset
    Data Range: 0 to 255.996 MPH

    Any ideas?

    ReplyDelete
    Replies
    1. Can you post a few of the messages from a capture while the vehicle is moving? I like to watch the data change in the CAN Bus messages while comparing it to the readings on the gauge in the dash.

      Delete
  18. hi.
    really good post and realy helpfull for me.
    may i ask to you some quetion??
    in your post. the sender ID is 123. can i change it with another value ID??

    ReplyDelete
    Replies
    1. Yes you can change the CAN id. The possible values for 11 bit CAN id's are hex 0x000 through 0x7FF (decimal 0 to 2047).

      Delete
  19. Hello man

    I want to do a connection between the arduino due and the Bus-can shield, to receive the information of position of a servomechanism,What code do I have to use?

    Thanks

    ReplyDelete
  20. Hey Matt,
    Can i connect a Adafruit 1480 - Graphical LCD, using SPI on the Seeedstudio CAN shield. Both uses SPI, but what changes should I make in the code. Will it automatically set slave select for the LCD and shield and do a good job?

    Thanks

    ReplyDelete
    Replies
    1. You can connect multiple devices to the SPI bus but each one needs a separate SS pin. Your code will need select which device you are talking to and you will only be able to talk to one device at a time. Probably something like:
      1. enable SS for CAN shield
      2. read can data
      3. disable SS for CAN shield
      4. enable SS for LCD
      5. update LCD with new speed
      6. disable SS for LCD

      Delete
    2. damn i wish i could upvote the comments/replies here :)
      i, being a noob, find these super-simple snippets of info extremely valuable, even if just to confirm i got it right

      Delete
  21. Hello,
    wondering if you can help me out with my project.

    I'm sending various Messages with different id's and I cant find out how to do some maths for a message with on ID and do another mathematical approach for a second ID; my data i think is getting mixed together. Any pointers?

    ReplyDelete
  22. Hi, i can try that tutorial but, i haven't been succesfull. I can't run. I have two SeedStudio Can bus shield and two arduino uno. I cut trace P1 with knife. I can use SeedStudio Library for can bus. Unfortunately, it can't run. So, The Rx and Tx led disabled on the can-bus shild. I load send and receive program. But the rx and tx led light isn't not. Could you help me? Thanks..

    ReplyDelete
  23. Hello, and congratulations for the guidance , it is really very useful .
    I would saere if you can send multiple messages simultaneously on the line can
    It is whether this is possible , how?

    ReplyDelete
    Replies
    1. Multiple devices can broadcast on the bus at the same time. Just use different CAN id's for each device.

      Delete
    2. Thank you for your reply!
      if I wanted to send this message:

      ID -DLC - DATA
      215 -4 -FF FF FF F0
      35D -8 -00 03 20 00 FF 00 50 00



      I should write more often this into void loop? for example:

      void loop()
      {
      tCAN message;

      message.id = 0x215;
      message.header.rtr = 0;
      message.header.length = 4;
      message.data[0] = 0xFF;
      message.data[1] = 0xFF;
      message.data[2] = 0xFF;
      message.data[3] = 0xF0;


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

      delay(1000);

      tCAN message;

      message.id = 0x35D;
      message.header.rtr = 0;
      message.header.length = 8;
      message.data[0] = 0x00;
      message.data[1] = 0x03;
      message.data[2] = 0x20;
      message.data[3] = 0x00;
      message.data[4] = 0xFF;
      message.data[5] = 0x00;
      message.data[6] = 0x50;
      message.data[7] = 0x00;

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

      delay(1000);

      thank you so much.

      Carmine


      Delete
    3. Not exactly sure what you are trying to do but you can reduce those delays way down to like 10 ms if you want to blast the bus with tons of those messages.

      Delete
  24. hello, I have a question:
    if you wanted to convey this:
    ID = 0618A001 (hex)
    DLC = 8
    Message = 00 16 03 68 16 0F 52 00
    how could I do?
    if I run the program made available to you, it reads only the last three digits (in this case 001).
    Thanks for the attention

    ReplyDelete
    Replies
    1. You are using an extended (29 bit) CAN id. You need to set the extended ID flag. I have a different blog post that talks about how to use them: http://matthewcmcmillan.blogspot.com/2015/02/arduino-can-bus-and-29-bit-extended-ids.html

      Delete
  25. Hey Matt, really thanks for your effort and tutorial, it's been really helpful! May I ask you something? Can you provide a simple code for RTR message events? For example the sender sends an RTR request, the receiver reads that, sends the response back to sender and the sender reads the response.

    Thanks!!!!

    ReplyDelete
    Replies
    1. Sorry I haven't worked with RTR messages so I don't know much about them.

      Delete
  26. Hi, I'm using the Seeed CAN Bus shield with Arduino UNO and the https://github.com/Seeed-Studio/CAN_BUS_Shield library.

    The programs for send and receive from the CAN data bus work well, however I can't do a request for a specific PID value. Is this possible do it? If so, can you advise me on how to do it?

    ReplyDelete
  27. So you just have the two Arduinos connected with an OBD-II to OBD-II cable? It's not clear in the pictures, and looks more like USB cables...

    ReplyDelete
    Replies
    1. No, they are connected together with a CAN bus which is a pair of twisted wires with 120 ohm resistors at each end. OBD-II is not the same thing as CAN. OBD-II is a diagnostic port used in cars.

      https://en.wikipedia.org/wiki/CAN_bus

      https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/CAN-Bus_Elektrische_Zweidrahtleitung.svg/1000px-CAN-Bus_Elektrische_Zweidrahtleitung.svg.png

      Delete
  28. I am using can bus controller which is not a stand alone.Apart form spi connections is there any connection for the interrupt pin in the can bus controller

    ReplyDelete
  29. Hi Matt, I know this post is from a few years ago but I was hoping you would be able to answer some questions and help me out.
    I am interested in this post because I work for a vehicle manufacturer and we are looking into arduino boards to simulate a CAN much as you have done here, the reason we would like to do this is to create an inexpensive CAN test rig to show our mechanic's how CAN work's. Is it possible to know:
    Does the CAN network have the normal 2.5V on both the CAN High & Can Low wires?
    Does the CAN network have 120Ohm terminating resistors (Do a resistance check between CAN Hi & CAN Low, should be 60 Ohm if it has 2 120Ohm.
    If so, are they removable?
    Also if the resistor's are not in place, have you noticed any ghosting where a signal would be sent over and over as it goes back around the CAN Lines (this is what the resistors are for)

    What we want to do is have a CAN circuit where we can show the mechanic's the resistance and also show them the Voltage, we also would love to be able to remove the resistor's and press a button once on one of the nodes and see it ghost on the other node.

    Thank you if you can answer any of the above.

    ReplyDelete
    Replies
    1. That sounds like a fun project. I actually built something similar to what you are describing for the company I work for. I wrote a couple blog posts about it on Medium if you want to check those out:

      https://medium.com/silvercar-technology/how-do-you-fit-an-audi-a4-on-a-developer-s-desk-part-1-6788369a048b#.hfx5nu8b9

      https://medium.com/silvercar-technology/how-do-you-fit-an-audi-a4-on-a-developer-s-desk-part-2-4af854aa3ec8#.ti691ykhs

      To answer your specific questions:

      Q: Does the CAN network have the normal 2.5V on both the CAN High & Can Low wires?
      A: Yes, this circuit uses a 5v differential between CAN High and CAN Low.

      Q: Does the CAN network have 120Ohm terminating resistors (Do a resistance check between CAN Hi & CAN Low, should be 60 Ohm if it has 2 120Ohm.
      A: Yes it does have 120 ohm termination resistors on the ends of the bus with 60 ohm resistance when measured across high and low.

      Q: If so, are they removable?
      A: Depends how you build the device. If were to design something like that I would put a switch on it that could disable the termination resistor.

      Q: Also if the resistor's are not in place, have you noticed any ghosting where a signal would be sent over and over.
      A: At a bus speed of 100k I didn't see a lot of ghosting. At 500k it was pretty noticeable.

      Let me know if you have anymore questions.

      Delete
    2. Thank you very much for the answer, I will look into getting the arduino set up and may be back with a question or two in the future, thanks again!

      Delete
    3. simonkeeligan@tiscali.co.ukOctober 29, 2016 at 11:52 AM

      hi i have tried using the code you wrote to get my project working but when i try to verify its says CAN was not declared but i have copied the mcp_can.h into the library can you help ?
      cheers
      simonkeeligan@tiscali.co.uk

      Delete
    4. Simon,

      What version of the Arduino IDE are you using?

      Delete
  30. Hi I am having a trouble ... as am using my CAN shield in Loopback mode then I am receiving the msgs transmitted but am getting 'error sending message' in Normal mode when i tried to send data.... i am using CoryJFowler's librar of can shield..... can anyone please help what wrong with it????????

    ReplyDelete
    Replies
    1. Same here with the same library. The messages however gets through as I can see it on oscilloscope.

      Delete
    2. I figured it out. Just connect the receiver and you'll get the "Message sent successfully".

      Delete
  31. Hello
    very good a prototype for CAN communication

    How can we connect 3 nodes on CAN bus, question about cables ?
    Do the node in the center have 2 CAN shields, one for communication with node1 and 1 for communication with node3 ?
    Or something like a hub is necessary ?

    best regards
    Joel
    jmelan@free.fr

    ReplyDelete
    Replies
    1. No hub is needed. Each device can just tap into the bus. Take a look at this diagram: https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/CAN-Bus_Elektrische_Zweidrahtleitung.svg/2000px-CAN-Bus_Elektrische_Zweidrahtleitung.svg.png

      Delete
  32. can i send and receive using a single arduino at a time?, and can you provide me with the code

    ReplyDelete
  33. Hello
    (Noob question incoming, excuse me, I have started few days ago... :)
    Given the CAN-Bus shield utilizes D2,D10,D11,D12,D13, I assume I can't use it together with SD-card which connects to some of the same pins...? (This is how I connected the card: https://youtu.be/sS_oW81NweI?t=2m2s Works fine when tested without the shield wired to the ODB2-port.)
    I find it hard to believe one couldn't use both at the same time. I intended to log the CAN-Bus data onto the card.

    ReplyDelete
  34. I think I might have found the answer to my previous (not approved yet) question about possible collisions between multiple devices using the same pin.
    http://bit.ly/2lq7rjq

    ReplyDelete
    Replies
    1. Yes you need to use the SS pin to only talk to one SPI device at a time. The CAN controller has a bit of a buffer so you should be able to switch back and forth between writing to the SD card and reading from the CAN controller.

      Delete
  35. Hello
    Regarding your note about disabling the R3 resistor, does it mean one *has to* do this when connecting to a car? Or does it rather mean "I feel it would be better to do it?"
    I am unable to read any messages whatsoever, becoming rather desperate at this point. :) Do you think this could be related?

    I see RX LED blinking like crazy, the shield is initialized, yet I am getting no messages whatsoever... Sometimes the car behaves funny, despite my code including no sending of messages, merely listening. I tried several speeds, sticking to 500kbps lately just because all info I could find points to 500 being the correct one.

    Cheers

    ReplyDelete
    Replies
    1. If you are connecting to a vehicle you must disable the termination resistor R3. The vehicle already has the proper termination resistors on its bus. By adding your device with an additional termination resistor you are disrupting bus communication even without transmitting data.

      Delete
    2. !!! That was indaed one half of my issues! That, and also I had to connect GND (signal GND, i.e. pin 4 on the OBD-II access port)... Please consider adding that to your note about connecting to an existing in-car bus. And thanks a lot sir!

      Delete
    3. Glad you figured it out. In the section above labeled 'CAN bus termination' there is already text that says "If you plan on connecting into an existing CAN bus that already has termination you can disable the built in termination resistors."

      Delete
    4. I meant the GND part, which was the last obstacle for me.
      cheers :)

      Delete
    5. Ah, gotcha. Yep I'll add a note about having a common ground.

      Delete
  36. Hello!

    Great manual you've made here :)

    I have a question regarding "the resistor" (sounds kinda dark, isn't it? ;) ). So, I have a canbus shield by elecfreaks. It has 62Ohm resistor onboard.

    I'm able to read the data from Fiat & VW canbus net using it.

    Now, I've pulled the instrument cluster out from my Panda, gave it 12V, CAN from can shield, wrote some messages and... nothing happend. Either the cluster is not reactin (eg. for fuel level or speed), nor the shield isn't receiving anything from the instrument (I think it's supposed to, as the cluster need to verify car status).

    So, I've cut the jumper metioned by you. Still no luck. The bus' speed is set correctly (50kbps).

    Can you please help figure this out?

    Thank you in advance and best regards.
    Tom

    ReplyDelete
    Replies
    1. Since the instrument cluster is removed from the car you do not have a complete CAN bus with proper termination. You will need to add termination. You might be able to get away with just putting a 120 ohm resistor across the screw terminals on the CAN bus shield. If that doesn't work you will need to have 120 ohm resistors at the both ends of the CAN wires.

      Oh! one other thing that might be an issue... you need to have a common ground connection between the Arduino and the instrument cluster.

      Hope this helps.

      Delete
  37. Hi man really great work.

    My question is, do u think the library or your Code works for two Arduino Micros with the "Niren MCP2515 CAN interface" shown here: (http://shelvin.de/wp-content/uploads/2016/11/MCP2415-1000.jpg). It works with the MCP2515 however the CAN transceiver is a TJA1050.

    So there are two differences to your project: 1. The Arduino Micro 2. The CAN transceiver

    Thx for your work m8!

    ReplyDelete
    Replies
    1. The library only interacts with the MCP2515 CAN controller and it shouldn't notice a different transceiver. I haven't used any of the ATmega32u4 type boards (like the Micro). The library talks to the MCP2515 over SPI which the Micro does have. I guess in summary I would say I don't know for sure if the library will work as-is but I would say you have a good chance. If it doesn't work as-is it probably would just require a bit tweaking to get it to work on the Micro.

      Delete
    2. Thanks for your answer but unfortunately it doesn't want to work..
      I used the examples (Send and receive_check) brought with the GIT ZIP-file from Seedstudio.
      Do you maybe have any idea what changes i may have to make? I tried to look for some PIN configuration for SPI (maybe they defined some PINS fitting for the UNO but not my micro) but I didn't find such. Also I am sure that my termination is right.

      Delete
  38. Great work,

    Do you know how to communicate with two master and one slave. Can I just make in the slave program something like ...if(id=master1){do something}..else if(id=master2){do something}
    Should I set up some other parameters?
    Thanks

    ReplyDelete
    Replies
    1. There isn't really a concept of masters and slaves on a CAN bus. Any node can transmit any CAN id and all nodes recieve all CAN messages. You could accomplish what you are describing by deciding on CAN id numbering scheme for each the 'master' nodes.

      Delete
  39. Hi,
    thank you for sharing your work.
    I've a question: where's the right connection for the signal ground (Arduino Shield side)?
    I used the GND pin on the DB9 connector without any issue (see https://raw.githubusercontent.com/SeeedDocument/CAN_BUS_Shield/master/image/OBD.png), but it seems wonky.

    ReplyDelete
  40. Hi, Matt. Thank you for your post. I am trying to communicate to Arduinos UNO with Elecfreaks shields and when trying to download the library from Seeed, I get a message saying that it no longer exists. I downloaded the library from GitHub, that contains two files mcp_can.h and mcp_can_dfs.h and when I compile your Sender program I get an error saying CAN was not declared in this scope. I am using an Arduino IDE version 1.8.2. Please, could you provide some help? Thanks in adavance!

    Fernando.

    ReplyDelete
    Replies
    1. Check out this fork of the Seeed's can bus library: https://github.com/coryjfowler/MCP_CAN_lib
      Start with the examples in examples directory. My code here is based on an older version of the can bus library and may not compile anymore. Also the newer version of the Arduino IDE are much more strict on variable scope. You can try using an older version of the IDE or you will have to fix the code so things are properly scoped.

      Delete
    2. (Sorry for replying while not being Matt :)
      I am assuming we are both using the same library: https://github.com/Seeed-Studio/CAN_BUS_Shield

      If that is the case maybe I could help. This is how I inialize my CAN-Bus shield from Elecfreaks: https://pastebin.com/f51kg1Rr
      connectCanBus() shouuld be of your interest

      There is some extra functionality that you can ommit, I guess you should be able to extract from it what you need. Let me know if you need some assistance.

      Delete
    3. OK, thank you very much for your help.

      Delete
  41. hi matt, can you ask it to read specific bytes when reading can messages? for example i want to read ID608 byte 3 and 4.

    ReplyDelete
    Replies
    1. In this example the data is stored in an array named 'buf'. It's a zero based array so the number starts at zero. So byte 3 would be buf[2] and byte 4 is buf[3].

      Here is some abbreviated code that should point you in the right direction:

      CAN.readMsgBuf(&len, buf);
      canId = CAN.getCanId();

      if (canId == 608 ) {
      Serial.print("Byte 3: "); Serial.print(buf[2]);
      Serial.print("Byte 4: "); Serial.print(buf[3]);
      }

      Delete
  42. Hii Matt, can you help me with my problem. I'm using the code and when I sent messages from one arduino to the second arduino everything works great. Now I connected my arduino to an industrial joystick but the messages are empty and it stops after two messages. My serial monitor says this


    -----------------------------
    Get data from ID: 703
    0
    -----------------------------
    Get data from ID: 83
    0 0 0 0 0 0 0 0

    thats all.

    i hope you can point me on the right direction

    ReplyDelete
    Replies
    1. Hard to say what the issue might be. Seems like the CAN controller is going into an error state. I would try it without the joystick and see if it works. That will tell you if the addition of the joystick causes an issue. Then you can start tracking down why the joystick causes problems.

      Delete
    2. Hii Matt thanks for your reply, I really don’t know at this point. As soon as I send over 2 arduinos everything works fine. Right now I’am stuck with the joystick.

      Can it be related to the fact that the joystick isn’t in operational mode. What I read before was that, as soon as I plug my joystick in it goes in the pre operational mode. I need to send a message to put the joystick in a operational mode.

      NMT command code: 0x01
      Meaning: go operational

      I do not know if it has anything to do with it, its my first can related project.

      I am now stuck in implementing the sending option (for nmt commands) in my receive code. Although I do not know if this will help. For now I am searching for a solution.

      Delete
    3. Hi PhotoUnique. Did you manage to sort out the joystick issue?

      Delete
    4. Hi PhotoUnique. Did you manage to sort out your joystick related issue?

      Delete
    5. Hi Mohib

      Yes i did, I adjusted the code with some commands. After the init my codes sends a 0x01 to all nodes. The joysticks switches to the operational mode. I also activated the heartbeat mode on the joystick with a special command. Now I can read the hex values of the joystick.

      I have written a test program to test my industrial joystick.

      Delete
  43. Hi Matt
    Very glad you seem to be still with this. Many thanks so far.
    And to further it, i read your code up to the point where you divided the analogread(potpin) by 4 to fit it in the CAN-bus one-byte messaging and i must have died a bit (or a byte). I read your response to the question here and to count the number of 255's more than there are after the first byte, put that in the second byte is good... but my real world needs a bit more. (tempted.. too tempted.. a byte more).

    I have got a long way towards building a whole ECU simulator so as to send to a ELM327 and bluetooth, numerous engine sensors that aren't usually available at the dashboard. So with Android Torque i will display Exhaust Gas Temperature, Cylinder Head Temperature and (actual) Engine Coolant Temperature on my Land Rover Discovery TD5.
    I read on Medium about your project to put an Audi A4 on the workbench. (Is that code available, even for perusal?) I'm putting the "simulator" with real sensors in the car and CAN-busing the data to Android (cos the Torque frontend is done and nice). The car uses K-line throughout variously seven control units and none of the PIDs are published (2001MY), they're kind of unknown and actually incomplete for me; Exhaust Gas and Cylinder Head temperatures are on my own thermocouples and are foreign to Land Rover which doesn't measure those specifically. Engine Coolant Temperature, although on the analogue meter on the dash board is notorious for being a near binary and is either half-way or FSD (full scale deflection), a function of the engine ECU. I will use the NTC but not the TD5 ECU. (Splitting the NTC, Tee'ing off it, is another thread; Atmel will have no (real) effect on the NTC voltage, given the ECU must put its 10k series R with it across 5V).

    My problem for which i want help, is parsing the sensor data from analogread int and byte variables to the byte* etc required for the CAN-bus library to successfully build and send a CAN-bus message out of the Seeed Shield.

    Its a language problem more than anything for me i think. This compile error (maybe in various guises) doesn't go away regardless of what i do with and without low/highByte() >>8 &00FF etc etc... in the case of int.


    quote"
    Error compiling project sources
    TD5_Engine_Sensors.ino: 442:38: error: invalid conversion from 'int' to 'byte* {aka unsigned char*}' [-fpermissive]
    Debug build failed for project 'TD5_Engine_Sensors'
    CAN.sendMsgBuf(0x7E8, 0, PID_EGT, EGT)

    TD5_Engine_Sensors.ino:37: In file included from

    mcp_can.h: 126:10: error: initializing argument 4 of 'byte MCP_CAN::sendMsgBuf(long unsigned int, byte, byte, byte*)' [-fpermissive]
    byte sendMsgBuf(unsigned long id, byte ext, byte len, byte *buf); \\ send buf
    "end quote.

    the full code is here https://eightyeight.000webhostapp.com/#td5-engine-sensors . My website there is barely up and running.. it was and will be again "up" properly at eightyeight.co.uk, more threads for later.

    if you could have a look and see how bad it is let me know. - i just had a quick glance through again and notice some comments aren't aligned with as is, for example the round(egt) comment says its an integer, but it has since changed, declared as byte; the comment precedes the coding - all part of the effort to get the CAN.message builder to compile. In the final comments, i also say we need only mode 2 comss, Mode 1 comms only of course, for live dynamic data; just a typo.

    Any thoughts greatly appreciated, i understand (completely) if i hear nothing back!

    BTW FWIW I use Atmel Studio 7 environ with Arduino IDE sideways- i question now why and even why i prefer it, but i do, unknown if or how it affects (anything).

    Many thanks
    Greg

    ReplyDelete
    Replies
    1. Unfortunately I can't share the code from my Audi A4 simulator. It's something I built for work. I'll try and take a look at your code and see if I can figure anything out.

      Delete
  44. Thanks Matt, NP.
    I have done a long stint on the code for the arduino ECU sim and having 'started again' i have made something that at least compiles (its nothing like even marginally functional yet)..
    it'll be much easier for you to look at the newer stuff, lots less of the other stuff that either works, has yet to be considered, or will work only later.

    newer code here: http://eightyeight.co.uk/#can_engine_sensors

    sprintf and scanf seem most likely will be a big part of the solution to parsing the CAN byte orientated messages. The string formatters compile for Uno but whether they will do as required i have no idea. They didn't compile for Due, but that's not at all important for me (after a day's hacking around with code). The stdio and iostream libaries are not equivalent across AVR and SAM boards.

    I love your 3D printed lights, really good. I am looking for some lighting to go in the garden; how might the printed filament hold up in full sun (Really, really full sun, i live 27ยบ north latitude, Canary Islands, similar to Orlando, Fl probably.

    ReplyDelete
  45. Hi Matt. Great work you doing here.

    Lets say I had 4 Potentiometers and they need individual communication. can I use a single can shield on a single Arduino and assign them different addresses, or will i need 4 shields on 1 Arduino (if that's possible even), or will i need 4 of the above setup?

    ReplyDelete
    Replies
    1. You can build this with just one CAN shield. Just like you mentioned, you could use four different CAN id's to represent each of the potentiometers. You could also use just one CAN id and assign bytes in the payload for storing the potentiometer data. For example pot1 uses byte 0, pot2 uses byte1, etc.

      CAN id's aren't tied to hardware. One device (shield) can write data to the bus with as many CAN id's as you would like. The only thing you want to avoid is having two different devices write data to the bus using the same CAN id.

      Delete
    2. Thanks a heap Matt. You are the best.

      Delete
  46. Hi Matt,

    Thanks for your post.

    I am working on something. I want to send the CAN messages wirelessly using LoRa to another CAN BUS connected to the receiver LoRa. I am using a multiprotocol shield to connect the CAN Bus and LoRa for each Module.

    Do you have an ideal how can I get the message from the CAN bus to the LoRa for transmittion using the SPI.

    Thanks
    Akpo

    ReplyDelete
  47. Hi Matt

    I keep getting "init fail" when i use the code. I have tried the codes above and also those from the seeed studio library.

    I am using an Arduino uno and seeed studio can bus shield v1.2.

    Any sugestions of what might be wrong?

    ReplyDelete
  48. Hi Matt

    I am trying to figure out how to include the Destination Address in the CanBus message using the Arduino Libraries?

    I am trying to interface to an industrial CanBus implementation and am trying to send the following message;
    Prior PGN SA DA DLC Data
    6 59904 254 255 3 0x4B 0x9C 0x00

    The Hex data would be
    0x18EAFFFE FF 3 40 9C 00

    I just can'f figure out to include the destination address 255 (0xFF) using the CAN.sendMsgBuf() function.

    Thanks!

    Darel

    ReplyDelete
  49. Hi Matt,
    Thank you for good work. My question is how we can send the sensor data on hexadecimal ?
    with regards.

    ReplyDelete
  50. Hi Matt,
    I have an ARDUINO UNO with the Elecfreaks CAN-BUS shield V1.2
    I wired the CAN-H and CAN-L to pins 6 and 14 in my car's OBDII connector and connected also pin 5 to ARDUINO's GND
    I cut the P1 trace and measured 60ohms between CAN-H and CAN-l while connected to the car

    Unfortunately the Tx and Rx LEDs are not flashing
    I changed the MCP pin to 10 instead of 9 and that only got me that the shield init is OK, but nothing is received
    I tried all the supported baud rates, but still no luck
    I have only one ARDUINO UNO and one CAN-BUS shield

    Is there anything else I can do? I'm stuck!!!

    ReplyDelete
    Replies
    1. Hello Ahmed, i have the same problem like yours. Did you find any solution for that?

      Delete
    2. Yes. I'm now communicating to the CAN bus.
      First, the Tx and Rx LEDS are still not flashing even the communication is working.
      Second, I found that I was not connected to the CAN bus by connecting to OBDII connector, rather I was connected to an intermediate firewall, so I tapped into the CAN bus after I checked the car's wiring diagram.

      Delete
  51. Hello,

    The libraries link is not available.

    ReplyDelete
  52. Hi, you have used void MCP2515_ISR() in the receiver side code. Is it a function or interrupt. If it is a function, you have not called anywhere else in the program. Can you please explain about it.
    Thanks.

    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.