due_can library

I need some help on a project I am working on. I am using the arduino due with the due_can library. The can bus I am trying to communicate on has a baud rate of 83.333k. There is no 83.333k option in the due_can library. So I added the line "#define CAN_BPS_83K 83333" to the due_can.h file.

I then recompile and run the sketch and the can port shows that it is initializing. But I still am not getting any communication from the arduino. When I power the system on I see frames on the network from other ECU's I am testing but they go to sleep when no frames from my controller are sent.

I am able to test other ECU's that are on a 125Kbps using the same setup. The settings that I need to achieve on the 83.333Kbps network are 83.333 kBaud, prescaler 6, BTL-cycles 16 and sample point 81%. Is this possible with only adding the baud rate to the header file. I am a noobie to programming so I am not able to figure out exactly how the due_can library is selecting the bit timing in the .cpp file.

Any help to point me in the right direction on this would be greatly appreciated.

There isn’t really any need to add a define for your baud rate if you don’t want to. The begin function takes the baud rate anyway so you can pass any baud rate you want in there. Some bauds won’t work well because they don’t divide cleanly into the system core clock rate but 83.333k should be close enough that it works fine.

Are you saying that everything works fine at 125k baud but when you switch to 83.333k baud you can see traffic but not send? I have to admit, I’ve never tried 83.333k baud but I have tried 33.333k baud and even that worked. It’s odd to be able to read but not send on the bus but I suppose it could be because of bit timing differences as you said. Sometimes a difference in how the various phases are laid out can cause trouble. This is all done automatically for you by the library but look at this code from due_can.h

typedef struct {
	uint8_t uc_tq;      //! CAN_BIT_SYNC + uc_prog + uc_phase1 + uc_phase2 = uc_tq, 8 <= uc_tq <= 25.
	uint8_t uc_prog;    //! Propagation segment, (3-bits + 1), 1~8;
	uint8_t uc_phase1;  //! Phase segment 1, (3-bits + 1), 1~8;
	uint8_t uc_phase2;  //! Phase segment 2, (3-bits + 1), 1~8, CAN_BIT_IPT <= uc_phase2;
	uint8_t uc_sjw;     //! Resynchronization jump width, (2-bits + 1), min(uc_phase1, 4);
	uint8_t uc_sp;      //! Sample point value, 0~100 in percent.
} can_bit_timing_t;


/** Values of bit time register for different baudrates, Sample point = ((1 + uc_prog + uc_phase1) / uc_tq) * 100%. */
const can_bit_timing_t can_bit_time[] = {
	{8,   (2 + 1), (1 + 1), (1 + 1), (2 + 1), 75},
	{9,   (1 + 1), (2 + 1), (2 + 1), (1 + 1), 67},
	{10,  (2 + 1), (2 + 1), (2 + 1), (2 + 1), 70},
	{11,  (3 + 1), (2 + 1), (2 + 1), (3 + 1), 72},
	{12,  (2 + 1), (3 + 1), (3 + 1), (3 + 1), 67},
	{13,  (3 + 1), (3 + 1), (3 + 1), (3 + 1), 77},
	{14,  (3 + 1), (3 + 1), (4 + 1), (3 + 1), 64},
	{15,  (3 + 1), (4 + 1), (4 + 1), (3 + 1), 67},
	{16,  (4 + 1), (4 + 1), (4 + 1), (3 + 1), 69},
	{17,  (5 + 1), (4 + 1), (4 + 1), (3 + 1), 71},
	{18,  (4 + 1), (5 + 1), (5 + 1), (3 + 1), 67},
	{19,  (5 + 1), (5 + 1), (5 + 1), (3 + 1), 68},
	{20,  (6 + 1), (5 + 1), (5 + 1), (3 + 1), 70},
	{21,  (7 + 1), (5 + 1), (5 + 1), (3 + 1), 71},
	{22,  (6 + 1), (6 + 1), (6 + 1), (3 + 1), 68},
	{23,  (7 + 1), (7 + 1), (6 + 1), (3 + 1), 70},
	{24,  (6 + 1), (7 + 1), (7 + 1), (3 + 1), 67},
	{25,  (7 + 1), (7 + 1), (7 + 1), (3 + 1), 68}
};

You can see how this code creates a table to be used to automatically grab values to use for each of the bit timing parameters. You’ll also see that none of them use 81% as the sample point.

If you really need different parameters you could edit the above table to make it happen. But, it won’t be that terribly easy to make edits and not make things worse. The above table came right from Atmel and presumably they calculated them this way for a reason. Scary roads lie ahead if you edit this table but you might have to do it. Unfortunately canbus can be a real pain sometimes. When it works, it works nicely. When it doesn’t you end up with an oscilloscope and a fifth of your favorite liquor.

Collin,

Thanks for the reply. I am already on my 3rd 5th of scotch. I have taken scope traces and can't figure it out. BTW I am not reading the can messages with my set-up I have Vector Can tools that I tied into the network for troubleshooting purposes. I am testing a radio and amplifier that operate on CAN BUS to be specific about my project. I can see the initial wake up messages from both of those ECU's on the bus when the system is first powered using Vector Canoe SW. After their initial wakeup they go to sleep waiting for instruction from the master node (my setup). I also see error frames in Canoe which I am guessing is coming from my setup. I have seen a few different types ( various bit stuffing errors, no ack errors, etc.) That is why I was thinking it may be a bit timing issue. Also you are correct using the same setup at 125K everything works peachy. The only difference is I am controlling the 125K out of CAN0 and the 83.333k out of CAN2. I have in my sketch that when INIT for each port returns 1 that it shows init succeeded on serial. So when I run the sketch it shows that both ports initialized properly. Is there anything that could cause no messages to be sent out of CAN2 even though initialization succeeded? I am thinking that the CAN Controller will shut down CAN if it sees to many error frames but I dont know if this is what is going on or not.

Here is my code if it helps in any way… The actual messages are removed for legal reasons.

#include <due_can.h>

#include <due_can.h>
#include <DueTimer.h>
#include <SPI.h>

const int radPresPIN = 2;
const int cipPIN = 5;
const int fcipPIN = 3;
const int ntg4PIN = 4;
int fcipFlag = 0;
int cipFlag = 1;
int ntg4Flag = 0;
int radPresFlag = 1;
int d = 0;
int oneT = 0;   //100ms timer
int twoT = 0;  //200ms timer
int threeT = 0;  //500ms timer
int fourT = 0;  //1000ms timer
int fiveT = 0;  //2000ms timer




// CREATE ALL THE CAN MESSAGES TO BE SENT ON THE BUS
CAN_FRAME CBC_I3, CBC_I4, EcuCfg3, Stw_Actn_Req, GW_C_I2, CBC_I2, VehCfg1, NET_CFG_INT, VIN_1, VIN_2, VIN_3, GW_C1, AMP_CTRL, TGW_STAT_I, TGW_PWR_MAST, TGW_MSG, TGW_CFG_11,fc_AMP_CTRL, fc_AMP_INFO_CTRL, fc_CBC_I4, fc_STATUS_BCM2, fc_TGW_CFG_11, fc_TGW_MSG, fc_TGW_PWR_MAST, fc_TGW_STAT, fc_TRIP_A_B, fc_Vehicle_Speed_Odometer, fc_VIN_1, fc_VIN_2, fc_VIN_3,fc_NWM_BCM,nls_VEH_CFG2, nls_VEH_CFG1, nls_RADIO_STAT1, nls_Radio_MSG1, nls_Radio_MSG, nls_Net_CFG, nls_BCM_A7, nls_AMP_CTRL, nls_IC_A1, nls_VIN_A1, nls_VIN_A2, nls_VIN_A3, nls_NM_FCM, nhs_BCM_A7, nhs_VIN_A1_1, nhs_VIN_A1_2, nhs_VIN_A1_3, nhs_Veh_Cfg1, nhs_Net_Cfg2, A286I_1, A2CEI_1, A211I_1, A208I_1, A217I_1, A244I_1, A2DDI_1, A248I_1, A2D3I_1, A2DEI_1, A306I_1, A2DBI_1, A25FI_1, nhs_AMP_CTRL, nhs_RADIO_STAT1, nhs_RADIO_MSG;


 // LINK TO FUNCTIONS TO BE CALLED FROM TIMER INTERRUPTS
void Two00MS() { Two00MS_Send();}
void One00MS() { One00MS_Send();}
void Two000MS() { Two000MS_Send();}
void One000MS() { One000MS_Send();}
void Five00MS() { Five00MS_Send();}

code continued...

// FUNCTIONS for sending messages seperated by cyclic rate
// 100ms cyclic rate
void One00MS_Send() {
oneT = 1;
}  

// 200ms cyclic rate
void Two00MS_Send(){
twoT = 1; 
}

// 500ms cyclic rate
void Five00MS_Send() {
threeT = 1;
}
// 1000ms cyclic rate
void One000MS_Send(){
fourT = 1;
}

// 2000ms cyclic rate
void Two000MS_Send(){
fiveT = 1;
}

void setup(){
  /* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
***********************************************************CIP******************************************************************************
**********************CREATE MESSAGES TO SEND ON THE BUS WITH POPULATED DATA, DLC, and ID**********************************************************************************************/


 // start // Serial 
Serial.begin(115200);  
// set CAN BUS bit rate to 125kb per second
if(CAN.init(CAN_BPS_125K) == 1) {
  Serial.print("CAN0 Initialized Successfully.\n\r");
}
else{ Serial.print("CAN0 Initialization Failed.\n\r");
}

if(CAN2.init(CAN_BPS_83K) == 1) {
  Serial.print("CAN2 Initialized Successfully.\n\r");
}
else{ Serial.print("CAN2 Initialization Failed.\n\r");
}

// Define switch pins as input
pinMode(radPresPIN,INPUT_PULLUP);
 pinMode(cipPIN,INPUT_PULLUP);
 pinMode(fcipPIN,INPUT_PULLUP);
 pinMode(ntg4PIN,INPUT_PULLUP);
 

// Timer interrupts for the different cyclic rates
Timer3.attachInterrupt(Two00MS);
Timer3.start(200000); // Calls every 200ms
Timer4.attachInterrupt (One00MS); //Calls every 100ms
Timer4.start(100000);
Timer5.attachInterrupt (Two000MS);
Timer5.start(2000000);
Timer6.attachInterrupt (One000MS);
Timer6.start(1000000);
Timer7.attachInterrupt (Five00MS);
Timer7.start(500000);
        }

void loop(){
   Serial.print("CIP FLAG:  ");
Serial.println(cipFlag);
Serial.print("FCIP FLAG:  ");
Serial.println(fcipFlag);
Serial.print("NTG4 FLAG:  ");
 Serial.println(ntg4Flag);
Serial.print("Radio Present Flag:  ");
Serial.println(radPresFlag);
Serial.print("Time 1=  ");
Serial.println(oneT);
Serial.print("Time 2=  ");
Serial.println(twoT);
Serial.print("Time 3=  ");
Serial.println(threeT);
Serial.print("Time 4=  ");
 Serial.println(fourT);
Serial.print("Time 5=  ");
Serial.println(fiveT);
 chkSw(); 
 chkRadSw();
 oneTChk();
 twoTChk();
 threeTChk();
 fourTChk();
 fiveTChk();

}

void chkSw(){
 if (digitalRead(cipPIN) == LOW){
    cipFlag = 1;
    fcipFlag = 0;
    ntg4Flag = 0;
  }
  else if (digitalRead(fcipPIN) == LOW){
    cipFlag = 0;
    fcipFlag = 1;
    ntg4Flag = 0;
  }
  else if (digitalRead(ntg4PIN) == LOW){
    cipFlag = 0;
    fcipFlag = 0;
    ntg4Flag = 1;
  }
  
}

void chkRadSw(){
  if (digitalRead(radPresPIN) == LOW){
    if(radPresFlag == 0){
    radPresFlag = 1;
    }
    else if (radPresFlag == 1){
      radPresFlag = 0;
    }
  }
}


void oneTChk(){
if(oneT == 1){
  if(cipFlag == 1 && radPresFlag == 0){
     Can0.sendFrame(CBC_I4);
  Can0.sendFrame(Stw_Actn_Req);
  if (d == 0){
  Can0.sendFrame(VIN_1);
  d = 1;
  }
  else if (d == 1){
  Can0.sendFrame(VIN_2);
  d = 2;
  }
  else if(d == 2){
  Can0.sendFrame(VIN_3);
  d = 0;
  }
  Can0.sendFrame(GW_C1);
  Can0.sendFrame(TGW_PWR_MAST);
  oneT = 0;
  // Serial.println("100 Sent");
  }
  else if(cipFlag == 1 && radPresFlag == 1){
  Can0.sendFrame(CBC_I4);
  Can0.sendFrame(Stw_Actn_Req);
   Can0.sendFrame(GW_C1);
 if (d == 0){
  Can0.sendFrame(VIN_1);
  d = 1;
  }
  else if (d == 1){
  Can0.sendFrame(VIN_2);
  d = 2;
  }
  else if(d == 2){
  Can0.sendFrame(VIN_3);
  d = 0;
    }
   oneT = 0;
    Serial.println("100 Sent");
  }
  
  else if(fcipFlag == 1 && radPresFlag == 0){
  Can0.sendFrame(fc_CBC_I4);
 Can0.sendFrame(fc_TGW_PWR_MAST);
  Can0.sendFrame(fc_Vehicle_Speed_Odometer);
  if(d == 0){
  Can0.sendFrame(fc_VIN_1);
  d = 1;
  }
 else if(d == 1){
  Can0.sendFrame(fc_VIN_2);
 d = 2;
 }
 else if (d == 2){
  Can0.sendFrame(fc_VIN_3);  
  d = 0;
     }
   oneT = 0;
    Serial.println("100 Sent");
  }
  
  else if(fcipFlag == 1 && radPresFlag == 1)
  Can0.sendFrame(fc_CBC_I4);
  Can0.sendFrame(fc_Vehicle_Speed_Odometer);
   if(d == 0){
  Can0.sendFrame(fc_VIN_1);
  d = 1;
  }
 else if(d == 1){
  Can0.sendFrame(fc_VIN_2);
 d = 2;
 }
 else if (d == 2){
  Can0.sendFrame(fc_VIN_3);  
  d = 0;
     }
  oneT = 0; 
  Serial.println("100 Sent");
  }
  
  else if(ntg4Flag == 1 && radPresFlag == 0){
  Can1.sendFrame(nls_BCM_A7);
  Can1.sendFrame(nls_NM_FCM);
  Can1.sendFrame(nls_IC_A1);
  Serial.println("100 LS Signal Sent");
  Can0.sendFrame(nhs_BCM_A7);
  if(d == 0){
  Can0.sendFrame(nhs_VIN_A1_1);
  Can1.sendFrame(nls_VIN_A1);
  d = 1;
  }
  else if(d == 1){
 Can0.sendFrame(nhs_VIN_A1_2);
 Can1.sendFrame(nls_VIN_A2);
 d = 2;
  }
 else if(d = 2){
 Can1.sendFrame(nls_VIN_A3); 
 Can0.sendFrame(nhs_VIN_A1_3);
 d = 0;
          }
  oneT = 0;
   Serial.println("100 Sent");
  }
 
 else if(ntg4Flag == 1 && radPresFlag == 1){
 Can0.sendFrame(nhs_BCM_A7);  
 Can1.sendFrame(nls_BCM_A7);
 Can1.sendFrame(nls_NM_FCM);
 Can1.sendFrame(nls_IC_A1);
 Serial.println("100 -2 Can LS sent");
 if(d == 0){
  Can0.sendFrame(nhs_VIN_A1_1);
  Can1.sendFrame(nls_VIN_A1);
  d = 1;
  }
  else if(d == 1){
 Can0.sendFrame(nhs_VIN_A1_2);
 Can1.sendFrame(nls_VIN_A2);
 d = 2;
  }
 else if(d = 2){
 Can1.sendFrame(nls_VIN_A3); 
 Can0.sendFrame(nhs_VIN_A1_3);
 d = 0;
          }
  oneT = 0;
  Serial.println("100 Sent");
  } 
else{}
}

void twoTChk(){
  if(twoT == 1){
    if(cipFlag == 1){
    Can0.sendFrame(CBC_I3);
    twoT = 0;
    Serial.println("200 Sent");
    }
    else if(fcipFlag == 1){
    Can0.sendFrame(fc_STATUS_BCM2);
    twoT = 0;
    Serial.println("200 Sent");
    } 
  }
   else{}
  }
  
void threeTChk(){
if (threeT == 1 && cipFlag == 1){
 Can0.sendFrame(CBC_I2);
 threeT = 0;
 Serial.println("500 Sent");
}
else{}
}


void fourTChk(){
  if(fourT == 1){
    if(cipFlag == 1 && radPresFlag == 0){
    Can0.sendFrame(GW_C_I2);
    Can0.sendFrame(AMP_CTRL);
    Can0.sendFrame(TGW_STAT_I);
    Can0.sendFrame(TGW_CFG_11);
    Can0.sendFrame(TGW_MSG);    
    fourT = 0;
    Serial.println("1000 Sent");
    }
    else if(cipFlag == 1 && radPresFlag == 1){
    Can0.sendFrame(GW_C_I2); 
    fourT = 0;
   Serial.println("1000 Sent");
    }
    else if(fcipFlag == 1 && radPresFlag == 0){
    Can0.sendFrame(fc_AMP_CTRL);
    Can0.sendFrame(fc_AMP_INFO_CTRL);
    Can0.sendFrame(fc_TGW_CFG_11);
    Can0.sendFrame(fc_TGW_MSG);
    Can0.sendFrame(fc_TGW_STAT);
    Can0.sendFrame(fc_TRIP_A_B);
    Can0.sendFrame(fc_NWM_BCM);
    fourT = 0;
    Serial.println("1000 Sent");
    }
    else if(fcipFlag == 1 && radPresFlag == 1){
    Can0.sendFrame(fc_TRIP_A_B);
    Can0.sendFrame(fc_NWM_BCM);
    fourT = 0;
    Serial.println("1000 Sent");
    }
    else if(ntg4Flag == 1 && radPresFlag == 0){
    Can1.sendFrame(nls_RADIO_STAT1);
    Can1.sendFrame(nls_Radio_MSG1);
    Can1.sendFrame(nls_Radio_MSG);
    Can1.sendFrame(nls_AMP_CTRL);
    Serial.println("300 LS Sent");
    Can0.sendFrame(nhs_AMP_CTRL);
    Can0.sendFrame(nhs_RADIO_STAT1);
    Can0.sendFrame(nhs_RADIO_MSG);
    fourT = 0;
    Serial.println("1000 Sent");
    }
  }
  else{}
}

void fiveTChk(){
if (fiveT == 1){
  if(cipFlag == 1){
  Can0.sendFrame(EcuCfg3);
  Can0.sendFrame(VehCfg1); 
  Can0.sendFrame(NET_CFG_INT);
  fiveT = 0;
  Serial.println("2000 Sent");
  }
  else if(ntg4Flag == 1){
  Can1.sendFrame(nls_VEH_CFG2);
  Can1.sendFrame(nls_VEH_CFG1);
  Can1.sendFrame(nls_Net_CFG);
  Serial.println("500 Can LS Sent");
  Can0.sendFrame(nhs_Veh_Cfg1);
  Can0.sendFrame(nhs_Net_Cfg2);
  fiveT = 0;
   Serial.println("2000 Sent");
  }
  else{}
     }
}

Any input on this would be greatly appreciated. I am new to programming with no formal training so I am sure my code is poorly written with many deviations from standard practice. So I am also open to any suggestions to improve the code also. I know there are many brilliant minds on this forum so I am hoping someone can help me out with this. Thanks in advance for your input.