CanBus Error detection

Hi,

I've got a question about buffer overloads with canbus using the Sparkfun MCP2515_CAN module, with library GitHub - Seeed-Studio/Seeed_Arduino_CAN: Seeed Arduino CAN-BUS library - MCP2518FD&MCP2515&MCP2551

I would like to use the CAN protocol, I readed that it's very stable and has a good error handling. But is the buffer overload handled?

For the test, I setted up 2 arduino's, one is sending data to the other.
My question is: How can i be sure if the data is received right?

For the test i'm sending a message with a frequence of 100ms, and read it out at the other side with 300ms. the receiver has a buffer of 2 messages, so i expected a error would occur at the sending site, that the message is'nt delivered well, because the buffer is full. But this doesn't happen.

When the receiver is checked with CAN.checkError(), the error num 5 is received (i expect this is buffer full)

Is the only way to check the receive status, to send a OK signal back to the sender?
this would increase the amount of data sended over the bus.

Can anyone help me with this question?

Thanks!

code of the Receiver

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


// 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 = 53;

MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin

void setup()
{
    Serial.begin(115200);

    while (CAN_OK != CAN.begin(CAN_500KBPS))              // init can bus : baudrate = 500k
  {
        Serial.println("CAN BUS Shield init fail");
        Serial.println(" Init CAN BUS Shield again");
        delay(100);
  }
    Serial.println("CAN BUS Shield init ok!");
}


void loop()
{
    unsigned char len = 0;
    unsigned char buf[8];
  delay(300);
   if (CAN.checkError()) {
    Serial.println(CAN.checkError());
   }
    if (CAN_MSGAVAIL == CAN.checkReceive())            // check if data coming
    {
        CAN.readMsgBuf(&len, buf);    // read data,  len: data length, buf: data buf

        unsigned int canId = CAN.getCanId();
        
        Serial.println("-----------------------------");
        Serial.print("Get data from ID: ");
        Serial.println(canId, HEX);

        for(int i = 0; i<len; i++)    // print the data
        {
            Serial.print(buf[i], HEX);
            Serial.print("\t");
        }
        Serial.println();
    }
}

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

code of the master

// demo: CAN-BUS Shield, send data
#include <mcp_can.h>
#include <SPI.h>

// 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 = 10;

MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin

void setup()
{
    Serial.begin(115200);

    while (CAN_OK != CAN.begin(CAN_500KBPS))              // init can bus : baudrate = 500k
    {
        Serial.println("CAN BUS Shield init fail");
        Serial.println(" Init CAN BUS Shield again");
        delay(100);
    }
    Serial.println("CAN BUS Shield init ok!");
}

unsigned char stmp[8] = {0, 1, 2, 3, 4, 5, 6, 7};
void loop()
{
    // send data:  id = 0x00, standrad frame, data len = 8, stmp: data buf
    Serial.println(CAN.checkError());
    Serial.println( CAN.sendMsgBuf(0x02, 1, 8, stmp));
    delay(100);                       // send data per 100ms
}

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

You can have a look at what is done in the sendMsg() call. what does your print tell you? (returns either CAN_OK, CAN_GETTXBFTIMEOUT or CAN_SENDMSGTIMEOUT)

byte MCP_CAN::sendMsg()
{
    byte res, res1, txbuf_n;
    uint16_t uiTimeOut = 0;

    do {
        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
    }
    uiTimeOut = 0;
    mcp2515_write_canMsg( txbuf_n);
    mcp2515_start_transmit( txbuf_n );
    do
    {
        uiTimeOut++;
        res1= mcp2515_readRegister(txbuf_n-1 /* the ctrl reg is located at 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;

}

Hi,

If i'm reading the piece of library you sended, it looks you're right, but when i was testing it,

it seems the canbus can receive and overwrite existing data with new data in the buffer before the data is readed out from of the buffer, so the data can dissapear without the sender and receiver don't know it.

in some documentation i've readed that the receiver also can send a signal to the sender that it has to slow down.. i thought that signal should be send to the sender, so I receive an error on the sender side, that the buffer is full. but i receive a zero (CAN_OK).

The part that i don't understand is:

Can the data be overwritten in the chip's buffer before it's readed out, or must it first be readed out, before new data can be stored in the receive buffer?

I guess it depends on mcp2515_getNextFreeTXBuf() finding an available emission buffer. I'm not an expert there but buffer I think it depends also on the client to acknowledge or not it's OK to keep sending stuff