CAN.sendMsgBuf flooding the CAN bus with one message

Hello! I am hoping someone can help out with this. I am using a SeedCAN shield on an Arduino Uno and need to send 4 CAN messages. One of them, BCM_R_G needs to change byte 2 based on switch input. I am not a code expert so everything I write is best described as "caveman code". but here it is

#include <SPI.h>

#define CAN_2515
// #define CAN_2518FD

// Set SPI CS Pin according to your hardware

#if defined(SEEED_WIO_TERMINAL) && defined(CAN_2518FD)
// For Wio Terminal w/ MCP2518FD RPi Hat:
// Channel 0 SPI_CS Pin: BCM 8
// Channel 1 SPI_CS Pin: BCM 7
// Interupt Pin: BCM25
const int SPI_CS_PIN  = BCM8;
const int CAN_INT_PIN = BCM25;
#else

// For Arduino MCP2515 Hat:
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
const int CAN_INT_PIN = 2;
#endif


#ifdef CAN_2518FD
#include "mcp2518fd_can.h"
mcp2518fd CAN(SPI_CS_PIN); // Set CS pin
#endif

#ifdef CAN_2515
#include "mcp2515_can.h"
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
#endif


const int PowerPin = 3 ; // Power switch to wake up SCM (High Active)
const int VentLow = 4 ;// Vent Medium mode Pin (High Active)
const int VentHigh = 5 ;// Vent High Pin (High Active)
const int BackHeatMed =6 ;// Cushin Heat Medium Pin (High Active) 
const int BackHeatHigh =7 ;// Cushin Heat High Pin (High Active)
const int SeatHeatMed = 8 ;// Seat Heat Medium Pin (High Active)
const int SeatHeatHigh = 0 ;// Seat Heat High Pin (High Active)
const int OnInd = 1 ;// Seat Heat High Pin (High Active)

int mode_2 = 0x00; // initialize mode Byte 2 data


void setup() {
    SERIAL_PORT_MONITOR.begin(115200);
    while(!Serial){};

    while (CAN_OK != CAN.begin(CAN_500KBPS)) {             // init can bus : baudrate = 500k
        SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
        delay(100);
    }
    SERIAL_PORT_MONITOR.println("CAN init ok!");

  pinMode(PowerPin, INPUT_PULLUP);
  pinMode(VentLow, INPUT_PULLUP);
  pinMode(VentHigh, INPUT_PULLUP);
  pinMode(BackHeatMed, INPUT_PULLUP);
  pinMode(BackHeatHigh, INPUT_PULLUP);
  pinMode(SeatHeatMed, INPUT_PULLUP);
  pinMode(SeatHeatHigh, INPUT_PULLUP);
  pinMode(OnInd, OUTPUT);

  

  unsigned char alwayson1[8] = {0, 0, 0, 0, 0, 0, 0, 0};       


  unsigned char alwayson2[8] = {0, 0, 0, 0, 0, 0, 0, 0};
    

  unsigned char alwayson3[8] = {0, 0, 0, 0, 0, 0, 0, 0};
      
 
  unsigned char mode[8] = {0, 0, 0, 0, 0, 0, 0, 0};
      
}


void loop() {
  //Vent Mode Select
if (digitalRead(VentLow)==HIGH && digitalRead(VentHigh)== HIGH)
  mode_2 = 0x00;
  
else if (digitalRead(VentLow)==LOW && digitalRead(VentHigh)==HIGH)
   mode_2 = 0x04;
  
else if (digitalRead(VentLow)==HIGH && digitalRead(VentHigh)== LOW)
   mode_2 = 0x0C;

else 
  mode_2 = 0x00;
 

// Cushin and Back Heat Mode Select
if (digitalRead(digitalRead(VentLow)==HIGH && digitalRead(VentHigh)== HIGH))
{ 
  if (digitalRead(BackHeatMed)==LOW && digitalRead(BackHeatHigh)==HIGH && digitalRead(SeatHeatMed) == HIGH && digitalRead(SeatHeatHigh)==HIGH)  
    mode_2 = 0x80;  
    
  else if (digitalRead(BackHeatMed)==HIGH && digitalRead(BackHeatHigh)==LOW && digitalRead(SeatHeatMed) == HIGH && digitalRead(SeatHeatHigh)==HIGH)
     mode_2 = 0xC0;
     
  else if (digitalRead(BackHeatMed)==HIGH && digitalRead(BackHeatHigh)==HIGH && digitalRead(SeatHeatMed) == LOW && digitalRead(SeatHeatHigh)==HIGH)
     mode_2 = 0x20;
     
  else if (digitalRead(BackHeatMed)==HIGH && digitalRead(BackHeatHigh)==HIGH && digitalRead(SeatHeatMed) == HIGH && digitalRead(SeatHeatHigh)==LOW)
     mode_2 = 0x30;
     
  else if (digitalRead(BackHeatMed)==LOW && digitalRead(BackHeatHigh)==HIGH && digitalRead(SeatHeatMed) == LOW && digitalRead(SeatHeatHigh)==HIGH)
    mode_2 = 0xA0;

  else if (digitalRead(BackHeatMed)==LOW && digitalRead(BackHeatHigh)==HIGH && digitalRead(SeatHeatMed) == HIGH && digitalRead(SeatHeatHigh)==LOW)
     mode_2 = 0xB0;
 
  else if (digitalRead(BackHeatMed)==HIGH && digitalRead(BackHeatHigh)==LOW && digitalRead(SeatHeatMed) == LOW && digitalRead(SeatHeatHigh)==HIGH)
     mode_2 = 0xE0;
  else if (digitalRead(BackHeatMed)==HIGH && digitalRead(BackHeatHigh)==LOW && digitalRead(SeatHeatMed) == HIGH && digitalRead(SeatHeatHigh)==LOW)
     mode_2 = 0xF0;
  }
if (digitalRead(PowerPin)==LOW)
    {
      digitalWrite(1, HIGH);
      unsigned char mode[8] = {0, 0, mode_2, 0, 0, 0, 0, 0};
      unsigned char alwayson1[8] = {0, 0, 0, 0, 0, 0, 0, 0};
      unsigned char alwayson2[8] = {0, 0, 0, 0, 0, 0, 0, 0};
      unsigned char alwayson3[8] = {0, 0, 0, 0, 0, 0, 0, 0};      

     CAN.sendMsgBuf(0x408,0,8,mode); 
     CAN.sendMsgBuf(0x409,0,8,alwayson1);
     CAN.sendMsgBuf(0x400,0,8,alwayson2);
     CAN.sendMsgBuf(0x600,0,8,alwayson3);     
    }
else 
  digitalWrite(1, LOW);


    delay(100);

}

When I try to send the CAN messages, I notice only one is going through and the CAN bus load is way too hi, at 90%. So the bus seems flooded with the one message. I also cant stop the message from sending. I would like each CAN message to be sent once per loop. Even adding a delay in there doesnt seem to help. I suspect something is just causing the one message to keep going forever but I am not sure.
Any ideas? I have never used the CAN bus shield before but I used a mcp2515 CAN board before and didnt have this issue. So I am at a bit of a loss

A quick look at your code indicates it will just keep sending which you describe is happening. Post a schematic showing how all of this is wired. It is possible you have errors on the PHI (Physical Interface) possibly improper termination. Part of the CAN protocol is if a message is not acknowledge in frame it will send it again until it counts out. I believe when that happens you start over. Also you must have an active receiver when sending a CAN message, it does not matter if the receiver is being accessed or not, by protocol it must acknowledge any valid message.

Hello! I have proper termination ( 2, 120 ohm ressistors totally 60 ohms in the bus). The arduino is wired to one module and that is basically the syatem. All of the can bus wires are twisted pairs so interference should be good.

I am wondering about the acknowledge though. I havent seen a can message be sent over and over again until it got an acknowledgement but i also havent worked with this shield before either.
Would you happen to know if there is a way to ignore the ack? I know there is with vector tools but not exactly sure how to code that in with this.

No problem ignoring the ACK (Acknowledge), it simply will not operate. In Frame tells us the acknowledge comes in the frame that is being sent. The transmitter sends a recessive bit at ACK time and anybody on the bus that determines the message asserts a dominate bit at ACK time.

The easiest way to get started is to use two units, one for send the second for receive. I use the Cory Fowler library at: GitHub - coryjfowler/MCP_CAN_lib: MCP_CAN Library it has both a send and receive sections of code. I will take a SWAG and say it will work with your hardware as they are using the MCP2515 and the driver is not relevant to the controller as most drivers will work.

So twist in the story! I actually have a setup that works using different hardware. the setup that works uses a CAN board at the link here:

and using this code:

#include <SPI.h> //Library for using SPI Communication
#include <mcp2515.h> //Library for using CAN Communication


struct can_frame alwayson1;
struct can_frame alwayson2;
struct can_frame alwayson3;
struct can_frame mode;
MCP2515 mcp2515(10);

const int PowerPin = 3 ; // Power switch to wake up SCM (High Active)
const int VentLow = 4 ;// Vent Medium mode Pin (High Active)
const int VentHigh = 5 ;// Vent High Pin (High Active)
const int BackHeatMed =6 ;// Cushin Heat Medium Pin (High Active) 
const int BackHeatHigh =7 ;// Cushin Heat High Pin (High Active)
const int SeatHeatMed = 8 ;// Seat Heat Medium Pin (High Active)
const int SeatHeatHigh = 0 ;// Seat Heat High Pin (High Active)
const int OnInd = 1 ;// Seat Heat High Pin (High Active)


void setup(){

  pinMode(PowerPin, INPUT_PULLUP);
  pinMode(VentLow, INPUT_PULLUP);
  pinMode(VentHigh, INPUT_PULLUP);
  pinMode(BackHeatMed, INPUT_PULLUP);
  pinMode(BackHeatHigh, INPUT_PULLUP);
  pinMode(SeatHeatMed, INPUT_PULLUP);
  pinMode(SeatHeatHigh, INPUT_PULLUP);
  pinMode(OnInd, OUTPUT);

  while (!Serial);
  Serial.begin(9600);
  SPI.begin(); //Begins SPI communication
   mcp2515.reset();
  mcp2515.setBitrate(CAN_500KBPS, MCP_8MHZ); //Sets CAN at speed 500KBPS and Clock 8MHz
  mcp2515.setNormalMode();

  alwayson1.can_id = 0x400; //CAN id as 0x400
    alwayson1.can_dlc = 8; //CAN data length as 8
    alwayson1.data[0] = 0x00; 
    alwayson1.data[1] = 0x00; 
    alwayson1.data[2] = 0x00;
    alwayson1.data[3] = 0x00;
    alwayson1.data[4] = 0x00;
    alwayson1.data[5] = 0x00;
    alwayson1.data[6] = 0x00;
    alwayson1.data[7] = 0x00;    
      

  alwayson2.can_id = 0x600; //CAN id as 0x600
    alwayson2.can_dlc = 8; //CAN data length as 8
    alwayson2.data[0] = 0x00; 
    alwayson2.data[1] = 0x00; 
    alwayson2.data[2] = 0x00;
    alwayson2.data[3] = 0x00;
    alwayson2.data[4] = 0x00;
    alwayson2.data[5] = 0x00;
    alwayson2.data[6] = 0x00;
    alwayson2.data[7] = 0x00;

      alwayson3.can_id = 0x409; //CAN id as 0x400
      alwayson3.can_dlc = 7; //CAN data length as 8
      alwayson3.data[0] = 0x00; 
      alwayson3.data[1] = 0x00; 
      alwayson3.data[2] = 0x80;
      alwayson3.data[3] = 0x00;
      alwayson3.data[4] = 0x00;
      alwayson3.data[5] = 0x00;
      alwayson3.data[6] = 0x00;

      mode.can_id = 0x408; //CAN id as 0x400
      mode.can_dlc = 8; //CAN data length as 8
      mode.data[0] = 0x00; 
      mode.data[1] = 0x00; 
      mode.data[2] = 0x00;
      mode.data[3] = 0x00;
      mode.data[4] = 0x00;
      mode.data[5] = 0x00;
      mode.data[6] = 0x00;
      mode.data[7] = 0x00;

}

void loop()
{
  //Vent Mode Select
if (digitalRead(VentLow)==HIGH && digitalRead(VentHigh)== HIGH)
  mode.data[2] = 0x00 ;
else if (digitalRead(VentLow)==LOW && digitalRead(VentHigh)==HIGH)
  mode.data[2] = 0x04 ;
else if (digitalRead(VentLow)==HIGH && digitalRead(VentHigh)== LOW)
  mode.data[2] = 0x0C ;
else 
 mode.data[2] = 0x00 ;

// Cushin and Back Heat Mode Select
if (digitalRead(digitalRead(VentLow)==HIGH && digitalRead(VentHigh)== HIGH))
{ 
  if (digitalRead(BackHeatMed)==LOW && digitalRead(BackHeatHigh)==HIGH && digitalRead(SeatHeatMed) == HIGH && digitalRead(SeatHeatHigh)==HIGH)  
     mode.data[2] = 0x80;
  else if (digitalRead(BackHeatMed)==HIGH && digitalRead(BackHeatHigh)==LOW && digitalRead(SeatHeatMed) == HIGH && digitalRead(SeatHeatHigh)==HIGH)
     mode.data[2] = 0xC0;
  else if (digitalRead(BackHeatMed)==HIGH && digitalRead(BackHeatHigh)==HIGH && digitalRead(SeatHeatMed) == LOW && digitalRead(SeatHeatHigh)==HIGH)
     mode.data[2] = 0x20;
  else if (digitalRead(BackHeatMed)==HIGH && digitalRead(BackHeatHigh)==HIGH && digitalRead(SeatHeatMed) == HIGH && digitalRead(SeatHeatHigh)==LOW)
     mode.data[2] = 0x30;
  else if (digitalRead(BackHeatMed)==LOW && digitalRead(BackHeatHigh)==HIGH && digitalRead(SeatHeatMed) == LOW && digitalRead(SeatHeatHigh)==HIGH)
     mode.data[2] = 0xA0;
  else if (digitalRead(BackHeatMed)==LOW && digitalRead(BackHeatHigh)==HIGH && digitalRead(SeatHeatMed) == HIGH && digitalRead(SeatHeatHigh)==LOW)
     mode.data[2] = 0xB0;
  else if (digitalRead(BackHeatMed)==HIGH && digitalRead(BackHeatHigh)==LOW && digitalRead(SeatHeatMed) == LOW && digitalRead(SeatHeatHigh)==HIGH)
     mode.data[2] = 0xE0;
  else if (digitalRead(BackHeatMed)==HIGH && digitalRead(BackHeatHigh)==LOW && digitalRead(SeatHeatMed) == HIGH && digitalRead(SeatHeatHigh)==LOW)
     mode.data[2] = 0xF0;
}
if (digitalRead(PowerPin)==LOW)
    {
      digitalWrite(1, HIGH);
      mcp2515.sendMessage(&mode); //Sends the CAN message
      mcp2515.sendMessage(&alwayson1); //Sends the CAN message
      mcp2515.sendMessage(&alwayson2); //Sends the CAN message
      mcp2515.sendMessage(&alwayson3); //Sends the CAN message
    }
 else 
  {digitalWrite(1, LOW);
  }
    delay(100);
}


Using a Vector CAN case as the receiver, everything works perfectly. The bus is running around 2% load at max and all the messages are sent.

However, taking the same setup with the CANcase to this new setup, we get the flooding the bus issue with one message that wont stop sending. That is what is making me wonder if the ack is really the issue. If it was, I would think I would see this on the working setup. Unless some libraries done care about ack and other do? I did try to run the working code with this new setup too. It didnt like a few things.

Just for reference, I had to change the HW since this new setup mounts way better.

Would you happen to know where would be a good place to check and see if the ack is handled differently between these two?

sorry to bumbard... I think I might have found it, it is now getting it to work. Going through the library, I found a simple send message command shown here:

/*********************************************************************************************************
** Function name:           sendMsg
** Descriptions:            send message
*********************************************************************************************************/
byte mcp2515_can::sendMsg(unsigned long id, byte ext, byte rtrBit, byte len, const byte* buf, bool wait_sent) {
    byte res, res1, txbuf_n;
    uint16_t uiTimeOut = 0;

    can_id = id;
    ext_flg = ext;
    rtr = rtrBit;

    do {
        if (uiTimeOut > 0) {
            delayMicroseconds(10);
        }
        res = mcp2515_getNextFreeTXBuf(&txbuf_n);                       // info = addr.
        uiTimeOut++;
    } while (res == MCP_ALLTXBUSY && (uiTimeOut < TIMEOUTVALUE));

    if (uiTimeOut == TIMEOUTVALUE) {
        return CAN_GETTXBFTIMEOUT;                                      // get tx buff time out
    }
    mcp2515_write_canMsg(txbuf_n, id, ext, rtrBit, len, buf);

    if (wait_sent) {
        uiTimeOut = 0;
        do {
            if (uiTimeOut > 0) {
                delayMicroseconds(10);
            }
            uiTimeOut++;
            res1 = mcp2515_readRegister(txbuf_n - 1);  // read send buff ctrl reg
            res1 = res1 & 0x08;
        } while (res1 && (uiTimeOut < TIMEOUTVALUE));

        if (uiTimeOut == TIMEOUTVALUE) {                                     // send msg timeout
            return CAN_SENDMSGTIMEOUT;
        }
    }

    return CAN_OK;

}

The one I am using now is sending the message to the transmit buffer. Not entirely sure what that means unless it is putting the message in line of priority. Anyway, I tried putting that in the code shown here:

  sendMsg(0x409, 0, 8,mode);

However, I get the following error:

C:\Users\ejdeml\AppData\Local\Temp\.arduinoIDE-unsaved202394-29812-1djoq8l.uuvq\CAN_send\CAN_send.ino: In function 'void loop()':
C:\Users\ejdeml\AppData\Local\Temp\.arduinoIDE-unsaved202394-29812-1djoq8l.uuvq\CAN_send\CAN_send.ino:102:4: error: 'sendMsg' was not declared in this scope
    sendMsg(0x409, 0, 8,BCM_R_H);
    ^~~~~~~
Multiple libraries were found for "mcp_can.h"
  Used: C:\Users\ejdeml\OneDrive - Rivian Automotive, LLC\Documents\Arduino\libraries\mcp_can
  Not used: C:\Users\ejdeml\OneDrive - Rivian Automotive, LLC\Documents\Arduino\libraries\CAN_BUS_Shield
  Not used: C:\Users\ejdeml\OneDrive - Rivian Automotive, LLC\Documents\Arduino\libraries\Seeed_Arduino_CAN-master
exit status 1

Compilation error: 'sendMsg' was not declared in this scope

I also tried as MCP_2515::sendMsg but it is not finding it in the library. I am sure I am missing something simple.... Any idea what it is?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.