How to read ACK bit?

mati

New member
Hello,

I am new either to can bus and c++, therefore forgive me for asking silly questions, but I am stucked on this issue for 3 weeks now, and I can't find the solution.
I have two teensy boards that have to communicate with each other: one sends messages and the other reads them.
The receiver prints a sort of error message "no data on the bus", everytime read.msg() returns false.
Since the sender transmits signal faster, I expect that there is always a message to read, but instead every now and then I get the message error.
For this reason, I tried to check the bit ACK to verify the reception.
I searched a lot on the internet and finally I found the possibility to check errors using the CAN_error_t message and the function error(). I wrote them in the sender code but at this point I faced another problem.
Even if the receiver is not powered, no error is printed (except at the beginning). I disconnected also one extremity of the can bus, but still no error.
Can someone tell me what I am doing wrong? I expect to see an ACK error without powering the receiver, and some errors like bus off for improper termination of the can bus.


The wirings should be fine, both the teensy boards are equipped with a transciever, and the can bus is terminated with 120 ohm resistor at each end. I think it is a softwer problem, but still can't understand such behavior.

Here below the two codes for the sender and receiver

SENDER:

Code:
FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> myCan;
CAN_error_t Can_err;

void setup() {
  Serial.begin(9600);
  while(!Serial);
  myCan.begin();
  myCan.setBaudRate(1000000);
  Serial.println("initialized");
}

void loop() {
  // sender
  CAN_message_t msg;
  msg.id=0x001;
  msg.flags.extended=0;
  msg.len=5;
  Serial.print("message ID: 0x");
  Serial.println(msg.id);
  msg.buf[0]='h';
  msg.buf[1]='e';
  msg.buf[2]='l';
  msg.buf[3]='l';
  msg.buf[4]='o';
  myCan.write(msg);
  myCan.error(Can_err,true);
  delay(1000);
}

RECEIVER:

Code:
FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> can1;
CAN_message_t msg;

void setup() {
  Serial.begin(9600);
  while (!Serial);
  can1.begin();
  can1.setBaudRate(1000000);
  Serial.println("FlexCan_T4 initialized for rec");
  can1.enableFIFO();
  can1.mailboxStatus();
}

void loop() {
    if (can1.read(msg)){
        Serial.print("ID: 0x");Serial.print(msg.id, HEX);
        Serial.print("|");
        Serial.print("buffer: ");
        for (int i=0; i<msg.len; i++){
        Serial.print(char (msg.buf[i]));}
        Serial.println(" ");
    }
    else
    Serial.println("No data on the bus");
    delay(2000);
}
 
First, please post complete code so we can compile the sketch. The #include <FlexCAN_T4.h> is missing.

The sender is working fine.
The receiver needs a can1.events()
Change your code to this:

Code:
void loop() {
  can1.events();
    if (can1.read(msg)){
        Serial.print("ID: 0x");Serial.print(msg.id, HEX);
        Serial.print("|");
        Serial.print("buffer: ");
        for (int i=0; i<msg.len; i++){
        Serial.print(char (msg.buf[i]));}
        Serial.println(" ");
    }
    else
    Serial.println("No data on the bus");
    delay(2000);
}
 
Hi skpang,

Thank you so much for your reply, events() was the solution and now the code works fine. However, I had to remove delay(2000) from loop( ) otherwise the messages were not read in the right order.

I upload here the correct version of the previous code.

Sender:

Code:
#include <Arduino.h>
#include<FlexCAN_T4.h>


FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> myCan;
CAN_error_t Can_err;
u_int32_t count=0;

void setup() {
  Serial.begin(9600);
  while(!Serial);
  myCan.begin();
  myCan.setBaudRate(1000000);
  myCan.enableFIFO();
  Serial.println("initialized");
}
void loop() {
  CAN_message_t msg;
  for(int ID=0; ID<0x005; ID++){
  msg.id=ID;
  msg.flags.extended=0;
  msg.len=4;
  Serial.print(" message ID: 0x");
  Serial.println(msg.id);
 
  msg.buf[0]=(count>>24) & 0xFF;
  msg.buf[1]=(count>>16) & 0xFF ;
  msg.buf[2]=(count>>8) & 0xFF;
  msg.buf[3]=count & 0xFF;
  myCan.write(msg);
  myCan.error(Can_err,true);
  count++;
  delay(1000);}
}


Receiver:

Code:
#include <Arduino.h>
#include<FlexCAN_T4.h>
FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> can1;
CAN_message_t msg;
CAN_error_t err_msg;

void setup() {
  Serial.begin(9600);
  while (!Serial);
  can1.begin();
  can1.setBaudRate(1000000);
  Serial.println("FlexCan_T4 initialized for rec");
  can1.enableFIFO();
  can1.mailboxStatus();
}
void loop() {
  can1.events();
    if (can1.read(msg)){
        Serial.print("ID: 0x");Serial.print(msg.id, HEX);
        Serial.print("|");
        Serial.print("buffer: ");
        uint32_t count=0;
        for (int i=0; i<msg.len; i++){
          count|=msg.buf[i]<<((3-i)*8);
        }
        Serial.println(count);
    }
}

May I ask you a clarification on events( )? When should I use it? I thought events( ) was only needed when interrupts were enabled. However, it seems that now events() should always be used to properly receive messages and reduce the risk that some of them might be lost.
 
Back
Top