Arduino CAN BUS Bridge and MITM

I am using a DUE with CAN BUS transceivers to essentially perform a “MITM attack” to retrofit some new parts into my older truck.

While the majority of the messages for this system match between the newer and older model, the chassis code is different and causes errors. I have the due set up to look for the frame that contains the chassis code, modifying it, then send it on to the new sensor.

Overall that works nicely except it seems like buffer is over run at times. 98% of the time everything works perfectly but it seems to drop frames for a short times and the sets off an error light for a split second.

The code is heavily (90+%) based off of collin80’s due_can examples. My snippet is below.

Does anyone have any ideas on how to make this a bit more efficient or a way to try to limit what I assume are buffer over run issues? For reference, the sensors are looking for 8-10 messages IDs if I were to set up some sort of filter. I have 8 identified but there may be one or two more.

//Reads all traffic on CAN0 and forwards it to CAN1 (and in the reverse direction) but modifies some frames first.
// Required libraries
#include "variant.h"
#include <due_can.h>

//Leave defined if you use native port, comment if using programming port
//#define Serial SerialUSB

void setup()
{

  Serial.begin(115200);
  
  // Initialize CAN0 and CAN1, Set the proper baud rates here
  Can0.begin(CAN_BPS_125K);
  Can1.begin(CAN_BPS_125K);
  
  //By default there are 7 mailboxes for each device that are RX boxes
  //This sets each mailbox to have an open filter that will accept extended
  //or standard frames
  int filter;
  //extended filter
  /*
  for (filter = 0; filter < 3; filter++) {
  Can0.setRXFilter(filter, 0, 0, true);
  Can1.setRXFilter(filter, 0, 0, true);
  }  */
  //standard
  for (int filter = 3; filter < 7; filter++) {
  Can0.setRXFilter(filter, 0, 0, false);
  Can1.setRXFilter(filter, 0, 0, false);
  }  
  
}

void printFrame(CAN_FRAME &frame) {
   Serial.print("ID: 0x");
   Serial.print(frame.id, HEX);
   Serial.print(" Len: ");
   Serial.print(frame.length);
   Serial.print(" Data: 0x");
   for (int count = 0; count < frame.length; count++) {
       Serial.print(frame.data.bytes[count], HEX);
       Serial.print(" ");
   }
   Serial.print("\r\n");
}

//data coming into CAN0 is forwarded to CAN1 unless ID = 3E8 and array[1] then 1D becomes 22
//3E8#3d 1d a2 7b ff 1b 8d 14
//ID  0  1  2  3  4  5  6  7 
//All data coming in on CAN1 is forwarded to CAN0

void loop(){
  CAN_FRAME frame;

  if (Can0.available() > 0) {//read Can0 and then send on Can1
    Can0.read(frame);
    if (frame.id == 1000 && frame.data.bytes[1] == 29) {
      frame.data.bytes[1] = 34; // 0x22 is 34
    }
    Can1.sendFrame(frame);
    //printFrame(frame);  //uncomment line to print frames that are going out
  }
  
  if (Can1.available() > 0) {//read Can1 and then send on Can0
    Can1.read(frame);
    Can0.sendFrame(frame);
    //printFrame(frame);  //uncomment line to print frames that are going out
  }
}

Some thoughts:

1/ Did you wired your transceivers as shown in figure 4 or 5 of this .pdf with the correct 120 Ohm resistors ?

2/ If you Serial print between reception and emission (although print.frame() function is commented), you may have a timing issue. Select the maximum baud rate (250000).

3/ To speed up the loop(), insert all code (except CAN_FRAME frame;) inside lopp(), inside a while(true) {....}

1/ The transceivers are wired correctly. I am using a dual can transceiver breakout board.

2/ Does it matter if I just turn off the serial init altogether if I am not using serial output? I commented out the serial init items completely and I am getting maybe a few percent fewer dropouts.

3/ I moved the "CAN_FRAME" outside of the "void loop." Can you elaborate on using the while(true) instead of the if statement?

//Reads all traffic on CAN0 and forwards it to CAN1 (and in the reverse direction) but modifies some frames first.
// Required libraries
#include "variant.h"
#include <due_can.h>

//Leave defined if you use native port, comment if using programming port
//#define Serial SerialUSB

void setup()
{

  Serial.begin(115200);

  // Initialize CAN0 and CAN1, Set the proper baud rates here
  Can0.begin(CAN_BPS_125K);
  Can1.begin(CAN_BPS_125K);

  //By default there are 7 mailboxes for each device that are RX boxes
  //This sets each mailbox to have an open filter that will accept extended
  //or standard frames
  int filter;
  //extended filter
  /*
    for (filter = 0; filter < 3; filter++) {
    Can0.setRXFilter(filter, 0, 0, true);
    Can1.setRXFilter(filter, 0, 0, true);
    }  */
  //standard
  for (int filter = 3; filter < 7; filter++) {
    Can0.setRXFilter(filter, 0, 0, false);
    Can1.setRXFilter(filter, 0, 0, false);
  }

}

void printFrame(CAN_FRAME &frame) {
  Serial.print("ID: 0x");
  Serial.print(frame.id, HEX);
  Serial.print(" Len: ");
  Serial.print(frame.length);
  Serial.print(" Data: 0x");
  for (int count = 0; count < frame.length; count++) {
    Serial.print(frame.data.bytes[count], HEX);
    Serial.print(" ");
  }
  Serial.print("\r\n");
}

//data coming into CAN0 is forwarded to CAN1 unless ID = 3E8 and array[1] then 1D becomes 22
//3E8#3d 1d a2 7b ff 1b 8d 14
//ID  0  1  2  3  4  5  6  7
//All data coming in on CAN1 is forwarded to CAN0

void loop() {
  CAN_FRAME frame;

  while (true)
  {
    if (Can0.available() > 0) {//read Can0 and then send on Can1
      Can0.read(frame);
      if (frame.id == 1000 && frame.data.bytes[1] == 29) {
        frame.data.bytes[1] = 34; // 0x22 is 34
      }
      Can1.sendFrame(frame);
      //printFrame(frame);  //uncomment line to print frames that are going out
    }

    if (Can1.available() > 0) {//read Can1 and then send on Can0
      Can1.read(frame);
      Can0.sendFrame(frame);
      //printFrame(frame);  //uncomment line to print frames that are going out
    }
  }
}