Mcp2515 packets lost or how to check packets.

Hello. I’m using two mcp2515 modules with 16mhz oscillator and one arduino nano. This dual can adapter. I connect it to mercedes can bus 500 kbs with Standart id’s. I transmitt all packets, except one. With IF i find my packet, modify it and send to network. But i have an error in car ecu that packets by can bus are missing or wrong. I have this error if i don’t modify any packets and use sketch dual-can for mcp2515, which i found in the web
.

// Demo: Dual CAN-BUS Shields, Data Pass-through
// Written by: Cory J. Fowler
// January 31st 2014
// This examples the ability of this library to support more than one MCP2515 based CAN interface.


#include <mcp_can.h>
#include <SPI.h>

unsigned long rxId;
byte len;
byte rxBuf[8];

byte txBuf0[] = {AA,55,AA,55,AA,55,AA,55};
byte txBuf1[] = {55,AA,55,AA,55,AA,55,AA};

MCP_CAN CAN0(10);                              // CAN0 interface usins CS on digital pin 10
MCP_CAN CAN1(9);                               // CAN1 interface using CS on digital pin 9

void setup()
{
  Serial.begin(115200);
  
  // init CAN0 bus, baudrate: 250k@16MHz
  if(CAN0.begin(MCP_EXT, CAN_250KBPS, MCP_16MHZ) == CAN_OK){
  Serial.print("CAN0: Init OK!\r\n");
  CAN0.setMode(MCP_NORMAL);
  } else Serial.print("CAN0: Init Fail!!!\r\n");
  
  // init CAN1 bus, baudrate: 250k@16MHz
  if(CAN1.begin(MCP_EXT, CAN_250KBPS, MCP_16MHZ) == CAN_OK){
  Serial.print("CAN1: Init OK!\r\n");
  CAN1.setMode(MCP_NORMAL);
  } else Serial.print("CAN1: Init Fail!!!\r\n");
  
  SPI.setClockDivider(SPI_CLOCK_DIV2);         // Set SPI to run at 8MHz (16MHz / 2 = 8 MHz)
  
  CAN0.sendMsgBuf(0x1000000, 1, 8, tx0Buf);
  CAN1.sendMsgBuf(0x1000001, 1, 8, tx1Buf);
}

void loop(){  
  if(!digitalRead(2)){                         // If pin 2 is low, read CAN0 receive buffer
    CAN0.readMsgBuf(&rxId, &len, rxBuf);       // Read data: len = data length, buf = data byte(s)
    CAN1.sendMsgBuf(rxId, 1, len, rxBuf);      // Immediately send message out CAN1 interface
  }
  if(!digitalRead(3)){                         // If pin 3 is low, read CAN1 receive buffer
    CAN1.readMsgBuf(&rxId, &len, rxBuf);       // Read data: len = data length, buf = data byte(s)
    CAN0.sendMsgBuf(rxId, 1, len, rxBuf);      // Immediately send message out CAN0 interface
  }
}

/*********************************************************************************************************
  END FILE

Please tell me why it could be? Maybe arduino nano is too slow? How can i check the packets for errors or how i can enable rollover? Thanks.

Your requirement said "500 kbs with Standart id's" but the code is using 250 kbps with extended addressing.

I paste here code from example. I changed in it only speed to 500 kbps on both can. And i have an error. How can i check how much packets i send and receive on each can? How i can turn on rollover. I read that i need turn BUKT bit, but i don't know how to do that.

Check the success/fail return code from CAN0.sendMsgBuf.
Have you figured out whether you need extended or standard addresses?

I would be surprised if the relatively slow Arduino/MCP2515 combination is able to act a passthrough for a 500 kbps bus if there is lots of traffic.

I have never touched the default settings for rollover/BUCT. Are you trying to solve a particular problem?

Not familiar with how the Mercedes modules handle errors, but as you say you have similar issues with an example sketch, are these reported "missing or wrong messages" actually error frames? I.e. due to baudrate mismatch / extended frame use as commented above, or missing terminator resistor, as your connected HW is an end node?

Hello/ Thanx for answers. I have an errors only on can1

Transmit error counter register value: 0
Receive error counter register value: 0
Error register value: 1000000

Google says that it is overflow.

My code is:

// Demo: Dual CAN-BUS Shields, Data Pass-through
// Written by: Cory J. Fowler
// January 31st 2014
// This examples the ability of this library to support more than one MCP2515 based CAN interface.


#include <mcp_can.h>
#include <SPI.h>
#define setRollover(v) changeBits(RXB0CTRL, 1 << BUKT, v << BUKT); 
unsigned long rxId;
char msgString[128];
byte len;
byte rxBuf[8];
byte i;
byte ya[] = {0xFF,0xFF,0xFC,0x2C,0xA1,0x00,0x00,0x0F};
byte ya2[] = {0x05,0x58,0x01,0x1F,0xFF,0xFF,0xFF,0xFF};

//byte txBuf0[] = {AA,55,AA,55,AA,55,AA,55};
//byte txBuf1[] = {55,AA,55,AA,55,AA,55,AA};

MCP_CAN CAN0(10);                              // CAN0 interface usins CS on digital pin 10
MCP_CAN CAN1(9);                               // CAN1 interface using CS on digital pin 9

void setup()
{
  Serial.begin(115200);
    // init CAN0 bus, baudrate: 250k@16MHz
  if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK){
  Serial.print("CAN0: Init OK!\r\n");
  CAN0.setMode(MCP_ANY);
 
  } else Serial.print("CAN0: Init Fail!!!\r\n");



  
  // init CAN1 bus, baudrate: 250k@16MHz
  if(CAN1.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK){
  Serial.print("CAN1: Init OK!\r\n");
  CAN1.setMode(MCP_ANY);
  } else Serial.print("CAN1: Init Fail!!!\r\n");

}

void loop(){  
  if(!digitalRead(2)){                         // If pin 2 is low, read CAN0 receive buffer
    CAN0.readMsgBuf(&rxId,0, &len, rxBuf);       // Read data: len = data length, buf = data byte(s)
 
if(CAN0.checkError() == CAN_CTRLERROR){
    Serial.print("Error register value: ");
    byte tempErr = CAN0.getError() & MCP_EFLG_ERRORMASK; // We are only interested in errors, not warnings.
    Serial.println(tempErr, BIN);
   
    Serial.print("Transmit error counter register value: ");
    tempErr = CAN0.errorCountTX();
    Serial.println(tempErr, DEC);
   
    Serial.print("Receive error counter register value: ");
    tempErr = CAN0.errorCountRX();
    Serial.println(tempErr, DEC);
   
    //I do not have a function that clears errors and that has been added to my todo list. 04/26/17 CJF
 }
 

    CAN1.sendMsgBuf(rxId,0, len, rxBuf);      // Immediately send message out CAN1 interface


    
  }
  if(!digitalRead(3)){                         // If pin 3 is low, read CAN1 receive buffer
    CAN1.readMsgBuf(&rxId,0, &len, rxBuf);       // Read data: len = data length, buf = data byte(s)
//Serial.println(rxId,HEX);
  if(CAN1.checkError() == CAN_CTRLERROR){
    Serial.print("Error register value: ");
    byte tempErr = CAN1.getError() & MCP_EFLG_ERRORMASK; // We are only interested in errors, not warnings.
    Serial.println(tempErr, BIN);
   
    Serial.print("Transmit error counter register value: ");
    tempErr = CAN1.errorCountTX();
    Serial.println(tempErr, DEC);
   
    Serial.print("Receive error counter register value: ");
    tempErr = CAN1.errorCountRX();
    Serial.println(tempErr, DEC);
   
    //I do not have a function that clears errors and that has been added to my todo list. 04/26/17 CJF
 }
    CAN0.sendMsgBuf(rxId,0, len, rxBuf);      // Immediately send message out CAN0 interface
  }
}

/*********************************************************************************************************
  END FILE
*********************************************************************************************************/

i have two mcp2515 with 16Mhz quartz and arduino nano with atmega328p

How i can enable rollover? I need change BUKT bit, but i don’t know how.

This is my interpretation of the datasheet. I could be wrong, but the behaviour seems reasonable.

Your code doesn’t have any filters therefore both receive buffers, RXB0 and RXB1 can receive messages.

The first message goes into RXB0.
If RXB0 is full the next message goes into RXB1. Effectively the rollover from RXB0 to RXB1 is automatic.
If both buffers are full when another messages arrives then you get an overflow error.

This is probably what you are seeing as the Arduino/MCP2515 combination is too slow to process the number of messages arriving.

If you have filters set then the two receive buffers are independent and can only receive messages as per each bank of filters. BUKT allows messages to rollover from one buffer to the other.

So in your case I don’t think BUKT is going to make any difference. The Arduino/MCP2515 is just too slow for the amount of data arriving. A faster Arduino may help, but I think you may be out of luck with the MCP2515 as the two message receive buffer probably isn’t going to to give you a 100% working pass through solution. The hardware used in modern CAN bus analysers typically uses a 32bit microcontroller with onboard CAN controller (with 8 message buffer) that moves data using DMA rather than SPI.

Thanks for reply. What device i can buy for my work?

Teensy 3.5 boards are fast and have CAN controllers (but not transceivers). You might need to purchase 2 boards for a pass through arrangement.

Before you spend money on hardware I would recommend that you use an oscilloscope or logic analyser to measure the activity on the CAN bus. You need to get an idea of how many messages are arriving per second and how tightly they are clustered, in other words how big are the time gaps between the messages.

Once you have some numbers there are probably people on the Teensy forums that could help you choose a board.

Alternatively have a look on the car hacking forums to see what hardware they use for pass through CAN bus arrangements. They may not be Arduino based, but this probably doesn't matter in your case.