Can write stops after 3 messages

Hi All,

I am trying to write continuous can bus messages onto a bus (the same message to start out with and get familiar). But with my current code there are only 3 messages being sent before it stops (the if statement isn’t met, the code keeps running as it starts printing “failed to send msg”). Hopefully this is just a simple fix by me misunderstanding re-printing can bus messages. This is my code:

int main()
{
    while (1) 
    {
            CANMessage msg;
    msg.id = 1333;
    msg.len = 8;
    msg.data[0]=0x1F;
    msg.data[1]=0x1F;
    msg.data[2]=0x1F;
    msg.data[3]=0x1F;
    msg.data[4]=0x1F;
    msg.data[5]=0x1F;
    msg.data[6]=0x1F;
    msg.data[7]=0x1F;

        if (can.write(msg)) {
            printf("Send: %d %d %d %d %d %d %d %d\n", msg.data[0],msg.data[1],msg.data[2],msg.data[3],msg.data[4],msg.data[5],msg.data[6],msg.data[7]);
            // ThisThread::sleep_for(500ms);
        
        }
        else{
            printf("failed to send msg\n");
        }
    }

}

Hopefully any of you can help.

Kind regards,
Ties

1 Like

Hello,

if I remember that usually happen when the CAN tranciever is connected to nowhere.

BR, Jan

Hi Jan,

The can bus is definitely connected to something, as the code below does in fact run forever and perfectly fine.

int main()
{
    // printf("CAN Nucleo-F767ZI\n");
    printf("CAN Nucleo-F446RE\n");

    CAN can(PB_8, PB_9,500000);  
    CAN can2(PB_5, PB_13,500000);  
    DigitalOut led1(LED1);    
    CANMessage msg;
    if(can.filter(0x03FE,0x03FF,CANStandard)){
        printf("Can 1 Filter applied\n");
    }
    if(can2.filter(0x03FF,0x03FF,CANStandard)){
        printf("Can 2 Filter applied\n");
    }
    char counter = 0;
    char counter2 = 0;
    // trigger first read of opposite board
    if (can.write(CANMessage(0x03FE, &counter, 1)));
    // if (can2.write(CANMessage(1333, &counter, 1))) counter++;
    while (1) 
    {
        if (can.read(msg)) {
            printf("Received CAN 1: %d\n", msg.data[0]);
            ThisThread::sleep_for(500ms);
            if (can.write(CANMessage(0x03FE, &counter2, 1))) counter2++;
            led1 = !led1;
        }
                if (can2.read(msg)) {
            printf("Received CAN 2: %d\n", msg.data[0]);
            ThisThread::sleep_for(500ms);
            if (can2.write(CANMessage(0x03FF, &counter, 1))) counter++;
            led1 = !led1;
        }
    }
}

It works with both the 2 on board can bus pins on my nucleo as 2 separate boards. This is why I’m confused as the only thing that changed is the fact that instead of writing messages in response to something in the code; it just needs to send messages repeatedly.

KR,
Ties

I am not sure me explanation will be 100% correct but I will try and we will see.

In background the CAN::write method put data to CAN-Tx buffer and set a flag for CAN controller what say “data are ready for transmit”. CAN controller will proceed that request and CAN::write in this moment probably returns successful Write operation.
However how are bits transmitted to CAN-BUS it can happen a collision caused by an arbitration or just simply there is no device on other side that can pull last bit as ACK of successfully delivered message. Then CAN controller will try to send the same last message again and probably again without successful. At the same time you try to fill another new messages to CAN-Tx buffer but CAN controller is not able to successfully transmit any message and buffer is not empty, then your new message is probably scraped and CAN::write returns false for every another try of CAN::write call.

CAN API contains methods for read an error state for both lines (Txd/Rxd), so you can try to add them to your code. From my experiences it is not necessary to use it when CAN-BUS is stable.

printf("Error Rx %d - tx %d\n", can.rderror(),can.tderror());
  • When the number is zero then everything is ok.
  • When the number is increasing, then there exist and persist an issue.
  • When the number is decreasing, then there was a collision but not persist no issue
  • When the number is 255 then will be necessary perform CAN::reset()

BR, Jan

1 Like