Debugging CAN Problem

(deleted)

(deleted)

can_library_comparison.ino (7.19 KB)

It's somewhat sad that the CAN and RS485 software or driver support is really lacking on the Arduino platform, despite it being available for a fairly long time now. I get that it is more of a means of sending serial data than something that truly needs a great deal of code but the hardware to handle CAN and RS485 is available in bulk for fairly cheap and can be fairly feature rich but the struggle of getting RS485 going took several years and some very committed people making somewhat custom hardware and then making it available for sale. You can also buy some cheap junk too but you really, really should optically isolate a 12V CAN or RS485 from a 3.3V Arduino and that sadly doesn't seem like standard practice. Certainly not for $3 modules.

There is at least official MKR module units available now for the CAN and RS485 side of things though as usual, the prices are fairly high and it's not even isolated.

Is there anything in your code that prevents the handleCAN interrupt (and therefore CAN0.readMsgBuf) from running while you are in the middle of doing a CAN0.sendMsgBuf ?

I'm not sure the MCP2515 or the libraries are capable of coordinating the communication required for a simultaneous receive and send. In my code I always detach the receive interrupt before doing a send and then reattach it afterwards. I also use level rather than edge interrupts as the interrupt line stays low while the the MCP2515 has data.

Also beware of libraries that have blocking send functions.
Does your MCP2515 have a 16 MHz crystal? You need that to do 1Mbps.
Also a 16 MHz Nano needs about 1.6 milliseconds to read a single message from a MCP2515 which is a problem at high baud rates because messages can arrive faster than that.

The ESP32 CAN library ESP32CAN.h (ESP32 only) is able to receive and send can messages at near the same time as well as queue the unprocessed CAN messages. I use CAN_SPEED_1000KBPS.

(deleted)

(deleted)

(deleted)

(deleted)

can_library_comparison.ino (9.38 KB)

(deleted)

Regarding the expected vs observed baud rate, some of the libraries are written with the assumption that a 16 MHz crystal is being used. If you are using a 8 MHz crystal then you need to adjust the crystal setting which is either hidden inside the library, or is exposed via the library interface.

Fundamentally I don't see anything wrong with the libraries that only read a single message from the MCP2515. The front page of the datasheet tells you that there are 2 receive buffers so you know that you may have to do multiple reads to get all the data.

It sounds like you were expecting the libraries to do multiple reads and buffer the data for you. Unless the documentation claims to do this then they probably don't as this increases the memory footprint and ties up the SPI bus for longer.

Using edge interrupts, as per the example programs, is fine providing that you poll the device after receiving a message to see if the second buffer also has a message. However if you use level instead of edge interrupts then the interrupt handler will fire whenever the MCP2515 has data so you don't need to do polling.

Also the nature of the CAN bus protocol means the rate at which you send messages from the Arduino isn't necessarily the same as the rate at which they get put onto the CAN bus. For example if an Arduino attempts to send 3 messages at 50 millisecond intervals and the bus is busy, they will be queued in the Tx buffers until the bus is free and then all 3 will be sent with minimal delay. On a 500 kHz bus you'll see a train of 3 messages at intervals of less than 1 millisecond. In this scenario a Nano/MCP2515 combination at the receiving end will be too slow to capture all 3 messages.

sparky961:
LIB2 ( GitHub - pierremolinaro/acan2515: MCP2515 CAN Controller Driver for Arduino ) is still the only one that runs my test continuously without failing.

If you look in the library code you'll see that the ACAN2515::tryToSend function disables all interrupts before talking to the MCP2515.
To me this looks like more evidence that the MCP2515 isn't capable of doing a simultaneous send and receive.
Back in post #3 I mentioned needing to temporarily detach the interrupt handler for the receive function when doing a send. Effectively the ACAN2515 library it's doing the same thing as I do except in a less precise manner as noInterrupts() affects everything including the Arduino millisecond timer.

(deleted)

(deleted)

(deleted)

can_library_comparison.ino (9.35 KB)

(deleted)