Go Down

Topic: Cheap & simple MCP2551/MCP2515 CAN BUS set up (Read 17212 times) previous topic - next topic

JJ_Table_Turner

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
Code: [Select]
#include "mcp_can.h"
#include <SPI.h>

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
Code: [Select]
#include "mcp_can.h"
#include <SPI.h>
#include <stdio.h>
#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

giantsfan3

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

gmazza

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
  • [Rx] Status:40 Len:2 Frame:16EF7E8C EXT?:1 Filter:0 Buffer:0 Data:[7F 73 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]
  • [Rx] Status:40 Len:2 Frame:16EF7E8C EXT?:1 Filter:0 Buffer:0 Data:[7F 73 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
  • [Rx] Status:40 Len:0 Frame:23C EXT?:0Filter:0 Buffer:0 Data:[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]
  • [Rx] Status:40 Len:0 Frame:23C EXT?:0Filter:0 Buffer:0 Data:[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

coryjfowler

#3
Jan 17, 2014, 07:22 am Last Edit: Jan 17, 2014, 07:26 am by coryjfowler Reason: 1
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.

"Taking the time to make a proper, punctuated, post is a mark of courtesy and respect."  http://forum.arduino.cc/index.php?topic=149022.0

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.
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.


tomsvilans

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!

polyglot


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.


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.

lian999111


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.

coryjfowler

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.


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!  

"Taking the time to make a proper, punctuated, post is a mark of courtesy and respect."  http://forum.arduino.cc/index.php?topic=149022.0

Go Up