Arduino Uno R3 | Seeed 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]
what kind of potentiometer did you use???
ReplyDeleteIt's a Philmore 10k ohm linear potentiometer.
DeleteHi
ReplyDeletegreat 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.
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.
Deletehi Matt, I find it difficult to send CAN messages and send the same messages to serial port. Have you experiences something like this before?
Deletejis, 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?
Deleteyes,i have to send around 10 CAN messages and receive 4 messages periodically.the same need to be displayed on my serial console
DeleteGood 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,
ReplyDeleteHow 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?
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.
DeleteWhere did you define the id of each arduino?
ReplyDeleteThe 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:
DeleteCAN.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.
Is it possible to use the Sparkfun shield with an arduino Mega?
DeleteI 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.
DeleteHi, 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
ReplyDeleteIt 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.
Deletethanks your answer,
DeleteDid you use 120 ohm resistance in this work??
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.
DeleteThank you Matt McMillan
DeleteHi, 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?
ReplyDeleteThanks
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.
DeleteI missed something in my previous reply. The Seeed shield also uses Digital pin 2.
DeleteGreat 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.
ReplyDeleteHi 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...............
ReplyDeleteNow 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
Are you wanting to send the weight data from one Arduino to another?
Deleteyes exactly from one arduino to another using can bus
DeleteWell my example code above should give you most of what you need. What sort of help are you looking for?
Deletea complete code to send the weight data from one Arduino to another !!
ReplyDeleteSorry 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.
DeleteHow can I contact u
ReplyDeleteYou can message me on Twitter @matthewmcmillan
DeleteYou lack the initialisation of the can object in both files:
ReplyDeleteMCP_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
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.
DeleteHi, I've been trying to make this work with a Megasquirt 3 but haven't been successful.
ReplyDeleteI'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?
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.
DeleteIf 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
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???
DeleteWay 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.
DeleteThis comment has been removed by the author.
ReplyDeleteThank 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?
ReplyDeleteThe 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.
DeleteFor 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?
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!
ReplyDeleteI this post I used the library published by SeeedStudio which can be downloaded here: https://github.com/Seeed-Studio/CAN_BUS_Shield
DeleteIn 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"
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...
DeleteThis 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.
DeleteThe 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!
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!
DeleteThis comment has been removed by the author.
ReplyDeleteHi Matt, do you know why im not getting any data to my CAN bus sniffer?
ReplyDeleteI 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
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?
DeleteI have a question:-
ReplyDeleteWe'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?
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.
Deletehi.
ReplyDeletereally 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??
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).
DeleteHello man
ReplyDeleteI 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
Hey Matt,
ReplyDeleteCan 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
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:
Delete1. 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
damn i wish i could upvote the comments/replies here :)
Deletei, being a noob, find these super-simple snippets of info extremely valuable, even if just to confirm i got it right
Hello,
ReplyDeletewondering 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?
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..
ReplyDeleteHello, and congratulations for the guidance , it is really very useful .
ReplyDeleteI would saere if you can send multiple messages simultaneously on the line can
It is whether this is possible , how?
Multiple devices can broadcast on the bus at the same time. Just use different CAN id's for each device.
DeleteThank you for your reply!
Deleteif 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
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.
Deletehello, I have a question:
ReplyDeleteif 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
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
DeleteHey 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.
ReplyDeleteThanks!!!!
Sorry I haven't worked with RTR messages so I don't know much about them.
DeleteHi, I'm using the Seeed CAN Bus shield with Arduino UNO and the https://github.com/Seeed-Studio/CAN_BUS_Shield library.
ReplyDeleteThe 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?
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...
ReplyDeleteNo, 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.
Deletehttps://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
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
ReplyDeleteHi 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.
ReplyDeleteI 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.
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:
Deletehttps://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.
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!
Deletehi 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 ?
Deletecheers
simonkeeligan@tiscali.co.uk
Simon,
DeleteWhat version of the Arduino IDE are you using?
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????????
ReplyDeleteSame here with the same library. The messages however gets through as I can see it on oscilloscope.
DeleteI figured it out. Just connect the receiver and you'll get the "Message sent successfully".
DeleteHello
ReplyDeletevery 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
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
Deletecan i send and receive using a single arduino at a time?, and can you provide me with the code
ReplyDeleteHello
ReplyDelete(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.
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.
ReplyDeletehttp://bit.ly/2lq7rjq
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.
DeleteHello
ReplyDeleteRegarding 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
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!!! 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!
DeleteGlad 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."
DeleteI meant the GND part, which was the last obstacle for me.
Deletecheers :)
Ah, gotcha. Yep I'll add a note about having a common ground.
DeleteHello!
ReplyDeleteGreat 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
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.
DeleteOh! 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.
Hi man really great work.
ReplyDeleteMy 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!
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.
DeleteThanks for your answer but unfortunately it doesn't want to work..
DeleteI 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.
Great work,
ReplyDeleteDo 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
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.
DeleteHi,
ReplyDeletethank 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.
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!
ReplyDeleteFernando.
Check out this fork of the Seeed's can bus library: https://github.com/coryjfowler/MCP_CAN_lib
DeleteStart 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.
(Sorry for replying while not being Matt :)
DeleteI 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.
OK, thank you very much for your help.
Deletehi matt, can you ask it to read specific bytes when reading can messages? for example i want to read ID608 byte 3 and 4.
ReplyDeleteIn 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].
DeleteHere 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]);
}
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
ReplyDelete-----------------------------
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
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.
DeleteHii 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.
DeleteCan 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.
Hi PhotoUnique. Did you manage to sort out the joystick issue?
DeleteHi PhotoUnique. Did you manage to sort out your joystick related issue?
DeleteHi Mohib
DeleteYes 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.
Hi Matt
ReplyDeleteVery 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
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.
DeleteThanks Matt, NP.
ReplyDeleteI 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.
Hi Matt. Great work you doing here.
ReplyDeleteLets 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?
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.
DeleteCAN 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.
Thanks a heap Matt. You are the best.
DeleteHi Matt,
ReplyDeleteThanks 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
Hi Matt
ReplyDeleteI 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?
Hi Matt
ReplyDeleteI 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
Hi Matt,
ReplyDeleteThank you for good work. My question is how we can send the sensor data on hexadecimal ?
with regards.
Hi Matt,
ReplyDeleteI 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!!!
Hello Ahmed, i have the same problem like yours. Did you find any solution for that?
DeleteYes. I'm now communicating to the CAN bus.
DeleteFirst, 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.
Hello,
ReplyDeleteThe libraries link is not available.
Thanks for letting me know. I fixed the links.
DeleteHi, 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.
ReplyDeleteThanks.