Arduino MKR CAN shield SPI bus clock speed issue (SOLVED)

Hi all,

I wanted to share the below experience and solution of integrating an MKR CAN shield into larger projects. I did not find posts that already discussed this, and I hope it may serve some people.

I was doing some project where I wanted to integrate the Arduino MKR CAN shield into projects, using MKR Zero and MKR 1010 Wifi boards. But while the example sketches in the Arduino IDE (CANSender and CANreceiver) worked well when nothing else was connected, every time I try to integrate them into a larger system, with other SPI components or hardware, these sketches failed to run. I started checking the usual suspects (conflicts in CS and IRQ signals) but there was no problem there.

Long study cut short, I received a clue when I was taking a bare Arduino MKR Zero with only a MKR CAN shield, and connected some loose 10cm flat ribbon wire – not connected to anything – and the shield stopped working!!! So even the small capacitance of that loose wire seemed to set things astray.

A further inspection on an oscilloscope showed the following: the SPI SCK signal did not look very healthy (see attached screenshot: considerable rise and fall times, almost a sine wave), and its measured frequency was 12.0 MHz. Looking at the data sheet of the MCP2515, the chip on the CAN shield that handles the SPI interface, we see in Table 13.6 that the maximum clock frequency of the SPI bus is 10MHz and clock high time should be 45ns at minimum. The default Arduino sketches do not meet these requirements, as the measured clock is 12MHz and the measured clock high time is slightly below 45ns. This may well explain the unstable behaviour and the issues I described above.

For me, the solution was to slow down the SPI bus when running the CAN shield communication. In the CAN library that the Arduino example uses (by Sandeep Mistry, GitHub here), the speed can be set to a lower value by opening MCP2515.cpp and changing the below line.

_spiSettings(10E6, MSBFIRST, SPI_MODE0) 
// measured clock 12.0 MHz with MKR Zero
// This is the original value in the library, but has stability issues 

_spiSettings(5E6, MSBFIRST, SPI_MODE0) 
// measured clock 6.0 MHz with MKR Zero
// slower clock, but now stable 

_spiSettings(1E6, MSBFIRST, SPI_MODE0) 
// measured clock 0.87 MHz with MKR Zero
// even much slower clock, but now stable

With these lower speeds, the CAN sketches still ran perfectly. After that, I tried several integration projects (including a project with an ArduiTouch that has large SPI-controlled LCD touch screen, connected to a model train rail controller using CAN bus protocol (Märklin 60657 Mobile Station) and it now all works as it should.