Can the Arduino MKR ZERO work with the Arduino MKR CAN shield?

I tried to use the Arduino MKR ZERO to control the Arduino MKR CAN shield to send CAN signal to another device, but I failed to receive the signal when using an Arduino UNO with mcp2515 CAN module as a receiver.

I used the sample codes in the mcp2515 library (https://github.com/autowp/arduino-mcp2515) for the test and these codes worked when I tried to set up the communication between two Arduino UNO. So I am wondering if the MKR ZERO is not compatible with the MKR CAN shield.

code for the sender:

#include <SPI.h>
#include <mcp2515.h>

struct can_frame canMsg1;
struct can_frame canMsg2;
MCP2515 mcp2515(10);


void setup() {

  canMsg1.can_id  = 0x0F6;
  canMsg1.can_dlc = 8;
  canMsg1.data[0] = 0x8E;
  canMsg1.data[1] = 0x87;
  canMsg1.data[2] = 0x32;
  canMsg1.data[3] = 0xFA;
  canMsg1.data[4] = 0x26;
  canMsg1.data[5] = 0x8E;
  canMsg1.data[6] = 0xBE;
  canMsg1.data[7] = 0x86;

  canMsg2.can_id  = 0x036;
  canMsg2.can_dlc = 8;
  canMsg2.data[0] = 0x0E;
  canMsg2.data[1] = 0x00;
  canMsg2.data[2] = 0x00;
  canMsg2.data[3] = 0x08;
  canMsg2.data[4] = 0x01;
  canMsg2.data[5] = 0x00;
  canMsg2.data[6] = 0x00;
  canMsg2.data[7] = 0xA0;
  
  while (!Serial);
  Serial.begin(115200);
  SPI.begin();
  
  mcp2515.reset();
  mcp2515.setBitrate(CAN_125KBPS);
  mcp2515.setNormalMode();
  
  Serial.println("Example: Write to CAN");
}

void loop() {
  
  mcp2515.sendMessage(&canMsg1);
  mcp2515.sendMessage(&canMsg2);

  Serial.println("Messages sent");
  
  delay(100);

}

code for the receiver:

#include <SPI.h>
#include <mcp2515.h>

struct can_frame canMsg;
MCP2515 mcp2515(10);


void setup() {
  Serial.begin(115200);
  SPI.begin();
  
  mcp2515.reset();
  mcp2515.setBitrate(CAN_125KBPS);
  mcp2515.setNormalMode();
  
  Serial.println("------- CAN Read ----------");
  Serial.println("ID  DLC   DATA");
}

void loop() {
  
  if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
      
    Serial.print(canMsg.can_id, HEX); // print ID
    Serial.print(" "); 
    Serial.print(canMsg.can_dlc, HEX); // print DLC
    Serial.print(" ");
    
    for (int i = 0; i<canMsg.can_dlc; i++)  {  // print the data
        
      Serial.print(canMsg.data[i],HEX);
      Serial.print(" ");

    }

    Serial.println();      
  }

}

there was nothing wrong with the compiling and uploading of the code, I just could not receive anything from the Arduino UNO. I tried to change the CS to another pin but it still didn't work.

Can the Arduino MKR ZERO work with the Arduino MKR CAN shield?

Definitely.

There are some important things to know:
The markings on the silkscreen on the bottom of the MKR CAN Shield may be wrong. On mine, the CANL and CANH markings are switched with each other. The correct order of the pins on the terminal block is:

  • VIN
  • CANH
  • CANL
  • GND

The other important thing is that the shield's CS pin is pin 3. So on the sketch you upload to your MKR Zero, you should have this line:

MCP2515 mcp2515(3);

As for the Uno, it just depends on which pin on the Uno you connected the CS pin of your MCP2515 module to.

After that, I still couldn't make it work with the arduino-mcp2515 library, though I had no problems with this library https://github.com/Seeed-Studio/CAN_BUS_Shield. I took a look at the arduino-mcp2515 library source and noticed they do hardware configuration in the constructor, which is definitely a no-no. There is a pull request to fix this:
SPI fix, new begin command and allow oneshotmode by milesfrankland · Pull Request #30 · autowp/arduino-mcp2515 · GitHub
With those changes, it works fine for me.
You can download the modified library here:
https://github.com/milesfrankland/arduino-mcp2515/archive/master.zip
With the modified library, you need to change this line in your sketches:

mcp2515.reset();

to:

mcp2515.begin();

pert:
Definitely.

There are some important things to know:
The markings on the silkscreen on the bottom of the MKR CAN Shield may be wrong. On mine, the CANL and CANH markings are switched with each other. The correct order of the pins on the terminal block is:

  • VIN
  • CANH
  • CANL
  • GND

Amazing! I get the signal!
I tried several different libraries and none of them worked yesterday, because it was unimaginable that the silkscreen was wrong on the shield.
Thank you very much!

pert:
The other important thing is that the shield's CS pin is pin 3. So on the sketch you upload to your MKR Zero, you should have this line:

MCP2515 mcp2515(3);

As for the Uno, it just depends on which pin on the Uno you connected the CS pin of your MCP2515 module to.

After that, I still couldn't make it work with the arduino-mcp2515 library, though I had no problems with this library https://github.com/Seeed-Studio/CAN_BUS_Shield. I took a look at the arduino-mcp2515 library source and noticed they do hardware configuration in the constructor, which is definitely a no-no. There is a pull request to fix this:
SPI fix, new begin command and allow oneshotmode by milesfrankland · Pull Request #30 · autowp/arduino-mcp2515 · GitHub
With those changes, it works fine for me.
You can download the modified library here:
https://github.com/milesfrankland/arduino-mcp2515/archive/master.zip
With the modified library, you need to change this line in your sketches:

mcp2515.reset();

to:

mcp2515.begin();

I try to use the new library for both MKR and UNO, and it seems like the signal received from the UNO is not the same as that sent from the MKR. What I send from the MKR should be

 canMsg1.can_id  = 0x0F6;
  canMsg1.can_dlc = 8;
  canMsg1.data[0] = 0x8E;
  canMsg1.data[1] = 0x87;
  canMsg1.data[2] = 0x32;
  canMsg1.data[3] = 0xFA;
  canMsg1.data[4] = 0x26;
  canMsg1.data[5] = 0x8E;
  canMsg1.data[6] = 0xBE;
  canMsg1.data[7] = 0x86;

  canMsg2.can_id  = 0x036;
  canMsg2.can_dlc = 8;
  canMsg2.data[0] = 0x0E;
  canMsg2.data[1] = 0x00;
  canMsg2.data[2] = 0x00;
  canMsg2.data[3] = 0x08;
  canMsg2.data[4] = 0x01;
  canMsg2.data[5] = 0x00;
  canMsg2.data[6] = 0x00;
  canMsg2.data[7] = 0xA0;

but what I received is:

40000310 5 0 0 0 0 3E 
40000310 5 0 0 0 0 3E 
40000344 5 0 0 0 0 3E 
40000310 5 0 0 0 0 3E 
40000310 5 0 0 0 0 3E 
40000350 5 0 0 0 0 3E 
40000310 5 0 0 0 0 3E 
40000310 5 0 0 0 0 3E 
40000344 5 0 0 0 0 3E 
...

And the updating speed in the UNO is much faster than the speed of sending signals from the MKR.
I've read the document for the modified library and it seems like that the pin allocation is for UNO instead of MKR (e.g. in GitHub - milesfrankland/arduino-mcp2515: Arduino MCP2515 CAN interface library, the SI and SO should be connected to D11 and D12, respectively. However, the MISO and MOSI of MKR and the CAN shield are pin 10 and pin 8.) I am wondering if this is the reason. Did you have the same problem and if you have any potential solution for that?
Thanks again for your answer.