CAN FD Arduino Shield Issue

Hello,

I am using the CAN-FD shield with Arduino. I am sending the messages via but I am seeing CAN errors on the bus via Canape. I added the following line of code to the “mcp2518fd_can_dfs.h” header file because my application uses a 1M data rate and 1M arbitration rate. I am sending frames less than 8 bytes. The messages are being transmitted and read fine by my CAN tool but CANape is reporting message errors.

static const uint32_t CAN_1000K_1M = ( 1UL << 24) |(1000000UL);

Is there some issue with adding the line above?

Not sure where I could be going wrong. Any assistance would be appreciated.

Thanks,
Matt

Also, it appears CAN-FD frames are not being sent (only CAN 2.0) despite presumably configuring for CAN-FD. Below is a snip of my code.

#include <mcp2518fd_can.h>
#include <mcp2518fd_can_dfs.h>
#include <mcp_can_fd.h>

#include <TimerInterrupt.h>
#include <TimerInterrupt.hpp>
#include <ISR_Timer.h>
#include <ISR_Timer.hpp>

#include <SPI.h>

#define MAX_DATA_SIZE 64

// Full Scale Pressure Range from Dyno
const float FullScalePressure = 231.46;

// pins for CAN-FD Shield
const int SPI_CS_PIN = 9;
const int CAN_INT_PIN = 2;

mcp2518fd CAN(SPI_CS_PIN); // Set CS pin

//Variable Definitions
unsigned int VoltageCounts = 0;
float Voltage = 0;
float Pressure = 0; 
unsigned int Pressure16bitScaled = 0;
unsigned int Pressure16bitScaled2 = 0;
uint8_t PressureLowByte = 0;
uint8_t PressureHighByte = 0;
bool KL15 = 0;
bool IgnStat = 0;
uint8_t IgnStatValue = 1;
bool PushButton = 0;
unsigned int VoltageOffset = 0;
unsigned int VoltageCountsZeroed = 0;
unsigned int PreChargeSwitch = 0;
float PreChargeVoltage = 0;
uint8_t PKBSwitchState = 0;
uint8_t PKBApplyReleaseRequest = 5;
bool ApplyReleaseFlag = 0;
uint32_t TimeStamp = 0;
unsigned char flagRecv = 0;
unsigned char len = 0;
unsigned char buf[MAX_DATA_SIZE];

/*
    can-fd baud rate:

    CAN_125K_500K
    CAN_250K_500K
    CAN_250K_750K
    CAN_250K_1M
    CAN_250K_1M5
    CAN_250K_2M
    CAN_250K_3M
    CAN_250K_4M
    CAN_500K_1M
    CAN_500K_2M
    CAN_500K_3M
    CAN_500K_4M
    CAN_1000K_4M
    CAN_1000K_1M
    CAN20_250KBPS
*/


void setup() {
  Serial.begin(115200);
  //while(!Serial){};
  
  //CAN.setMode(CAN_NORMAL_MODE);

  while (CAN_OK != CAN.begin(CAN_1000K_1M)) {             // init can bus : baudrate = 1000K_1M
  Serial.println("CAN init fail, retry...");
  delay(100);
    }
    
Serial.println("CAN init ok!");

//Setup Interrupts
//attachInterrupt(digitalPinToInterrupt(18), ApplyRelease, CHANGE);

pinMode(22, INPUT_PULLUP);
pinMode(23, INPUT_PULLUP);
pinMode(24, INPUT_PULLUP);
}

void loop() {
  
  // Read KL15 input switch, if TRUE then enter while loop below.  
  KL15 = digitalRead(22);

  if (KL15 == 0){
    VoltageOffset = analogRead(A0);
  }

  while(KL15 == 0){

    // Read Pressure Transmitter Voltage and Zero
    VoltageCounts = analogRead(A0);
    VoltageCountsZeroed = VoltageCounts - VoltageOffset;

    // Calculate PreChargeSwitch Voltage
    PreChargeSwitch = analogRead(A1);
    PreChargeVoltage = PreChargeSwitch*5.0/1023;

    //Check if Zeroed Voltage Count is OOR (negative) and set to 0 if negative.  This prevents the voltage counts from wrapping around.
    if (VoltageCountsZeroed > 1024) {
      VoltageCountsZeroed = 0;
    }

    // Calculate Voltage and Pressure from Zeroed Voltage Counts Value
    Voltage = VoltageCountsZeroed*5.0/1023;
    Pressure = (Voltage)*FullScalePressure/5;
  
    //Precharge determination logic, if Pressure >  bar then set 16 bit pressure output to analog pressure input
    if (Pressure > 5){
      Pressure16bitScaled = Pressure*51200/200;
    }
    // If precharge switch is activated then set pressure output to 4 bar
    else if (PreChargeVoltage > 4.5){
      Pressure16bitScaled = 1024; //Corresponds to 4 bar pressure
    }
    // Otherwise set pressure output to 0
    else {
      Pressure16bitScaled = 0;
    }

    /* This causes PKBApplyReleaseRequest to set to 27.  
    if ((ApplyReleaseFlag == 1) && ((millis() - TimeStamp) < 200)){
      PKBApplyReleaseRequest = 27;
  }
    else{
      PKBApplyReleaseRequest = 5;
    }

    // This causes PKBApplyReleaseRequest to set to 40.  Once 200 ms elapses the request set to 5.   
    if ((ApplyReleaseFlag == 0) && ((millis() - TimeStamp) < 200)){
      PKBApplyReleaseRequest = 40;
    }
    else{
      PKBApplyReleaseRequest = 5;

    }*/

    //Split 16 bit value into lower and upper bytes to be sent over CAN.  
    PressureLowByte = (byte) (Pressure16bitScaled & 0x00FF);
    PressureHighByte = (byte) ((Pressure16bitScaled & 0xFF00) >> 8);
    
    //Read IGN Status signal
    IgnStat = digitalRead(23);

    //Setting eBooster_CMD
    uint8_t eBooster_CMD[7] = {PressureLowByte, PressureHighByte,5,5,5,5,5};

    //Setting eBooster_Veh_Pwr
    if(IgnStat == 0){
    IgnStatValue = 4; //sets IgnCmdStat to RUN
    }
    else{
    IgnStatValue = 1; //sets IgnCmdStat to OFF
    }
    uint8_t eBooster_Veh_Pwr[2] = {IgnStatValue, 120};

    uint8_t eBooster_Veh_Data[2] = {0, 0};

    uint8_t eBooster_1[2] = {0, 0};

    uint8_t eBooster_2[1] = {0};

    uint8_t eBooster_3[8] = {0, 0, 0, 0, 0, 0, 0, 0};

    uint8_t eBooster_4[2] = {0, 0};

  
  //Sending eBooster_CMD
  CAN.sendMsgBuf(0x07, 0, 7, eBooster_CMD); // send a standard frame to id 0x07
    
  //Sending eBooster_Veh_Pwr
  CAN.sendMsgBuf(0x112, 0, 2, eBooster_Veh_Pwr); // send a standard frame to id 0x112

  //Sending eBooster_Veh_Data
  CAN.sendMsgBuf(0x113, 0, 2, eBooster_Veh_Data);

  //Sending eBooster_1
  CAN.sendMsgBuf(0x14B, 0, 2, eBooster_1);

  //Sending eBooster_2
  CAN.sendMsgBuf(0x14C, 0, 2, eBooster_2);

  //Sending eBooster_3
  CAN.sendMsgBuf(0x158, 0, 2, eBooster_3);

  //Sending eBooster_4
  CAN.sendMsgBuf(0x11C, 0, 2, eBooster_4);

if (CAN_MSGAVAIL == CAN.checkReceive()) {
        CAN.readMsgBuf(&len, buf);            // You should call readMsgBuff before getCanId
        unsigned long id = CAN.getCanId();
        
        Serial.print("Get Data From id: ");
        Serial.println(id);
        Serial.print("Len = ");
        Serial.println(len);
            // print the data
        for (int i = 0; i < len; i++) {
            Serial.print(buf[i]); 
            Serial.print("\t");
        }
        Serial.println();
    }

  delay(1); // send data once every 1 ms

  //Read KL15 at end of while loop
  KL15 = digitalRead(22);

  Serial.println("IgnStat");
  Serial.println(IgnStat);
  Serial.println("IgnStatValue");
  Serial.println(IgnStatValue);

  }
 }

/*
//ApplyRelease request ISR
void ApplyRelease ()
{
  ApplyReleaseFlag = !ApplyReleaseFlag;
  TimeStamp = millis();
}
*/


// END FILE

Hi there, Is this a seed shield? Which Arduino?

can you show a picture of this setup?
Have you tried adding a longer Delay

to longer and see if it’s data or settling time on the buss.
slow it down and try that. at 1 meg for both the arduino may be sketchy.
HTH
GL :slight_smile: PJ
:v:

#define CAN_1000KBPS 18
fyi,  Implements CAN V2.0B at up to 1 Mb/s
CAN BUS Shield Work well with Arduino UNO (ATmega328), Arduino Mega (ATmega1280/2560)
as well as Arduino Leonardo (ATmega32U4).

Hi PJ! Thank you for your reply. It is indeed the Seeed shield purchased from the Seeed website.

I have tried adding a drastically longer delay (10, 100, and 1000 ms) an had no luck. The errors still appear on the bus.

I am using the mega 2560 Arduino.

I do see the CAN frames being transmitted but I don’t think they are CAN-FD frames. My debugger shows only regular CAN frames.

Also, I cannot receive any CAN-FD frames either. only regular CAN frames are received.

This indicates to me the controller is not configured correctly for CAN-FD.

Hi there,
I would concur, Try a different LIB.
Your mega Should be plenty.what are the buss resistors and any diagram how you have it connected.
GL :slight_smile: PJ
:v:

You’ll get it, keep looking. I’ll look at alternative LIB’s :+1:

Thanks PJ. I have two 120 ohm resistors, one at the ECU and one at the Arduino. I don’t suspect it is a hardware configuration issue.

I don’t have a diagram handy but I think hardware wise it is ok. Can you recommend another library for the arduino can fd shield?

Hi there,
Ok I would tend to agree if your getting the Standard Can messages Hardware is OK, try the older LIB, I see it is compatible.
Should be a doable task, not like your doing left field stuff. Hmm.
HTH
GL :slight_smile: PJ
:v:

Can you send a link to the library you are referring to? The one on github?

this is the library I am using.

Look over here, more are mentioned.
HTH
GL :slight_smile: PJ
:v:

ok, I will give it a try. thanks!

1 Like

It is not clear to me how to specify the can id to send or receive and how to read the actual data.

All I see are examples of how to confirm messages have been sent or received but not how to actually specify the message being sent.

Can someone provide more details on how to use pierremolarino’s library above?