Arduino + Controller Area Network (CAN)
Stolen from Wikipedia: The CAN (controller area network) bus is a vehicle bus standard designed to allow microcontrollers and devices to communicate with each other within a vehicle without a host computer. This bus standard includes it's own messaging protocol for communications between nodes on the network.
One of the most popular uses for this technology is in the automobile where the network provides a communication channel between the ECU, Transmission, airbags, braking systems, etc...
As you'll have noticed, I've recently been investigating OpenLCB which uses this technology for communications between its nodes on a model railway. The article below will show how the CAN bus can be incorporated with an Arduino to allow communications between different microcontrollers/nodes on your network.
Topography
The OpenLCB project dictates that the CAN bus implemented via their standards must not be in the form of a ring. When I initially saw the Railstars:io prototype I expected that a ring would be required; the prototype shows an 'in' and 'out' communications port. Little did I realise that, upon closer inspection, the io could act as a termination point for the CAN bus that it connects to. We therefore will implement a layout as follows on our railways...
The OpenLCB project will use standard RJ45 cables (i.e. ethernet cables) due to the requirement of twisted pair technology to guarantee data transmission.
Interfacing with the Arduino via SPI
The Serial Peripheral Interface is a communication standard used to provide communications between integrated circuits. The Arduino has an SPI library and therefore allows us to easily communicate to the CAN interface.
We'll be using the MCP2515 and MCP2551 integrated circuits to transmit/receive our data from SPI onto the CAN bus. This setup has been done before in Sparkfun's CAN-BUS Shield, the CAN-CAN, the Universal CAN Library (Universelle CAN Bibliothek) and the CANduino. The CAN-CAN Schematic and Sparkfun's schematics provide a great reference point for hooking the whole lot up. Of course, you could also just grab their shield if you don't want to build everything yourself.
Schematic
The image below should be pretty self-explanatory. See the next section for the exact pins for the SPI interface. RESET and INT can go to any digital pin.
Building, troubleshooting and talking to one's self
I built two at the same time to be able to test node-to-node communications. There was nothing overly tricky in the construction... I just chose to use relatively tight pcb prototyping boards which didn't leave much room for error. The above schematic was followed and the devices were hooked up to my Arduino(s).
I tried the loopback test from the canduino project and got random responses... the data going in was not the same as the data coming back. I started the debugging process after letting out a little sigh.
It turns out that, on all Arduinos, the SPI interface can only be used on specific pins:
SPI Pin | Arduino Mega | Smaller Arduinos (168,328) |
---|---|---|
SS/CS | 53 | 10 |
MOSI | 51 | 11 |
MISO | 50 | 12 |
SCK | 52 | 13 |
Note that the CAN library also then required a change as the pins in it are hard-coded to a 168/328 Arduino and wouldn't have ever worked with the Mega. You can find my fix for this down below.
I finally had responses after the pins were in the correct locations... but not the responses I wanted to see; I looked at the crystals next. My Arduinos all used 16.000MHZ crystals, but my local hobby shop only had 4mhz, 8mhz or 20mhz. This concerned me and I google'd and google'd to work out if, in the same circuit, multiple ICs could be driven off different oscillation rates. I decided that, since the 'SPI' interface had it's own 'bus rate' and the CAN bus also had it's own 'bus rate' that the crystals therefore did not affect these speeds. Also, the Arduino would dictate the speed of the SPI interface since it was the master (and slower.) I therefore bought 20mhz crystals for the MCP2515 chips, with my fingers crossed. Of course, this could have been the next issue.
Fortunately, from my previous attempts at barebones Arduinos, I had a 16mhz crystal on-hand. I swapped out the 2 capacitors and the 20mhz for the 16mhz and hooked it all up again. Nothing...
So, I then whipped out my Atmega328p 'barebones' Arduino and hooked it up to that. The SPI pins were different, as per above, so I made sure they were correct... and the CAN library from the canduino source had to be modified back to the required pins. After putting it all together I checked the serial output in the Arduino Serial Monitor and saw the correct response. The loop back test was working!
WTH... there was no reason that it should... except that maybe the SPI interface on my Mega was fried? I then, just because I hate caution and feed it to the wind all the time, swapped the 20mhz crystal and capacitors back in. It STILL WORKED! Good... I could keep the 16mhz for my other barebones Arduino.
So... with a known-working CAN node, I swapped it back onto the Mega. WTH... it worked. I now had my CAN nodes (by this time the other node built was also functioning thanks to it's guinea pig brother) talking to themselves. It was time to get them to talk to each other!
Talking in the CAN
Hah... there's an unwritten rule to not talk whilst in the toilet, but in our situation we'll make an exception. From the start I'd built the bus and was just itching to get the damn thing transmitting messages. The setup was simple: terminal blocks were used at junctions and standard dodgy speaker wire was the main network cable. 120ohm resistors were the terminators as per the standard CAN specification.
The only real issues here were the source code (or my lack of knowledge of how it worked) and the usage of crystals. Yes, they came back to haunt me... it turns out that, whilst I had the loopback going, I'd left a 16mhz on one node and a 20mhz on the other. In the source code you specify the 'CAN Bus Speed' which, of course, was configured the same on both Arduinos. The actual issue was that, when the Arduino told the CAN controller to run at bus speed '1000', the CAN nodes did this but, due to their differing crystals, their calculations of what '1000' meant were incorrect! Since one was running 4mhz faster (20mhz vs. 16mhz) it must've been communicating on the bus at a different rate and therefore confusing the hell out of the other node.
The next issue was the code... I looked over it and thought that each node would take turns in transmitting and recieving... I was wrong: you had to actually set one as the sender and one as the receiver. I configured this based on the Arduino class (by #IFDEF just as the SPI pins were configured) and then had communication! My nodes were live and functional!
RX/TX LEDs
The final step was wanting RX/TX activity LEDs. It turns out that the MCP2515 supports this, but you need to do a little configuration. If you view the datasheet at microchip you'll note that the RXnBF Pins can be configured as 'nothing', 'general outputs' or 'low on RX buffer full'. I was hoping that obe would be 'high on TX buffer', but no such luck. It actually turns out that the chip has two RX buffers and therefore two RXnBF Pins. LEDs attached to these pins will, once configured as per below, illuminate once the associated RX buffer is full. If you ever see both full then you might be losing data?
Second option: It turns out that in the MCP2515 Demo Board PDF that you can just put two LEDs on the RXCAN(1)/TXCAN(2) pins of the MCP2515.
Third option: It seems that you can also configure the INT pin to fire on TX buffer 'emptying'. You'll have to disable the pin firing on all other error situations to do this. By default, this pin is usually pulled 'high' by the MCU, so you must either disconnect that, use a resistor between the MCU and MCP2515 or just pull the pin high normally via a pullup resistor and then connect an LED in parallel with this to the INT pin. I imagine that in more complicated scenarios you'd actually want to know once the MCP2515 has generated an interrupt.
IDs: Standard or Extended?
All messages sent on the network have a 'frame id' of either (standard mode) 11-bits or (extended mode) 29-bits. It must be understood that this 'frame id' does not actually identify a node! It is simply an identifier for the actual message being transmitted. This identifier can contain any form of information you want; the bits are yours to play with.
One main use for this identifier is to record the intended recipient of the message you are sending. Depending on the amount of nodes in your network (don't forget to think of future scalability!) you can use anywhere up to 29-bits to uniquely identify them. Of course, this identifier could just be used to identify the 'class' of node and then you could put further data in the message to indicate the exact recipient. You could also go the other way and only use a portion of the identifier for the recipient code and have the rest for other uses.
The MCP2515 has in-built filtering to work on the identifier of incoming messages. If you're only using standard mode then the filters also apply to the first two bytes of the message. The filtering works inside the MCP2515 and therefore doesn't saturate your SPI link as the messages are stopped prior to being put into the RX buffer.
MCP2515 Modes
There's 5 modes that you can set the MCP2515 into. These are as follows:
Mode | Description |
---|---|
Configuration | This mode allows the developer to update settings. The following settings require this mode to be set first: CNF1,CNF2,CNF3,TXRTSCTRL,MASKS,FILTERS. |
Normal | Standard operating mode. RXM0 and RXM1 per buffer do not apply in this mode. All filters and Masks do apply. |
Sleep | Low-power mode. SPI remains active, and the MCP2515 will wake up if there is activity on the CAN bus if the WAKIE/WAKIF interrupts are enabled. After woken, the chip will be in Listen Mode. |
Listen | Make sure there are two or more nodes on the CAN bus. Whilst in Listen mode, the chip won't output a thing, so if another chip sends a message then the message will constantly circulate on the bus if there is no other node to 'ACK' it. Another node must be there to stop the message transmission. RXM0 and RXM1 per buffer apply in this mode and the masks/filters also do too. |
Loopback | All messages sent are returned via the RX buffers, filtered first. No messages are sent out over the CAN. No messages are received from the CAN. |
Buffers
It needs to be noted that the MCP2515 has two receiving buffers known as Buffer 0 and Buffer 1. Messages will go to the first if it's free (and not filtered) and then the second. Filters can be set on both, but the second buffer is much more flexible with four filters.
I don't know the exact reason for the MCP2515 containing two buffers, and then why one is more flexibile than the other, but in the end it's up to the developer as to how to use them. Filters can be configured to allow specific message 'types' on each buffer. This then means that, for example, the developer could configure the second buffer to only allow emergency messages such as 'STOP THAT TRAIN' whilst the first deals with the standard communications.
Filtering CAN Messages via the MCP2515
With the base configuration, an MCP2515 controller will accept any messages sent across the network. This therefore means that your nodes need to filter each individual message coming across the bus to determine if they themselves are the intended recipient. Fortunately the MCP2515 has in-built configurable filtering to allow only messages intended for the node to be passed through its RX buffers.
The MCP2515 has 6 configurable filters with 2 masks. The first mask works in conjunction with the first two filters and applies to the first receiving buffer whereas the second mask works with the final 4 filters and works with the second receiving buffer. Filtering is enabled when any bit of a mask is '1' and disabled when the masks are completely zero'd out.
You may be wondering why both a mask and a filter are needed? As mentioned above, you may not have used the entire 'identifier' area of the sent message to indicate the recipient. Therefore, when you're checking an incoming message, you wont want to filter the entire identifier. As the identifier bits can be a '1' or '0', you need to initially specify which bits you want to check (mask) and then whether or not they are a '1' or '0' (filter).
Node 1 ('101') | Node 2 ('110') | |
---|---|---|
Identifier | 10110 | 10110 |
Mask | 00111 | 00110 |
AND'd | 00110 | 00110 |
Filter | 00101 | 00110 |
Match? | False | True |
In the table above, you can see that Node 1 failed to match. The filter applied was looking for '101' (5 in decimal) but the lower 3 bits identifier (that's what the mask was looking for) was actually '110' (6 in decimal). You can see that the actual result was '110' after the mask was applied to the identifier. The second node matched as the filter is actually looking for '110'.
Now, we have to use the full registers when we apply this to the MCP2515. This means filling out 29bits of data. When in doubt, fill everything else with zeroes. Each register in the MCP2515 is 8bytes, this therefore means that you need 4 bytes per filter and 4 bytes per mask. The 6 filters and 2 masks that were mentioned above are located in the following areas:
Mask 0 | Filter 0 | Filter 1 | Mask 1 | Filter 2 | Filter 3 | Filter 4 | Filter 5 |
---|---|---|---|---|---|---|---|
0x20 | 0x00 | 0x04 | 0x24 | 0x08 | 0x10 | 0x14 | 0x18 |
0x21 | 0x01 | 0x05 | 0x25 | 0x09 | 0x11 | 0x15 | 0x19 |
0x22 | 0x02 | 0x06 | 0x26 | 0x0a | 0x12 | 0x16 | 0x1a |
0x23 | 0x03 | 0x07 | 0x27 | 0x0b | 0x13 | 0x17 | 0x1b |
Right, now that you know you need 4 bytes for a filter and then 4 bytes for a mask... and you know where to store them... you'll probably now need to know how to construct a mask and filter. We'll start with a mask that looks for the value 11 (decimal!) [0x0b in hex, 1011 in binary] in the standard 11-bit identifier. As you can guess, I've just provided the filter by representing the value in binary; we simply need to zero-out the bits to the left to ensure we provide the correct number. Have I provided the mask? No! Look at the truth table below if we were to use 1011 as the mask.
Node 1 ('11011') | Node 2 ('01111') | Node 3 ('01011') | |
---|---|---|---|
Identifier | 11111 | 11011 | 01011 |
Mask | 01011 | 01011 | 01011 |
AND'd | 01011 | 01011 | 01011 |
Filter | 01011 | 01011 | 01011 |
Match? | True | True | True |
They all matched!?!?!? Since we were only checking the 'exact' value via the mask, we weren't actually looking to see if any of the bits around the value were set. The basic principal is that we need to know the maximum length of the value we could be looking for and then use that as the mask. For example, if you have up to '11111' (32 including '0') ids on your network, then you want to make sure that your mask is '11111' and that your filter is the exact number of the node checking if the message is theirs.
Node 1 ('01011') | Node 2 ('01111') | Node 3 ('11011') | |
---|---|---|---|
Identifier | 11111 | 11011 | 01011 |
Mask | 11111 | 11111 | 11111 |
AND'd | 11111 | 11011 | 01011 |
Filter | 01011 | 01011 | 01011 |
Match? | False | False | True |
That's better! Make sure your values are correct! So, in the example below we'll use '11111' as the max value and therefore the mask. We'll then use 01011 as the value of the node we're pretending to be and we'll insert these into the correct registers (being Mask 0 and Filter 0.)
Message Acceptance Process
So, two buffers with differing filters... what happens when a message arrives? The basic idea is that a message will hit the first buffer and, if not accepted, attempt to hit the second buffer. The message is then discarded if the second buffer is also configured to not accept this message.
Note: There are also two bits (RXM0 and RXM1) in the RXBnCTRL (where n is either 0 or 1 depending on the buffer) that determine how messages are accepted. Note: My code currently has the ability to set these registers; for the life of me I cannot actually get the chip to function as per the datasheet when these registers are set. If anyone else has succeeded in using the RXM bits successfully then please leave a comment and tell how you did it!
RXM0 | RXM0 | Description |
---|---|---|
0 | 0 | [Default] Enable reception of all valid messages as determined by the appropriate acceptance filters. (See the pseudo-code below as to how the masks and filters apply.) |
0 | 1 | Only accept standard messages. Filters are useless if the EXIDE bit does not match with this value. For example, if you put an extended filter on buffer 0 but you disable extended messages to buffer zero with this configuration then that filter will never be used. |
1 | 0 | Only accept extended messages. The same rules apply that any standard filters on a buffer with this setting will not be used. |
1 | 1 | Receive ALL messages regardless of filters. Also recieve messages that have caused an error during transmission. The fragment of message received in the buffer prior to the error will be brought through. This mode should really only be used for debugging a CAN system. |
So, as long as the RXM bits are both set to '0', the message buffers will then process through the following procedure to accept or deny messages.
for EACH BUFFER b: (initially 0) if (MASK 'b' is ZERO) { //mask 0 for buffer 0 and mask 1 for buffer 1 Accept new message on Buffer b } else { using FILTERs 0,1 (if b equals 0) OR FILTERs 2,3,4,5 (if b equals 1) if (both the message and filter are 'extended') or (both the message and filter are 'standard') then for each '1' in MASK as 'x', does FILTER[x] equal message[x]? if all match then accept message else check next filter as this filters bits do not match the relevant message bits. else check next filter as this filter type does not match this message type. if still not accepted then TRY BUFFER 1 }
A mask is disabled when all its bits are '0'. As soon as a bit is '1' then that mask applies to the relevant buffer. As per the section above, the bits in the filter are then checked against the relevant message bits based on what bits the mask specifies the process to check.
On the contrary, a filter is not 'disabled' when all bits are '0'; instead you have configured two filters, on the buffer related to the mask, which will only permit standard messages where the identifier is zero. If you set the mask on a buffer to anything other than 0 and then don't touch the filters, this will prevent extended messages from coming through (as both filters have '0' as the EXIDE bit) and also prevent any standard messages that do not have an identifier of zero.
In the event that you don't want to receive a specific message type, you must put a mask on both receiving buffers and then an appropriate filter to block out the specific identifier bits. On the contrary, make sure that your masks and filters are smart enough to capture all other data required for your CAN node.
If in doubt, write an 'all-seeing' debugging application to view all traffic on your bus... it'll allow you to diagnose why messages are landing where you might not want them to. As per above, setting both RXM bits to 1 will bypass your filters; this way you don't have to muck around with your own configuration too much. Just make sure you have more than two other nodes on the bus if you want another in Listen mode. Having one node on the bus, or two with one in listen mode, will mean that any message transmitted will stay perpetually on the wire. A message must be consumed by another node for it to disappear.
Storing Masks and Filters on the MCP2515
Scroll up to see the register addresses for the masks and filters. The contents of each of these registers looks as follows:
Filter/Mask | Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
---|---|---|---|---|---|---|---|---|
Byte 0 (RX[F|M]nSIDH)* | SID10 | SID09 | SID08 | SID07 | SID06 | SID05 | SID04 | SID03 |
Byte 1 (RX[F|M]nSIDL)* | SID02 | SID01 | SID00 | –– | EXIDE/––** | –– | EID17^ | EID16^ |
Byte 2 (RX[F|M]nEID8)* | EID15 | EID14 | EID13 | EID12 | EID11 | EID10 | EID09 | EID08 |
Byte 3 (RX[F|M]nEID0)* | EID07 | EID06 | EID05 | EID04 | EID03 | EID02 | EID01 | EID00 |
- *: 'n' is the filter number, i.e. RXF0SIDH is the 'Standard ID High Receive Register Filter 0'.
[F|M] means that the name is 'RXF1SIDH' for Filter 1 and 'RXM1SIDH' for Mask 1. - **: 'EXIDE': set this to '1' and this filter will only apply to Extended IDs, '0' means it will only apply to standard IDs.
This byte is unimplemented for Masks. Just leave it as zero. - ^: These two bits are not used if you are in standard mode as you only need 16 bits to check the first two bytes of data.
Have I lost you yet? Each filter and mask needs to be able to store both the Standard ID bits and the Extended ID bits. As mentioned before, if you're in standard mode then the 'lower' two bytes (i.e. bits 16 to 0 [17,18 are ignored!]) of the extended area are for matching against the first two bytes of data. You can disable this by ensuring that the associated mask has zeroes in the extended area. On the contrary, if you wanted to check the first byte in the data for a specific value then you would pass in '001111111100000000' as the extended area of the mask with the relevant extended bits set in filter.
Somewhere up above I mentioned we'd use '11111' for the mask and '01011' for the node id. We'll now store this in the registers. We'll use Mask 0 and Filter 0 for this and we'll make sure the rest are all zeroes so they don't apply. You'll note that the first register (RXM0SIDH) starts with zeros; as per above this means that the identifier could actually contain any data in this area and, since the mask is '0' for these bits, the acceptance process wont care at all! The registers will need to be set as follows:
Register | Data | Register | Data |
---|---|---|---|
RXM0SIDH [0x20] | 0b00000011 | RXF0SIDH [0x00] | 0b00000001 |
RXM0SIDL [0x21] | 0b11100000 | RXF0SIDL [0x01] | 0b01100000 |
RXM0EID8 [0x22] | 0b00000000 | RXF0EID8 [0x02] | 0b00000000 |
RXM0EID0 [0x23] | 0b00000000 | RXF0EID0 [0x03] | 0b00000000 |
Note: All other Registers in the RXF/RXM space need to be zero'd out! |
So, as you can see above, we've put the mask 0b00000011111 in the 'standard id area' of Mask 0 and 0b00000001011 in the 'standard id area' of filter 0. Based on our logic above this will then only allow messages through that match the above requirements. Below is the code to actually do this on the Arduino.
#define MASK_0 0x20 #define FILTER_0 0x00 void CANClass::setMaskOrFilter(byte mask, byte b0, byte b1, byte b2, byte b3) { setMode(CONFIGURATION); setRegister(mask, b0); setRegister(mask+1, b1); setRegister(mask+2, b2); setRegister(mask+3, b3); setMode(NORMAL); } //set MASK 0 for RXB0 a mask checks all bits of the standard id. CAN.setMaskOrFilter(MASK_0, 0b11111111, 0b11100000, 0b00000000, 0b00000000); //set Filter 0 to 0x555. Therefore only messages with frame id: 0x555 are allowed through this buffer. CAN.setMaskOrFilter(FILTER_0, 0b10101010, 0b10100000, 0b00000000, 0b00000000);
Note that only setting this for buffer 0 will mean that any message that doesn't match will come through on buffer 1. You'll need to also set a mask on buffer 1 to stop the messages completely. Of course, you can also only ever check buffer 0 for messages and not care if buffer 1 has anything waiting.
Filters in action: Guessing game.
Ok, who would've thought you could make microcontrollers play a game together. You know the old trick, someone else chooses a 'random' number and you get to 'randomly' guess it. Why don't we make our Arduino's play the same game?
We'll set the filter on buffer 0 to the number the receiver is thinking of. This means that the sender will only actually get a message through to the receiver if they guess the correct identifier. Both controllers will then swap roles. Just to make life easier we'll limit the range of numbers allowed, but we'll still make the guessing as 'random' as possible.
I could paste the full code here, but instead I'll just post the general idea.
Main setup | |
---|---|
Set Mask of Buffer 0 to the 11-bit standard identifier Set Mask of buffer 1 to the same 11-bit id set filter 2 (first filter of buffer 1) to a specific ID for messages that aren't guesses. Set one node to RX and one to TX Initialise the random generator. |
|
Receiver Role | Transmitter Role |
|
|
Source code (including my version of the CAN Library)
The final piece of the puzzle is always the source code. I've included the guessing game example as well. Note that my code is based off the canduino and I intend to send changes upstream where possible to make life easier for everyone.
March 4th, 2012 - 16:40
THANK YOU!
Just stumbled on your post today. I have the MCP 2515 and 2551, and I’ve been trying for a couple days (unsuccessfully) to interface with an Arduino Mega 2650 ADK. Teaching myself from the datasheets really hurt. I’m not an electrical engineer, and this site seems like an excellent learning resource. Only modification necessary so far was to change CAN.h line 67 to:
#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega2560__)
I will let you know how it goes…
March 4th, 2012 - 17:20
Dylan,
Glad to be of assistance… it took a good deal of time for me to get my head around this setup also.
Thanks for the note on the ‘larger’ mega too! I’ve re-uploaded the CAN.h file (in the zip) to include both of them…
#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2650__)
Steven.
March 6th, 2012 - 12:47
Watch out! Some dyslexia slipped into your fix: it’s the 2560, not 2650.
Thanks again!
March 6th, 2012 - 13:42
Thanks for the heads up… I’d realised the mistake and fixed it within a few minutes :)
The email that ended up in your inbox would’ve had the original error, as does your original comment!
I don’t even know if the __AVR_ATmega128__ is a valid target? Can’t find a ‘legit’ Arduino with this MCU.
Anyway, I’m currently in the process of expanding the code to support extended IDs and proper sending (finding a free buffer) and error handling.
Will update this post over the next few days.
March 21st, 2012 - 02:43
Hi, I tried your loopback code and i managed to get the RX: 0 / 0 / 0 / etc output with my circuit. Now the only difference in my circuit compared to yours is that I am using 8MHz oscillators to control the MCP2515 clock.
Now I have compiled your code for the guessing game and i just changed it so that one node is set as RX and the other TX. I get an output from the RX saying Guess has been set at: 8 and the TX is outputting the numbers it is guessing. However when it guesses 8 it doesn’t output I think I got it?: as it should and then switch positions with the RX node. Instead it keeps guessing as though it got it wrong. I would really appreciate it if you could help me as I am doing my project for university on the CAN bus and i need it working by thursday…
Thanks!
March 21st, 2012 - 15:07
Just to let you know it is working now without any problems. It seems the Arduino Nano only allows interrupts on pins 2 & 3. Also in order for the code to work with the latest Arduino compiler the include Window.h needs to be changed to include Arduino.h. In addition i got rid of the ifdef for different Arduino boards as i’m using two the same, and hardcoded one as TX and one as RX.
Thanks for the article it really helped me with my project :D
March 21st, 2012 - 19:52
James,
Glad you got this working… was heading home to compile my code when you sent this second comment. Interrupts on pins 2 & 3 hey? That’s got nothing to do with SPI? I haven’t actually used interrupts in my code but I imagine any of the libraries could require them.
I also can’t see where Window.h is included? I have definitely used my code here with Arduino 1.0
Steven.
March 22nd, 2012 - 07:55
Sorry i meant WProgram.h (it was quite late when i commented :P) And yeah for the nano according to the documentation SPI is only allowed on pins 10-13 and interrupts on pins 2 & 3. Maybe i was mistaken but i thought you had used interrupts in your original code, i thought the header file defined them…
March 22nd, 2012 - 09:10
Sounds like you’ve not downloaded the code at the bottom of my post? Instead you’ve used the code directly from Canduino where the “WProgram.h” reference is? I definitely do not have that reference in the ‘library’ that I have provided.
As for “Interrupts”… there is a configurable interrupt pin on the MCP2515, but this is simply brought to any digital out pin on the Arduino and brought high. As long as the Arduino keeps that pin high then the MCP2515 will not actually stall waiting for the interrupt to be cleared. I have defined that in the header for the library, yes, but it doesn’t need to hook to an actual Arduino interrupt.
Anyway, looks like you updated the Canduino library again and also got it to work :)
March 23rd, 2012 - 12:09
Hi,
Awesome post really helped explain some areas that were hazy. I’ve spent about a week trying to interface with a working can bus and also with a single can device that is just sending out data. I’m unable to get the arduino with the MCP2515 to store anything to its buffer. When I check CAN.readstatus() it always returns a zero, I’ve also resetFiltersAndMasks() . Running everything in loopback works great. So I’m not sure where the issue is. I hooked up the can bus to an oscilloscope and the node I’m trying to read spikes at 2V where I can see the arduino outputting around 3V (by removing one from the bus). Also I tried adjusting the baudrate to see if that might be an issue, which didn’t seem to work.
I really appreciate any help and ideas on why the buffers arn’t storing data.
Thanks,
Randy
March 26th, 2012 - 09:48
Randy,
Have you got LEDs on the buffer pins and on the TX/RX lines between the MCP2515 and MCP2551 to see what activity is happening?
Are you just tapping into the target CAN bus at a random location to see the data? Do you need to check where the terminators are on the line?
Have you got the TX/RX wires around the right way for the bus you are attaching to?
As long as your node is in Listen mode, then all should work… I’ve not actually attempted to plug onto a network, but I do have three nodes and have confirmed that the third can be in Listen mode and that it will watch packets flying around.
Since you’ve confirmed packet functionality in loopback mode, I’d imagine that your wiring to the MCP2515 is correct.
I can only guess that your baud rate for the CAN bus you’re connecting to could be wrong? I know that I had mismatched nodes previously and they don’t communicate at all. Note that if your crystal on your MCP2515 doesn’t match the crystals used on the network you are connecting to then you will need to do some maths :) The baud rate you pass during initialisation is calculated off the base crystal and must be a 100% match to the rest of the network. Can you confirm the speed of the target network?
I’ll re-download the code from above and confirm that changes I have made ‘offline’ and not compiled are, in fact, correct.
April 25th, 2012 - 00:21
Hi
I cannot get mine to read the data.
It is reading the can but the data is not changing. Source is constantly changing.
Any suggestions.
Antony
April 25th, 2012 - 10:02
Alex,
Are you reading another CAN network? Or do you have your own CAN setup? Ensure you have the correct timing for the network you are listening to.
What mode do you have your controller in? What speed? How quickly are you trying to read the packets and are you clearing the values read afterwards? Do you have LEDs on the TX/RX on the CAN side of the network? (Put LEDs on the RB0 and RB1 as per above)
Steven.
April 26th, 2012 - 02:11
Hi
Having problem posting but here goes again.
Yes I am its a ROV with 2 nodes (topside and bottomside)
I have changed bits in the code for my bus speed which is 138.24
for this speed I am using a 11.0592 MHz crystal this zero error.
I have also changed the bit timing registers to CNF1 0x01 CNF2 0x0BA CNF3 0x07
Have tried all the modes. but the listen mode is main usage.
The question “How quickly are you trying to read the packets ” Not sure what you mean by this ??
The question “are you clearing the values read afterwards?” is this not done in the codeing ??
And yes I have LED on all.Only the Rx flashes
Regards Alex
April 26th, 2012 - 09:32
Alex,
Just to confirm, the Rx LED is on either the RX0BF or RX1BF pin? If it’s on the RX/TX lines between the MCP2515 and 2551 then that means the data is coming off the bus, but the controller isn’t reading it correctly.
By “how quickly” you’re trying to read the packets: if the loop in your code is too slow then there may be other packets transmitting across the network that your code is unable to read as your buffers are full. But if your buffer LEDs aren’t coming on, then it would mean that your MCP2515 isn’t actually receiving any messages off the CAN.
By “clearing values”: the frame buffer array that you are reading the data in to should be zero’d after the read to confirm that you are actually then reading in a new set of data.
Are you setting any masks or filters?
What does your init code look like? Your read/loop code? Are you using an Arduino?
Steven.
April 26th, 2012 - 17:59
Hi Steven.
Yes it’s the LCD on the RX on the lines between the MCP2515 and MCP2551 that’s flashing.
I am using your code to listen and not added anything atm untill I an reading the can.
Yes using Arduino UNO. Started a canbus topic on the Arduino forums. In Networking protocols and devices. Topic canbus a82c250.
Thanks for sorting will give it another session tonight.
Regards Alex
February 27th, 2013 - 03:13
Alex, probably what it is going on is that you are not sending ACK’s, just change the mode to NORMAL and give it a try.
The listener mode is a “man in the middle”, but if there are not any other nodes in the CAN network, no one is sending this necessary ACKs, so the CAN transmitter keeps sending again and again the same frame…
June 29th, 2012 - 00:41
Hello stevenh, thank you for your work. I’ve been playing with your library, but I cannot send/receive only extended frames using your examples/test. I’ve modified the filter_mask_test in order to send just extended frames. On the other hand I left the listener code unmodified. The tests i’ve been running shows that i can send extended frames when the listener is setup as “CAN.toggleRxBuffer0Acceptance(true, true);”, but I cannot get it works with “CAN.toggleRxBuffer0Acceptance(false, true);”. The listener just loops and don’t receive anything on the receive buffer.
July 1st, 2012 - 18:37
Freddie,
I’m not currently able to set up a test circuit, but I know I did have trouble setting the buffer acceptance flags on my previous experiments.
I think your best bet would be to configure the filters with extended-only masks and bits. You could write an “allow all extended messages” filter and apply it to all filters available. That should then stop Standard messages from getting in.
Steven.
July 6th, 2012 - 11:48
This site is absolutely brilliant. Wow…
I have a question that I was hoping somone with some CANBUS knowledge could help me out with. I have created a device for my car that displays messages on the information screen in the center console. This information screen normally displays information from the oem radio. To post on the screen i have to send 3 messages:
Message ID 0x28f (8 bytes)
Byte 0: Turns on CD-IN, MD-IN, ST, Dolby, AF, RPT, and RDM.
Byte 1: Turns on AUTO-M, TP, TA and PTY.
Byte 3: Enables intermediate characters between letters: . : ‘ ”
Byte 4: Used for setting the clock. Send 0x90 twice then 0x80 to start setting. Then 0x90 followed by 0x80 to go to the next field. 0x88 changes the current select (250ms repeat rate).
Message ID 0x290 (8 bytes)
Byte 0: Nothing displayed when 0x00. Set to 0xc0 to display full message. 0xd0 or 0xe0 or 0xf0 to display ony the second half (this doesn’t seem useful).
Bytes 1-7: Characters to display. ASCII codes from 0x20 to 0x7e (except 0x5c is replaced with the yen sign). 0xdf degrees sign, 0xf0 right arrow, 0xf1 left arrow, 0xf2 backslash, 0xf3 small C, 0xf4 small H, 0xf5 small D. The remaining characters are Japanese.
Message ID 0x291 (8 bytes)
Byte 0: Set to 0x85. Other values possibly used for scrolling?
Bytes 1-2: Repeat of bytes 6 and 7 from 0x290 message.
Bytes 3-7: Remaining 5 characters to display.
This works great, and I get my messages displayed on the screen just fine. What I have noticed though, is that after a minute my radio ceases to post messages onto the screen. I am assuming that the radio is going into a BUS-OFF mode where it is just giving up on trying to communicate with the screen (i believe that is part of the CAN standard?). A side effect of this, is that the radio also disables its peripherals (which i assume communicate on the canbus), bluetooth and satellite radio.
The crummy thing is that, even after i unplug my device, the radio doesn’t start displaying messages, and the bluetooth and satellite radio are still disabled. It takes me turning off the car, and turning it back on for the radio and its peripherals to start working again.
Is there a way that I can tell the radio to wake back up and start sending messages over the bus again without having the cycle the vehicle?? THANKS!!!
July 20th, 2012 - 19:49
Paimon, this is huge…
I wouldn’t be able to do anything without having the devices in front of me.
I can only suggest that the messages may not be being ‘consumed’ correctly and are still floating around the bus? Otherwise if you are consuming the response then the radio may not be receiving the data and thinking no one is talking back? Therefore giving up?
Is your device in LISTEN mode? If not then you may be stopping messages from propagating through the network.
Sorry I can’t be of much help, Steven.
July 20th, 2012 - 19:39
hi i have a problem with your guessing game code it will not compile im sure im proberbly just missing a file somewere and wondered if you could be of assistance the errors on compiling are as follows:
listener.cpp: In function ‘void setup()’:
listener:42: error: ‘class CANClass’ has no member named ‘toggleRxBuffer0Acceptance’
listener.cpp: In function ‘void loop()’:
listener:97: error: ‘class CANClass’ has no member named ‘buffer0DataWaiting’
listener:98: error: no matching function for call to ‘CANClass::readDATA_ff_0(byte*, byte [8], uint32_t*, byte*, byte*)’
C:\Documents and Settings\Shuttle\Desktop\Arduino\arduino-1.0.1-windows\arduino-1.0.1\libraries\CAN/CAN.h:129: note: candidates are: static void CANClass::readDATA_ff_0(byte*, byte*, short unsigned int*)
listener:103: error: ‘class CANClass’ has no member named ‘buffer1DataWaiting’
listener:104: error: no matching function for call to ‘CANClass::readDATA_ff_1(byte*, byte [8], uint32_t*, byte*, byte*)’
C:\Documents and Settings\Shuttle\Desktop\Arduino\arduino-1.0.1-windows\arduino-1.0.1\libraries\CAN/CAN.h:130: note: candidates are: static void CANClass::readDATA_ff_1(byte*, byte*, short unsigned int*)
cheers if you can help
July 20th, 2012 - 19:51
pasted the wrong thing in here the error i reffer to is below
July 20th, 2012 - 19:52
Is this being compiled from the Arduino IDE? Sounds like it doesn’t know where CAN library is.
Have you put the CAN folder into your arduino/libraries folder?
I’m surprised it isn’t saying “cannot find CAN.h” though!
July 20th, 2012 - 19:49
hi i have a problem with your guessing game code it will not compile im sure im proberbly just missing a file somewere and wondered if you could be of assistance the errors on compiling are as follows:
CAN_test.cpp: In function ‘void setup()’:
CAN_test:19: error: ‘class CANClass’ has no member named ‘resetFiltersAndMasks’
CAN_test:20: error: ‘class CANClass’ has no member named ‘setMaskOrFilter’
CAN_test:20: error: ‘MASK_0’ was not declared in this scope
CAN_test:21: error: ‘class CANClass’ has no member named ‘setMaskOrFilter’
CAN_test:21: error: ‘MASK_1’ was not declared in this scope
CAN_test:22: error: ‘class CANClass’ has no member named ‘setMaskOrFilter’
CAN_test:22: error: ‘FILTER_2’ was not declared in this scope
CAN_test.cpp: In function ‘void loop()’:
CAN_test:54: error: no matching function for call to ‘CANClass::load_ff_0(byte&, uint32_t*, byte [8], int)’
C:\Documents and Settings\Shuttle\Desktop\Arduino\arduino-1.0.1-windows\arduino-1.0.1\libraries\CAN/CAN.h:144: note: candidates are: static void CANClass::load_ff_0(byte, short unsigned int, byte*)
CAN_test:61: error: ‘class CANClass’ has no member named ‘buffer1DataWaiting’
CAN_test:62: error: no matching function for call to ‘CANClass::readDATA_ff_1(byte*, byte [8], uint32_t*, byte*, byte*)’
C:\Documents and Settings\Shuttle\Desktop\Arduino\arduino-1.0.1-windows\arduino-1.0.1\libraries\CAN/CAN.h:130: note: candidates are: static void CANClass::readDATA_ff_1(byte*, byte*, short unsigned int*)
CAN_test:72: error: no matching function for call to ‘CANClass::load_ff_0(byte&, uint32_t*, byte [8], int)’
C:\Documents and Settings\Shuttle\Desktop\Arduino\arduino-1.0.1-windows\arduino-1.0.1\libraries\CAN/CAN.h:144: note: candidates are: static void CANClass::load_ff_0(byte, short unsigned int, byte*)
CAN_test:78: error: ‘class CANClass’ has no member named ‘setMaskOrFilter’
CAN_test:78: error: ‘FILTER_0’ was not declared in this scope
CAN_test:84: error: ‘class CANClass’ has no member named ‘buffer0DataWaiting’
CAN_test:85: error: no matching function for call to ‘CANClass::readDATA_ff_0(byte*, byte [8], uint32_t*, byte*, byte*)’
C:\Documents and Settings\Shuttle\Desktop\Arduino\arduino-1.0.1-windows\arduino-1.0.1\libraries\CAN/CAN.h:129: note: candidates are: static void CANClass::readDATA_ff_0(byte*, byte*, short unsigned int*)
CAN_test:97: error: no matching function for call to ‘CANClass::load_ff_0(byte&, uint32_t*, byte [8], int)’
C:\Documents and Settings\Shuttle\Desktop\Arduino\arduino-1.0.1-windows\arduino-1.0.1\libraries\CAN/CAN.h:144: note: candidates are: static void CANClass::load_ff_0(byte, short unsigned int, byte*)
CAN_test:105: error: ‘class CANClass’ has no member named ‘buffer1DataWaiting’
CAN_test:106: error: no matching function for call to ‘CANClass::readDATA_ff_1(byte*, byte [8], uint32_t*, byte*, byte*)’
C:\Documents and Settings\Shuttle\Desktop\Arduino\arduino-1.0.1-windows\arduino-1.0.1\libraries\CAN/CAN.h:130: note: candidates are: static void CANClass::readDATA_ff_1(byte*, byte*, short unsigned int*)
cheers if you can help
July 20th, 2012 - 19:56
Hmmm… newer version of the IDE… might be having issues because of that..
You could try renaming CAN.cpp to CAN.c … and then even try putting both of those inside your sketch folder (remove them from the libraries folder) and then reference them as #include “CAN.h” instead of the
Good luck.
October 9th, 2012 - 18:59
Heya stevenh brilliant blog…Your library does not support extended Id….am i right?
DO u maybe have a version with supporting ext frames?
Thx
October 12th, 2012 - 06:32
FaisEIT,
The receiving and sending code (I just downloaded it and checked it again, it has been a while) definitely supports Extended-mode packets.
Note that the last boolean argument indicates if your packet is to be extended in the functions load_ff_0, load_ff_1 and load_ff_2.
There are a lot of optimisations that could be done to that code!
Steven.
February 6th, 2013 - 19:31
Hi,
I’m completely new to CAN and Arduino, but thanks to your blog I think I understand things better now !
However, I’ve been asked to set up the communication between a PC and an Arduino Mega 2560 board, through a CAN bus. I have a USB to CAN adaptor, linked to a Sparkfun CAN-bus shield which is plugged onto the Arduino board. I’ve made the changes in the wiring (pins 50, 51 etc instead of pins 10, 11 etc) and I’m trying to get your loopback code working. Some dedicated software installed on my PC is sending messages through the CAN bus, and I’m trying to receive them on the Arduino board. But the “CAN.readStatus()” function always returns 0. I’ve set up the baud rates on my PC and on the MCP2515 to be 500kB/s.
Could you please help me understand what’s going on here ?
Thanks a lot,
Coline
February 7th, 2013 - 09:30
Coline,
It has been a really long time since I’ve worked on the CAN Bus, but here’s a few things to try:
– Make sure you have the same frequencies set on both nodes? What crystal comes with the USB node, can you open it up and see?
– Make sure you have the comms cable terminated with resistors correctly?
– Make sure every node is in the correct state? I don’t know what software comes with the USB node, but you should be able to set it into LISTEN or not. I’d recommend LISTEN to start with.
– Does the Sparkfun board come with RX/TX LEDs (Actually, I’ve just looked, it does) .. do they flash?
– Are you sure RX/TX wiring is correct from the DB-9 port on the Sparkfun shield? Also to the USB node?
Feel free to take photos and post the links.
Steven.
February 7th, 2013 - 21:44
Hi Steven,
Thanks for your quick reply. I finally got the loopback code working (between my Arduino board and the shield).
Sadly, the CAN communication still doesn’t work. I wired 120 Ohms resistors to both ends of the D9 cable. When I try sending messages through the CAN bus using the software provided with the adapter, an error message appears : “BUSHEAVY”. The receive buffers on the MCP2515 seem to be empty.
As you asked, I had a look at the crystal on the adapter. It uses a 24 MHz crystal, when the Arduino uses a 16 MHz crystal. Could that be a problem ?
As for the code, I’m using the canduino version, and I just changed the pin numbers in it, accordingly to the Arduino Mega 2560 datasheet.
Is there anything else I need to change in the original canduino code to get a really simple CAN communication working ?
Best regards,
Coline
February 8th, 2013 - 19:42
Hi Steven,
Problem solved : on the Shield, the pins corresponding to CAN_L and CAN_H are wired to the pins 3 and 5 of the cable, not on the usual 2 and 7 !
Thanks for the help anyway,
Best regards,
Coline
April 10th, 2013 - 05:48
Hello Steve,
I saw in your last post that you haven’t worked on the CAN bus in a while, but I was hoping you could still help. I’m attempting to use your listener code to read data from a peice of equipment that is transmitting data via CAN messages at a baud rate of 500 kBits/sec. I configured the listener program to the 500 kBits/sec but the data I receive through the serial monitor is completely gibberish.
Serial Monitor Output:
[Rx] Status:0 Len:F Frame:1FBDFBE EXT?:1 Filter:0 Buffer:0 Data:[FB 54 B4 57 EA E2 19 B7]
Example of a good CAN message:
Frame: 161 Data:[6 FF 0 6 55 72 3E 26]
Do you have any suggestions of what might be going on? I’m thinking it could be a timing issue.
Thanks,
Doug
April 10th, 2013 - 14:07
Doug,
First thing, what’s your setup? Are you using the libraries above? What Arduino? Have you successfully communicated with another Arduino or other CAN Device before?
In your program loop, are you clearing the variables that you are reading in to first?
Timing may well be an issue; depending on the crystal you’re using on your setup, setting ‘500’ may not actually be ‘500’ on the wire.
You’ll need to calculate the correct baud depending on your crystal. This has never been an issue on my end, as I was always creating home-grown nodes with the same crystals.
Also, you should try and set your node into NORMAL mode as well and see if the packets change after you’ve started receiving them.
Steven.
April 11th, 2013 - 01:25
Steven,
Sorry I forgot to include my setup in my previous post. I’m using an Arduino Mega 2560 with a CAN BUS shield from Sparkfun. I’m attempting to use the listener.ino file and CAN library you’ve provided on this website. I’ve modified the the library files to work with the Mega’s SPI pins. The Sparkfun shield has a 16MHz crystal on board.
Like I said before I’m attempting to use your code for simplicity to ensure everything works before moving on to my own code.
I tried to set the node into NORMAL mode with no luck.
Thanks,
Doug
May 2nd, 2013 - 23:08
Doug – were you able to get “listener” to work ? I have a similar problem. My environment (Arduino Mega/Can-shield – Arduino UNO/CAN-shield) tests OK with a different listener written with another library but I l like the one here better.
April 23rd, 2013 - 06:00
finally i have succeeded on canbus shield to be working on arduino 2560 mega.
first of all, the shield is desig for uno and needs extra wiring:
50=>12, 51=>11, 52=>13, 53=>10
secondly, DO NOT FORGET TO PLACE ~120OHM RESISTOR BETWEEN CAN_H -CAN_L . this item was caused hours of loss. again, don’t forget. otherwise you see a 0-1-0-1.. array.
here the sketch file: http://pastebin.com/7nx2XUm4
here is the header file: http://pastebin.com/Jz2Mqf4n
However, i couldn’t solve one problem. weirdly, i can only send to 3 different headers and at least i need 4 (of course canbus suport much more than 4 adresses). Any ideas?
April 23rd, 2013 - 06:16
issue solved! it has just need a null listener(maybe another node or can2usb listeners) i have listen the messages with tektronix and it is actually weird that bus overloading. interesting issue. it is not suprised to manufacturers alter canbus with flexibus.
April 30th, 2013 - 14:28
thank you!I’m a chinese student. I thank it’s very useful to me.
May 14th, 2013 - 08:23
I have connected arduinomuno to canbus sheild. i used a breadbd connecting pwr, gnd , reset, tx & rx. I have the tx of arduino going to rx of canbus sheild. Using the serial monitor, should i be able to send a 1 and then receive a 1?
I never get a response. I have also tried stacking the bds but still get no response. I have tried canduino and others.
Is there a diagram of how to connect these bds? Also when using the serial monitor will I see the response if its working?
Lastly, is there a command set that must be typed in the send window in order to get a response or should i be able to send anything as in hyperterminal loopback testing?
August 15th, 2013 - 03:04
Hello,
Thanks for taking the time to write this up and put it online.
I’m currently using your code to run a CAN bus, I get the nodes to transmit (which I can see using an oscilloscope), and to work in a loop back mode but I can’t seem to get the bus to receive anything.
Currently the bus has two nodes, one of these nodes is a SparkFun shield with the Arduino, the other is a homemade version of the former (using an MCP 2510 rather than a 2515). It appears this problem has occurred before for other people judging by what other people have posted. Do you have any idea what I’m doing wrong?
Thank you very much,
Matt
November 4th, 2013 - 19:57
Hi!
Thanks for this article on CAN! I am about to start working on CAN bus communication with arduino and I am wondering if there really isn`t any way to implement one arduino to be master CAN device, so it could send and recive data? I have a project to make and it looks like I will have to make both direction CAN communication. Does anyone have any idea how to do that?
Thanks,
Greg
November 6th, 2013 - 14:03
Greg,
The nodes above can send and receive data. You simply need to make sure your ‘send’ function doesn’t take up too much time or you’ll miss packets.
i.e. wait for packets until there is something to send (this could be triggered via an interrupt) and then send your data.
Steven.
November 12th, 2013 - 01:22
Hi Steve,
thank you so much for your article. Its REALLY helpfull.
I have 2 CAN Shields (from watterott), 1 arduino ONE and 1 arduino MEGA and I was able to do the loopback test from the canduino project using its canduino library.
https://code.google.com/p/canduino/downloads/detail?name=Canduino%20V2.0.zip
Both seem to work just fine.
Since this part was done I decided to take the next step:
I wanted to test the communication (sender and reciever) between 2 arduinos so I dowloaded your library and examples.
I pasted (just like in the loopback test) your modified version of CAN.ccp and CAN.h in the arduino library folder and when I try to compile your “CAN_test” or even the “loopback test”example I get the following error:
:(
D:\Users\jrp\Documents\Arduino\Software\arduino-1.0.5\libraries\canduino\CAN.cpp: In static member function ‘static void CANClass::begin()’:
D:\Users\jrp\Documents\Arduino\Software\arduino-1.0.5\libraries\canduino\CAN.cpp:8: error: ‘SCK_PIN’ was not declared in this scope
D:\Users\jrp\Documents\Arduino\Software\arduino-1.0.5\libraries\canduino\CAN.cpp:9: error: ‘MISO_PIN’ was not declared in this scope
D:\Users\jrp\Documents\Arduino\Software\arduino-1.0.5\libraries\canduino\CAN.cpp:10: error: ‘MOSI_PIN’ was not declared in this scope
D:\Users\jrp\Documents\Arduino\Software\arduino-1.0.5\libraries\canduino\CAN.cpp:11: error: ‘SS_PIN’ was not declared in this scope
D:\Users\jrp\Documents\Arduino\Software\arduino-1.0.5\libraries\canduino\CAN.cpp: In static member function ‘static void CANClass::setRegister(byte, byte)’:
D:\Users\jrp\Documents\Arduino\Software\arduino-1.0.5\libraries\canduino\CAN.cpp:134: error: ‘SS_PIN’ was not declared in this scope
D:\Users\jrp\Documents\Arduino\Software\arduino-1.0.5\libraries\canduino\CAN.cpp: In static member function ‘static void CANClass::setMode(CANMode)’:
D:\Users\jrp\Documents\Arduino\Software\arduino-1.0.5\libraries\canduino\CAN.cpp:167: error: ‘SS_PIN’ was not declared in this scope
D:\Users\jrp\Documents\Arduino\Software\arduino-1.0.5\libraries\canduino\CAN.cpp: In static member function ‘static void CANClass::readRXBuffer(byte, byte*, byte*, uint32_t*, byte*, byte*)’:
D:\Users\jrp\Documents\Arduino\Software\arduino-1.0.5\libraries\canduino\CAN.cpp:190: error: ‘SS_PIN’ was not declared in this scope
D:\Users\jrp\Documents\Arduino\Software\arduino-1.0.5\libraries\canduino\CAN.cpp: In static member function ‘static byte CANClass::readStatus()’:
D:\Users\jrp\Documents\Arduino\Software\arduino-1.0.5\libraries\canduino\CAN.cpp:225: error: ‘SS_PIN’ was not declared in this scope
D:\Users\jrp\Documents\Arduino\Software\arduino-1.0.5\libraries\canduino\CAN.cpp: In static member function ‘static void CANClass::load_ff(byte, byte, uint32_t*, byte*, bool, byte)’:
D:\Users\jrp\Documents\Arduino\Software\arduino-1.0.5\libraries\canduino\CAN.cpp:235: error: ‘SS_PIN’ was not declared in this scope
D:\Users\jrp\Documents\Arduino\Software\arduino-1.0.5\libraries\canduino\CAN.cpp: In static member function ‘static byte CANClass::getFilterHit(byte)’:
D:\Users\jrp\Documents\Arduino\Software\arduino-1.0.5\libraries\canduino\CAN.cpp:278: error: ‘SS_PIN’ was not declared in this scope
D:\Users\jrp\Documents\Arduino\Software\arduino-1.0.5\libraries\canduino\CAN.cpp: In static member function ‘static void CANClass::toggleRxAcceptance(byte, bool, bool)’:
D:\Users\jrp\Documents\Arduino\Software\arduino-1.0.5\libraries\canduino\CAN.cpp:312: error: ‘SS_PIN’ was not declared in this scope
D:\Users\jrp\Documents\Arduino\Software\arduino-1.0.5\libraries\canduino\CAN.cpp: In static member function ‘static void CANClass::clearRX0Status()’:
D:\Users\jrp\Documents\Arduino\Software\arduino-1.0.5\libraries\canduino\CAN.cpp:331: error: ‘SS_PIN’ was not declared in this scope
D:\Users\jrp\Documents\Arduino\Software\arduino-1.0.5\libraries\canduino\CAN.cpp: In static member function ‘static void CANClass::clearRX1Status()’:
D:\Users\jrp\Documents\Arduino\Software\arduino-1.0.5\libraries\canduino\CAN.cpp:340: error: ‘SS_PIN’ was not declared in this scope
I did not get this errors when I used the library from canduino, do you any idea what may be my problem? how can I solve it?
Thanks in advanced
Juan
November 12th, 2013 - 13:53
Juan,
I have the following declares in my code for the variables that you are missing:
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
#define SCK_PIN 13
#define MISO_PIN 12
#define MOSI_PIN 11
#define SS_PIN 10
#endif
#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2650__)
#define SCK_PIN 52
#define MISO_PIN 50
#define MOSI_PIN 51
#define SS_PIN 53
#endif
It seems that your board has a different define… therefore the above aren’t getting picked up.
Do you know what pins the three listed above are for your boards? If so, I would remove the code I’ve pasted here from CAN.h and paste in the code below:
#define SCK_PIN 52
#define MISO_PIN 50
#define MOSI_PIN 51
#define SS_PIN 53
Make sure you replace the values there with the correct pins for your boards though!
This may well be an issue with the new Arduino code. 1.0.1 caused issues and now I’ll download and test 1.0.5.
Thanks for the heads-up!
November 13th, 2013 - 21:04
Hi stevenh,
I see you have this in the CAN.h file:
defined(__AVR_ATmega2650__)
Should that not be defined(__AVR_ATmega2560__)?
Regards.
November 14th, 2013 - 08:28
dminnaar,
Thanks! You’ve pointed out the issue!
It seems that I fixed this in the past but managed to upload a bad version.
This has now been repaired once and for all… I’m now using the SS,MISO,MOSI,SCK variables from pins_arduino.h so these can now never be wrong (unless Arduino themselves get it wrong!)
Please download the zip again.
November 22nd, 2013 - 03:16
OK, this may sound stupid but I got everything confused. I set up two arduinos, one is uno and one is mega ADK, which is basically the same as mega2560. Now I dont know how to test this, I mean I downloaded the library and code, there are few programs.
I just want to establish simple comunication between arduinos. What sketch should I upload? If I get it right the loopback test is to be used with only one arduino? connect it to the shield and it sholud work?
Well if I do that, I open serial monitor and get only:
sending an ext packet.
sending a standard packet.
…and that repeats forever.
Then I uploaded a CAN_test sketch on each arduino, conected the shields with wires, opened the serial monitors and I am getting random numbers between 1 and 15 or similar.
I dont know whether I am too tired or just too stupid to understand this so any help or explanation will be much appreciated!
Oh, and in the CAN.h library I changed this line for mega ADK. Is this right?
#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2650__) || defined(__AVR_ATmegaADK__)
Thanks,
Greg
November 22nd, 2013 - 08:12
Greg,
You should not have needed to edit the CAN.h header. I imagine you changed the code that has been commented out… your change would have had no effect. I’ve now re-uploaded the source and deleted that section entirely as we now rely on the arduino libraries to define this all for us.
Meanwhile… try the CAN_test project. Load it on to both Arduinos and report back on the console log. One should indicate that it is guessing, the other will state the number to be guessed.
If you are just seeing a whole lot of guesses on both then you’ve got them both set to guess. This would make sense actually, as your board isn’t defined at the start.
In the re-upload, I’ve changed the code to #else instead of two ifs… this should then set one of your nodes to the guesser and the other to the setter.
Re-download the code, give it a go and show me the output.
Make sure that the setup function of CAN_test.ino looks like:
November 22nd, 2013 - 19:32
Thanks for quick response!
OK, so I uploaded the CAN_test as you propoused. In the serial monitors I get:
This node will start off guessing…8,1,3,10,2,13,13,8,1,5,4,4,9,3,11,1,1,3,12,13… and so on. And the other:
This node will be waiting for the correct guess…Guess has been set at: 1
{#0}:8!
Other party got it on filter: 0
Sender:
6,1,5,8,6,12,5,5,6,2,14,1,11,6,2,4,14,14,6,4,3,13,1,12,2,12,3,1,11,5,4,12,2,6,5,2…
And the numbers are flying on and on.
November 22nd, 2013 - 21:10
Oh, and one other thing. About the hardware. I built shield based on your schematic. I have INT and RST pin from 2515 conected directly to arduino without pull up resistors. On every other shield comercally avalible there are pull up resistors on int and reset.
And the other thing about connecting those two… Some say you can connect them to any pin some say to pin 2 and 3… Which one is right?
December 13th, 2013 - 06:48
Hello,
great post ! Thank you for all the that information, has been of much help.
I’m trying to listen to a CAN bus although something seems to go bad …
What i get as out is: http://pastebin.com/GdsH7t5v
The other node on bus is a proprietary logging system that streams channels over bus.
I can apply send IDs, i’ve checked different setting but nothing changed, both from system and arduino sketch.
From my system i know that IDs can’t be more than 0x5FF
Any ideas would be helpful.
Thanks again!
December 13th, 2013 - 07:09
Good morning John,
From the output I’m not seeing anything erroneous… Although I have just woken up.
I’m more curious as to what data you actually expect to see on the network?
Is there a chance what you’re seeing needs to be deciphered?
Steven.
March 26th, 2014 - 07:52
Thank you for your reply, it seems i’m having trouble with the library.
I have a system that sends messages with ids 0x24 and 0x170.
the 0x24 is a time message and
the 0x170 is data form sensor
I use sparkfun CAN bus shield, and it works correctly with the library from CANduino project which seems to be a previous version of that you use.
I have to note that when i disconect the sender device from network i don’t get output to terminal, so my CAN node listens, but listens something very bad.
I’ve lost a lot of time to fix it but i haven’t found solution.
Thank you in advance
April 23rd, 2015 - 00:23
I have a problem which I have seen allot here, I can send but not receive data, the program senses that a can message is available but it is just random thing.
like this: (from a previous comment) http://pastebin.com/GdsH7t5v
January 11th, 2014 - 10:40
Wow that was strange. I just wrote an very long comment but after I clicked submit my comment didn’t show up.
Grrrr… well I’m not writing all that over again.
Regardless, just wanted to say wonderful blog!
March 26th, 2014 - 19:17
Hi
I have been following your schematic and have been built the can controller/transciever circuit. I have connected to my uno but have gotten no response from the 2515. Im a bit concerned with the pinouts that are not used 4,5,6,17,12 etc. are the to be tied high or low ?
March 28th, 2014 - 09:12
Shane,
Check out the datasheet, especially page 4: http://ww1.microchip.com/downloads/en/DeviceDoc/21801G.pdf
You’ll see that all the pins you’ve mentioned have internal pullup resistors on them.
Pins 4-6 are configurable and allow you to drive when buffers are ready to be transmitted instead of triggering the TXREQ bits via a packet.
12 is the ‘general’ interrupt … where an interrupt is triggered if you’ve configured an event to cause it. 17 is the reset switch which you touch if you want to reboot the state machine inside the 2515.
Highly recommend scouring the doco :)
May 18th, 2014 - 08:27
Thank you, for this post, it help me very much to understand the can bus.
June 6th, 2014 - 20:47
Very well explained & documented.Thank you so much.
June 24th, 2015 - 16:25
This loopback test worked for short time. for five frames may be. But it doesn’t any more. :(
What could be the problem. I followed the above circuit you provided.
Please respond.
July 30th, 2015 - 22:19
Hello,
I have a little question, how du you put the MCP2515 in loopback mode? Nice post by the way :)
January 12th, 2016 - 21:33
I’m sure you’ve already found the answer to this, but for anyone else… this is done via the library. Use the CAN.setMode(); function.
November 27th, 2015 - 04:04
Thanks for this info. Can you explain the loopback test connections. Is this one node (CAN Transceiver) sending a message, and reading the message it is sending? or are you using 2 nodes, e.g. Node 1 sends message to Node 2, Node 2 replies back with the same message? I was under the assumption a single node cannot send a message to itself.
January 12th, 2016 - 21:34
No other nodes are used. Loopback expects no CAN connection. The chip, internally, copies the TX’d data into the RX buffer. So, as per the sample code, data is sent, the code pauses and then the RX buffers are read.
January 12th, 2016 - 15:41
Hi.
Looking 2 last comments and hoping someone will reply. I am also having trouble doing LOOPBACK test. Not sure where to connect canH and CanL gonig into MCP2551 since i have no other node, only 1, and wanna do simple loopback test. is everything else connected according to schematic or do I have to change something else?
January 12th, 2016 - 21:41
Is loopback not working at all? usually you’d connect CANH/L to a bus with no other nodes, so just create as per the very first image in this post, without the left and right nodes. I’ve actually just tried to remember what I did, but I can’t confirm if loopback will work without any bus connection.
January 12th, 2016 - 23:18
I tried this. I connected everything like in schematic, but i was thinking that for loopback test MCP2515 is sending to itself, so i disconnected 2 wires connecting MCP2515 and 2551. So, I got some data on serial monitor.
In several runs I managed to get exact data I was sending, but only few times and only for few first loop() calls. Now I only get data like: rx_status 7F, and data all FF FF FF FF FF with length F….. Any ideas? I was thinking I managed to do it since I saw correct data displayed few times…. But now cant get it to work…. Am I missing something?
January 14th, 2016 - 04:15
To reply to my own post….. Found what I did wrong…. I didnt connect 2515 RESET To Pin 2 of Arduino…. Now loopback works great……
October 18th, 2016 - 07:40
Can your CAN library be used with the Sparkfun can shield? What needs to be configured?
Thanks
October 18th, 2016 - 11:46
Hi Vic,
What interface does the shield provide? If it’s SPI then it should actually already map to the correct SPI pins on your Arduino. What Arduino do you have?
October 19th, 2018 - 03:47
hello! i want to interface mcp2515 and mcp2551 with arm lpc2148? can i use these libraries ? or what are the changes i have to make ??please help me out
October 19th, 2018 - 14:54
Hi Pavan,
The libraries above are based off the Arduino stack. Maybe you could use them if you emulate all of the calls that are used.
Try and compile the code above with your standard include libraries and then see what the errors are. You’ll then just need to define mapping functions to translate to your native CPU calls.
Steven.
August 6th, 2021 - 12:06
Hey,
Just impressed by your electronic projects on your blog!
Really looking forward to see your plan comes true and go further.
I’m Wendy,the marketing guy from a PCB manufacturer called PCBWay in
China.
We would like to support you to finish the project with providing free PCB
board or maybe cooperate in other terms you may interested in.
Hope to get your reply.