CAN communication

Hello everyone,

I currently trying to build a CAN interface for Arduino based on this post. I set up two Arduino Nanos with the same setup. The chips are powered over their respective Arduinos. The only connection is GND, CANH, CANL (see picture).

Since the library mentioned in the post did not work, I now use this. It just read/writes the registers more efficiently.

The write-code:

#include <Arduino.h>

#include <mcp2515.h>

struct can_frame canMsg1;
struct can_frame canMsg2;

MCP2515 can(10);

void setup() {
    Serial.begin(9600);   //to communicate with Serial monitor
    SPI.begin();

    can.reset();
    can.setBitrate(CAN_125KBPS);
    can.setNormalMode();

    Serial.println("---Setup: Write---");  

    uint8_t stat = can.getStatus();

    Serial.print("status = "); Serial.println(stat);

    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;

    Serial.println("---Setup: End ---");  
}

//loading the data bytes of the message. Up to 8 bytes
unsigned char data[8] = {'C', 'a', 'r', 't', 'e', 'r', 'a', '!'};

void loop() {
    //CAN.sendMsgBuf(msg ID, extended?, #of data bytes, data array);
    
    
    can.sendMessage(&canMsg1);
    // can.sendMessage(&canMsg2);
    Serial.println("write");
    delay(2000);                     
}

the write-Code:

#include <Arduino.h>

#include <mcp2515.h>

struct can_frame canMsg;

MCP2515 can(10);

void setup() {
    Serial.begin(9600);   //to communicate with Serial monitor
    SPI.begin();

    can.reset();
    can.setBitrate(CAN_125KBPS);
    can.setNormalMode();

    Serial.println("---Setup: Read---");  

    uint8_t stat = can.getStatus();

    Serial.print("status = "); Serial.println(stat);


    Serial.println("---Setup: End ---");  
}

//loading the data bytes of the message. Up to 8 bytes
unsigned char data[8] = {'C', 'a', 'r', 't', 'e', 'r', 'a', '!'};

void loop() {
    //CAN.sendMsgBuf(msg ID, extended?, #of data bytes, data array);
    
    
    if (can.readMessage(&canMsg) == MCP2515::ERROR_OK) {
      
    Serial.print("ID:");
    Serial.print(canMsg.can_id, HEX); // print ID
    Serial.print("\t"); 
    Serial.print("DLC:");  
    Serial.print(canMsg.can_dlc, HEX); // print DLC
    Serial.print("\t");
    Serial.print("DAT:");      
    for (int i = 0; i<canMsg.can_dlc; i++)  {  // print the data
        
      Serial.print(canMsg.data[i],HEX);
      Serial.print(" ");

    }

    Serial.println();      
  }                   
}

The output reads

ID:9FFFFF80     DLC:0   DAT:
ID:400  DLC:0   DAT:
ID:0    DLC:0   DAT:
ID:9FFFFF00     DLC:0   DAT:
ID:0    DLC:8   DAT:0 0 0 0 0 0 F0 F8 
ID:9FFFFFFF     DLC:8   DAT:FE F8 E0 E0 C0 E0 F0 E0 
ID:40000000     DLC:0   DAT:
ID:9FFF0000     DLC:0   DAT:
ID:DFDFFEFC     DLC:8   DAT:FE FE FF FE F8 F8 F0 F0

but even if I send every 2000ms the messages do not come through every time and even if it does the messages are not the same.

I measured the some signals with my osci. The clock, the SPI communication (from Nano to MCP2515) and the power level seem right. The outputs of RX,TX of the MCP2515 to the MCP2551 shows somekind of signal, but I do not know how this communication should look like (probably with the same bitstream as the SPI). Also the Signal from CANH and CANL show not the original message (based on the standard CAN frame protocol).

Does anyone has experience with CAN communication using MCP2515 and a transceiver?

The only difference between my custom setup and a commercial shield is, that the breadboard setup has a lot of long cables and everything is very noisy and not as clean as on a PCB.

Using this library GitHub - coryjfowler/MCP_CAN_lib: MCP_CAN Library
try the loopback test for each Arduino, then the send and receive examples.

Sorry for the late reply.
I will try it with the mentioned library.

Loop-back test on both Nanos successful.

After implementing the Send-Receive Example I get following message after data frame is send.

From the SENDER

Entering Configuration Mode Successful!
Setting Baudrate Successful!
MCP2515 Initialized Successfully!
Error Sending Message...

From the RECEIVER

Entering Configuration Mode Failure...
Error Initializing MCP2515...
MCP2515 Library Receive Example...

I changed SENDER-RECEIVER and get an even weirder message from the RECEIVER

Entering Configuration Mode Successful!
Setting Baudrate Successful!
MCP2515 Initialized Successfully!
MCP2515 Library Receive Example...
Standard ID: 0x000       DLC: 0  Data:

My guess is that one Nanosetup is corrupted, noisy, defective. I will solder another chip to a PCB and try again

Changed the crystal and capacitors, because the signal on the Osci wasnt good enough (compared to the other Nano).

Loopback still works.
Now both chips get initialized correctly, but still cant send message out (there is also no bussignal between CANH, CANL).

WRITER

Entering Configuration Mode Successful!
Setting Baudrate Successful!
MCP2515 Initialized Successfully!
Error Sending Message...

RECEIVER

Entering Configuration Mode Successful!
Setting Baudrate Successful!
MCP2515 Initialized Successfully!
MCP2515 Library Receive Example...

Next step will be diving into the Library (MCP_CAN from @mikb55) in close comparison with the datasheet of the MCP2515 and 2551

On the sender disconnect the driver from the MCP2515.

Send a message and check for activity on the MCP2515 output.

If that works reconnect the driver and check for activity on its output.

If that doesn't work test the driver in isolation by sending it a 20 kHz square wave.
If nothing comes out, then you have destroyed it.

Not exactly sure what is happening but generally in the micro computer world when can devices would not communicate the ACK was not being returned to the transmitter. This is the reason you have to have at 1 node receiving and another transmitting.
Good Luck & Have Fun!
Gil

Update:

It was probably just a hardware problem based on my sloppy setup. I used a commercial CAN-Shield for Arduino and tested it with my setup. Sometimes the signal went through. I took the time and build my own shield on a breadboard (short cables, no loops) and it worked flawlessly. Even the Bitstream has less noise and no oscillation on the edges.

Going back to the breadboard with the jumper wires AND an external stable clock (from an NI measurement card) the other setup also works (much more noise).

I also tested both libraries suggested in this thread and can confirm that both work.

My conclusion: the crystal with the capacitors should not have unnecessary connections and cable length or at least should produce a stable pulse frequency. If anyone can confirm my reasoning I will close this thread

Have you added termination resistors at each end ?

you need to have 2 resistors 120ohms at the end of the can bus wires to stop signal reflection.

@tinman: Yes. 100Ohm was the recommendation in the datasheet