Cheap & simple MCP2551/MCP2515 CAN BUS set up

I've been playing around with CAN BUS, with a view to using it for home automation, mainly because it seems a really cheap way of off-loading communications to another device, freeing up the Arduino to do whatever in the meantime. The main problem I've had is the shortage of documentation and simple beginners sketches to start off with. I built two breadboard copies of the Seeeduino CAN-BUS Shield (http://www.seeedstudio.com/wiki/CAN-BUS_Shield) using two Nano Arduinos. CS is shown as selectable, but I used D10 and it works fine, 16MHz crystal with 2x22pf capacitors and 2x 0.1uF capacitors, one across each chip's supply as decoupling, and a random 330 Ohm resistor I had laying around as CAN-BUS terminator!

The Seeduino CAN-BUS Shield library does not work properly, and neither do the examples! Or at least I couldn't get them working initially in Arduino IDE 1.0.1. Fortunately the debugging in the compile window at the bottom of the Arduino IDE is pretty good, and I found that this was enough to help me correct the odd mistakes made there. I had to re-write the Receive example, as the contents of the original seem intended to do something completely different!

I hope this helps someone; it's far from being a complete network, but from reading the MCP2515 datasheet it looks relatively straightforward to implement Masks and Filters. If you can't be bothered to do that you could use the Arduino to do the filtering instead and just use the cheap hardware to do the receiving, buffering and CRC etc.

Seeduino CAN-BUS Shield clone Send.ino

#include "mcp_can.h"
#include 

unsigned char stmp[8] = {0, 1, 2, 3, 4, 5, 6, 7};

void setup()
{
  delay(5000);  // delay to allow me time to open the serial monitor window to check all is well
  Serial.begin(9600);
  if(CAN.begin(CAN_500KBPS) ==CAN_OK)  //check the Seeeduino CAN-BUS wiki for more details on code
  {
    Serial.print("can init ok!!\r\n");
      for (int i = 0; i < 9; i = i + 1)
      {
        Serial.print(stmp[i], DEC);
      }
  }
  else Serial.print("Can init fail!!\r\n");
}

void loop()
{
  CAN.sendMsgBuf(0x00, 0, 8, stmp);
  delay(1000);  //
}

Seeduino CAN-BUS Shield clone Receive.ino

#include "mcp_can.h"
#include 
#include 
#define INT8U unsigned char

unsigned char Flag_Recv = 0;
unsigned char len = 0;
unsigned char buf[8];
char str[20];

void setup()
{
  delay(5000);
  Serial.begin(9600);
  if(CAN.begin(CAN_500KBPS) ==CAN_OK) Serial.print("can init ok!!\r\n");
  else Serial.print("Can init fail!!\r\n");
  attachInterrupt(0, MCP2515_ISR, FALLING);  // interrupt indicates when message is available
}

void MCP2515_ISR()
{
     Flag_Recv = 1;
}

void loop()
{
    if(Flag_Recv)
    {
      Flag_Recv = 0;
      CAN.readMsgBuf(&len, buf);
      Serial.print("CAN message length = ");
      Serial.print(len, DEC);
      Serial.print(" CAN message = ");
      for (int i = 0; i < 8; i = i + 1)
      {
        Serial.print(buf[i], DEC);
      }
      Serial.println();
    }
}

If anyone else wants to try this and has problems with Seeduino CAN-BUS library, I post those as well; I just can't remember exactly what I had to change!

Cheers, JJ

Thank you for this! I'm getting started on CAN.

Hello,
i’ve bought a Seedstudio CAN Bus shield for Arduino and i want to read a load cell with it. I tried to wire two Arduino with CAN BUS shield and i uploaded the example “send” in the first one and the “receive” example in the second one. I modified these sketches because they didn’t worked, how explained above. The correct sketches are attached at this post. The two Arduino communicate without problems and the LEDs configuration is this:

  • SEND: RX and TX flash
  • RECEIVE: RX and INT flash
    Then I tried to connect the Arduino that receive with my load cell. In this case i don’t receive anything and the LED configuration is this:
  • RECEIVE: RX always turned on

Then I tried to upload this sketch: “listener” dnd i’ve saved its library on my PC (https://code.google.com/p/canduino/source/browse/trunk/#trunk%2FLibrary%2FCAN)

The result is this: i read this string from the serial monitor:
hello
[0] [Rx] Status:40 Len:2 Frame:16EF7E8C EXT?:1 Filter:0 Buffer:0 Data:[7F 73 0 0 0 0 0 0]
[0] [Rx] Status:40 Len:6 Frame:2F19DE4 EXT?:1 Filter:0 Buffer:0 Data:[AD 4F FA FA E7 6E 0 0]
[0] [Rx] Status:40 Len:2 Frame:16EF7E8C EXT?:1 Filter:0 Buffer:0 Data:[7F 73 0 0 0 0 0 0]
[0] [Rx] Status:40 Len:6 Frame:2F19DE4 EXT?:1 Filter:0 Buffer:0 Data:[AD 4F FA FA E7 6E 0 0]
[…]
The LEDs configuration is this:

  • RECEIVE: RX always turned on
    When I turn off my load cell the message stops.

I also tried to connect the two Arduino, the first one with the ‘send’ exampe and the second one with the sketch i posted above.
On the serial monitor i read this:
hello
[0] [Rx] Status:40 Len:0 Frame:23C EXT?:0Filter:0 Buffer:0 Data:[0 0 0 0 0 0 0 0]
[0] [Rx] Status:40 Len:0 Frame:54E EXT?:0Filter:0 Buffer:0 Data:[0 0 0 0 0 0 0 0]
[0] [Rx] Status:40 Len:0 Frame:23C EXT?:0Filter:0 Buffer:0 Data:[0 0 0 0 0 0 0 0]
[0] [Rx] Status:40 Len:0 Frame:54E EXT?:0Filter:0 Buffer:0 Data:[0 0 0 0 0 0 0 0]
[…]
The LEDs configuration is this:

  • SEND: RX, TX INT ON
  • RECEIVE: RX ON

Someone can help me?
Thanks in advance
GM

send.ino (458 Bytes)

receive.ino (873 Bytes)

listener.ino (3.21 KB)

Try the library here: https://github.com/coryjfowler/MCP2515_lib

I have fixed a lot of the issues I encountered with the Seeedstudio library and the examples. It has been working pretty well at this point even hooked up to highly utilized CAN Buses. I also have the intention to add support for multiple MCP2515 ICs, error support, and a better interrupt handling method.

Also, using the MCP2515 in "listen" mode causes it to NOT acknowledge any messages it receives. It is in a purely ears-only mode. If you use this mode on a CAN bus with only one other active CAN transceiver, you will find messages are sent infinitely till its controller errors out and shuts down.

Guys,

I've been doing a bit of tinkering with bus networking for a particular project I'm working on. Initially I attempted to implement ModBus protocol running on an RS-485 physical layer using 3 arduino slaves and one Mega master. My over-all intention/objective is to prototype for a large 100+ node-support each performing simple tasks. Each slave/node has ONE output and TWO inputs which they need to monitor and report to a master controller. A GUI app will be tied to the master node making use of the data for an operator.

This was successfully done using ModBus, however, the major draw-back is that for my project I will NOT have the ablity to individually preset the slave IDs. On the flip-side, I will be embedding a UNIQUE serial IC that will guarantee each node to have a non-repeating addressable value. My issue with ModBus is that I cannot detect a new slave added to the network without knowing it's address to ask it it's address....if that makes sense. Furthermore, as per the requirements of the task at hand, I am to assume that ALL 100+ nodes are identically flashed and are ALREADY connected to a bus. Oh AND I have no physical access to each node (they're mounted behind cabinets and installed by NON-technical people....they just connect them...that's IT!).

That's where I stumbled upon switching to a CAN bus. Being that I can load identical firmware on each node and (in theory) I can have a multi-master situation where each node can broadcast onto the bus, this seemed pretty promising. First of all, am I understanding correctly? Can I in fact upon connecting to the network send out a message that has a destination address of the MASTER node to say 'hey, I'm new, give me a node address?.' Or even have the MASTER node send out a broadcast message periodically asking 'hey, is there anyone new?.'

If so, does the library linked above (https://github.com/coryjfowler/MCP2515_lib) have commands to support this? I want to make sure before I buy a few shields to support CAN bus. Maybe CAN isn't the best answer....any ideas guys?

Thanks in advance.

bsahilu,

Did you get answers to your questions? I am a noob at CAN - very simply trying to establish some triggering / simple monitoring of some equipment using the Sparkfun CAN-BUS shield - and can't seem to figure it out... Would be interested if you got anywhere with your questions!

bsahilu: Guys,

I've been doing a bit of tinkering with bus networking for a particular project I'm working on. Initially I attempted to implement ModBus protocol running on an RS-485 physical layer using 3 arduino slaves and one Mega master. My over-all intention/objective is to prototype for a large 100+ node-support each performing simple tasks. Each slave/node has ONE output and TWO inputs which they need to monitor and report to a master controller. A GUI app will be tied to the master node making use of the data for an operator.

This was successfully done using ModBus, however, the major draw-back is that for my project I will NOT have the ablity to individually preset the slave IDs. On the flip-side, I will be embedding a UNIQUE serial IC that will guarantee each node to have a non-repeating addressable value.

The CANopen NMT protocol will solve this for you. It has a Master node that keeps track of what nodes are on the bus, sends out periodic requests for new nodes to announce themselves, allocates them an unused address and implicitly gives them permission to participate in the bus with that new address.

bsahilu: That's where I stumbled upon switching to a CAN bus. Being that I can load identical firmware on each node and (in theory) I can have a multi-master situation where each node can broadcast onto the bus, this seemed pretty promising. First of all, am I understanding correctly? Can I in fact upon connecting to the network send out a message that has a destination address of the MASTER node to say 'hey, I'm new, give me a node address?.' Or even have the MASTER node send out a broadcast message periodically asking 'hey, is there anyone new?.'

Yes, CAN is multi-master. But you generally want to design your network so that only one special head node runs particular master services like address-space management. The CANopen NMT is similar to what you suggest, with a dedicated NMT Master service running on a central node and managing who has access to the bus with what address. The specification provides for several levels of intelligence from both the NMT master and each of the slaves, from fully-dynamic and capable of error-reporting, down to basically brain-dead operation from jumpered addresses.

If you go with a recognised presentation protocol like CANopen, it also gives you formalisms for communicating the input and output values of each node that will possibly be compatible with other commercial (factory automation) systems. Plus other useful things like the ability to download configuration data/code to your slaves and whole lot more.

coryjfowler: Try the library here: https://github.com/coryjfowler/MCP2515_lib

I have fixed a lot of the issues I encountered with the Seeedstudio library and the examples. It has been working pretty well at this point even hooked up to highly utilized CAN Buses. I also have the intention to add support for multiple MCP2515 ICs, error support, and a better interrupt handling method.

Also, using the MCP2515 in "listen" mode causes it to NOT acknowledge any messages it receives. It is in a purely ears-only mode. If you use this mode on a CAN bus with only one other active CAN transceiver, you will find messages are sent infinitely till its controller errors out and shuts down.

Hi cory, Your library for MCP2515 is the best one I've tried so far. Thank you very much. I also found a bug in sendMsg() function, which I guess you might want to be informed of.

I think the code: res1 = mcp2515_readRegister(txbuf_n) should be changed to: res1 = mcp2515_readRegister(txbuf_n - 1) to get TXBnCTRL correctly. I check the library, txbuf_n is the address of SIDH returned by mcp2515_getNextFreeTXBuf(&txbuf_n). If bit3 in SIDH happen to be 1, the bit will never be cleared even the CAN message has been sent successful, and sendMsg() will be stuck in the while loop until the set TIMEOUTVALUE is reached.

The library I linked to has no high-level functions. It is purely a library to control the MCP2515 for generic CAN use. Higher level functionality would need to be coded for your specific needs in your sketch. I have used the library to mock other protocols like J1939 and NMEA2000 but my sketch is what contained that higher functionality. It would be possible to create additional libraries that take advantage of the MCP2515 library to allow a more streamlined approach to these other protocols but that is outside the scope of the library I have been debugging and improving. I hope that clarifies things a bit.

lian999111: Hi cory, Your library for MCP2515 is the best one I've tried so far. Thank you very much. I also found a bug in sendMsg() function, which I guess you might want to be informed of.

I think the code: res1 = mcp2515_readRegister(txbuf_n) should be changed to: res1 = mcp2515_readRegister(txbuf_n - 1) to get TXBnCTRL correctly. I check the library, txbuf_n is the address of SIDH returned by mcp2515_getNextFreeTXBuf(&txbuf_n). If bit3 in SIDH happen to be 1, the bit will never be cleared even the CAN message has been sent successful, and sendMsg() will be stuck in the while loop until the set TIMEOUTVALUE is reached.

I will look into that, thanks for pointing it out!

Hi Guys!

I've been looking at this library and the code for some time now. The CAN.sendMsgBuf() function uses the ID of the receiving end but is this limited to 0xFF? Normaly CAN can handle more nodes so is this a restriction of the library?

coryjfowler: Try the library here: https://github.com/coryjfowler/MCP2515_lib

I have fixed a lot of the issues I encountered with the Seeedstudio library and the examples. It has been working pretty well at this point even hooked up to highly utilized CAN Buses. I also have the intention to add support for multiple MCP2515 ICs, error support, and a better interrupt handling method.

Also, using the MCP2515 in "listen" mode causes it to NOT acknowledge any messages it receives. It is in a purely ears-only mode. If you use this mode on a CAN bus with only one other active CAN transceiver, you will find messages are sent infinitely till its controller errors out and shuts down.

Did you ever build a library for multiple mcp2515 ?

I'm interested in having 2 can bus shields controlled by one controller.

goodguy: Did you ever build a library for multiple mcp2515 ?

I'm interested in having 2 can bus shields controlled by one controller.

The library has been capable since 2014, if I recall correctly.

Before the setup() function, does the following exist?

MCP_CAN CAN0(10);

If so, make

MCP_CAN CAN1(the unique digital pin the second CAN chip select is on);

MCP_CAN CAN2(the unique digital pin the third CAN chip select is on);

and so on.

coryjfowler:
The library has been capable since 2014, if I recall correctly.

Before the setup() function, does the following exist?

MCP_CAN CAN0(10);

If so, make

MCP_CAN CAN1(the unique digital pin the second CAN chip select is on);

MCP_CAN CAN2(the unique digital pin the third CAN chip select is on);



and so on.

I must have looked at the wrong library.

The one I played with has;

const int SPI_CS_PIN = 10;

MCP_CAN CAN (SPI_CS_PIN);

Do you have a link to the gethub page with the correct library? Thanks so much.

https://github.com/coryjfowler/MCP_CAN_lib/tree/Sub-Development

Had time today to try this library.

Thanks Cory for the link and library.

Having a problem with it.

Have any idea why?

Thanks

See attached image.

2016-07-14 13.36.40.jpg

DO NOT use MCP_STD or MCP_EXT in the can0.begin(...) function. There is a bug in the silicon of the MCP2515 and the feature does NOT operate as specified in the datasheet. The only two solid modes are MCP_ANY or MCP_STDEXT. I have confirmation from Microchip on the bug.

**** AUTOMATED MESSAGE - SEE RESPONSE METHODS BELOW ****

Below is a proposed resolution from Microchip Engineering Support Team for your Ticket 278363

Area : Analog/Interface Products Product Group: SMPINT Product : MCP2515

Problem Description: I have been developing a library for the MCP2515 protocol controller for the Arduino community. I am at the point where I believe that the issue lies in the IC and not the library. My issue is with the mask and filtering functions with-in the IC. I have found that what I am seeing contradicts what the datasheet reads. DS21801G page 27 and 28 inform me that setting RXM1 and RXM0 on the RXBnCTRL register will change how received frames are handled. Setting those bits to '11' receives everything and ignores the mask and filter functions, setting those bits to '10' will receive only valid extended IDs that meet filter criteria and so on.. I have set those bits to '10' in both registers and I still get standard IDs entering the receive buffer. I have set up the library to read the register after it has written to the IC and shows the correct values were written. The same goes if I set those bits to '01' I will still get extended IDs appearing, but, as the data sheet declares, the registers RXFnEID8:RXFnEID0 are ignored. Basically, it was filtering the first 11 bits of the extended IDs that came in. This was across more than one IC, though, they were probably from the same lot as they were purchased together from Mouser. Assistance would be greatly appreciated.

This is identical to Ticket 273853.

My test bus has standard identifier and extended identifier messages being transmitted on it. With both masks empty both extended identifiers and standard identifiers entering the receive buffer of the MCP2515 I am using regardless of how the above bits are set which does not correspond to the datasheet as I understand it.

Problem Resolution: Hi Cory,

I have received feedback from the MCP2515 applications engineer.

In short, he was able to reproduce the observations related to RXM 01 and 10 are not working as described. I am expressed interest in exercising similar tests on the MCP25625, a new CAN module, and exercising a design review of cause if there is a similar result. However, the given the age of the MCP2515 design, it is unlikely the MCP2515 will be reviewed by design and updated.

Observation Summary: RXM 00 can be used to setup filters. RXM 11 can be used to receive all messages. RXM 01 and 10 are not working as described.

Thanks for your persistence,

Michael

Hello, I am trying to set up an CAN network using a can shield from aliexpress with the MCP2515 and a TJA1050 tranceiver. For the test I am using a arduino nano and your libray Cory.

When I try the Send example the initializing works fine, but then I always get the "error sending message"

Is there a way, to get more debug information? Do I have the send an ack message or something else? I am just reading the can signals from the Arduino with a CAN USB interface which I use at work.

BR Alex

"Do you have to send the acknowledge" - No, the acknowledge is a single dominant bit that is sent by any active receiving node on the CAN bus and should be an automatic thing handled by the protocol controller in your USB dongle assuming it is not in a listen-only mode.

What kind of USB dongle is this and are you receiving anything?

If you are receiving a message, I would check to ensure that the USB dongle you are using is in an active mode on the CAN bus (Not listen-only).

If you are not receiving any messages, I would check to confirm the crystal frequency set in the program matches the actual crystal frequency on the shield and then confirm baud-rates are the same between the program and your USB dongle. (I have see a lot of cheap Chinese boards using 8MHz crystals instead of 16MHz that Seeedstudio and SKPang have used.)

I am using a Vector VN1630 and for viewing the messages I use the trace function in CANape. No I am not receiving anything. My shield has a 8Mhz crystal so I changed the initialize line to "CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK)"

For wiring the shield I used Pin10 (CS), Pin11 (MOSI), Pin12 (MISO), 13 (SCK). This should be correct and also I got the "MCP2515 Initialized Successfully!" message so it seems that the spi connection works.

Edit: I found the error in the Shield. It has a pin header as well as a screw terminal for the CAN connection. The screw terminal somehow seems not be connected properly on the PCB because as I tried the pin header it works just fine!

Sorry about the delay, I just returned from a trip and I didn't have an Arduino with a CAN shield with me.

I have a clone UNO setup with an old Seeed Studio CAN shield and without any changes to the send example, I am able to see the example message come across CANalyzer at 500k.

Unfortunately the shield I have uses a 16MHz crystal, but I have a MCP2515_CAN break out that uses an 8Mhz crystal and with the frequency modification to the begin function, I see the message come across CANalyzer.

At this point I suspect the shield you sourced may have a bad connection between the protocol controller IC and the transceiver IC, or there is a wiring error between the shield and the CAN dongle. I assume you also have the bus terminated; at least one termination resistance must be present for reliable communication to occur.