Send two can bus messages with retard

Hello, I'm am trying response a can bus message when I receive a specific msg, this part is fine, but I need these 4 messages will be sent (only 1 time) with specific times (or "delay"). ... I printed the current time for each message to see what happened and they are sent together...
i am using arduino uno with mpc2515 module and autowp mcp can library...

#include <SPI.h>
#include <mcp2515.h>

unsigned long last_msg_time = 0; // Variable para almacenar el tiempo del último mensaje
unsigned long last_msg_time1 = 0; // Variable para almacenar el tiempo del último mensaje
unsigned long last_msg_time2 = 0; // Variable para almacenar el tiempo del último mensaje
unsigned long last_msg_time3 = 0; // Variable para almacenar el tiempo del último mensaje
unsigned long last_msg_time4 = 0; // Variable para almacenar el tiempo del último mensaje
bool respuesta_enviada = false; // Variable para indicar si la respuesta ya se envió o no
struct can_frame canMsg;
struct can_frame canMsg1;
struct can_frame canMsg2;
struct can_frame canMsg3;
struct can_frame canMsg4;
struct can_frame canMsg5;
struct can_frame canMsg6;
struct can_frame canMsg7;
struct can_frame canMsg8;
struct can_frame canMsg9;
struct can_frame canMsg11;
MCP2515 mcp2515(10);


void setup() {
  canMsg1.can_id  = 0x83FFC2FE;
  canMsg1.can_dlc = 2;
  canMsg1.data[0] = 0x00;
  canMsg1.data[1] = 0x00;

  canMsg2.can_id  = 0x90082FD;
  canMsg2.can_dlc = 0;

  canMsg3.can_id  = 0x920083FF;
  canMsg3.can_dlc = 4;
  canMsg3.data[0] = 0x00;
  canMsg3.data[1] = 0x4F;
  canMsg3.data[2] = 0x04;
  canMsg2.data[3] = 0x00;
   
  canMsg4.can_id  = 0x940842EA;
  canMsg4.can_dlc = 2;
  canMsg4.data[0] = 0x48;
  canMsg4.data[1] = 0x02;
  
  canMsg5.can_id  = 0x920096EA;
  canMsg5.can_dlc = 8;
  canMsg5.data[0] = 0x00;
  canMsg5.data[1] = 0x00;
  canMsg5.data[2] = 0x27;
  canMsg5.data[3] = 0x06;
  canMsg5.data[4] = 0x02;
  canMsg5.data[5] = 0x40;
  canMsg5.data[6] = 0x00;
  canMsg5.data[7] = 0x00;
  
  canMsg6.can_id  = 0x920096EA;
  canMsg6.can_dlc = 8;
  canMsg6.data[0] = 0x01;
  canMsg6.data[1] = 0x10;
  canMsg6.data[2] = 0x00;
  canMsg6.data[3] = 0x00;
  canMsg6.data[4] = 0x32;
  canMsg6.data[5] = 0xC8;
  canMsg6.data[6] = 0x30;
  canMsg6.data[7] = 0x30;
  
  canMsg7.can_id  = 0x920096EA;
  canMsg7.can_dlc = 8;
  canMsg7.data[0] = 0x02;
  canMsg7.data[1] = 0x33;
  canMsg7.data[2] = 0x38;
  canMsg7.data[3] = 0x34;
  canMsg7.data[4] = 0x32;
  canMsg7.data[5] = 0x30;
  canMsg7.data[6] = 0x39;
  canMsg7.data[7] = 0x33;
   
  canMsg8.can_id  = 0x920096EA;
  canMsg8.can_dlc = 7;
  canMsg8.data[0] = 0x05;
  canMsg8.data[1] = 0xFF;
  canMsg8.data[2] = 0x45;
  canMsg8.data[3] = 0x01;
  canMsg8.data[4] = 0x00;
  canMsg8.data[5] = 0x00;
  canMsg8.data[6] = 0x27;
   
  canMsg9.can_id  = 0x920096EA;
  canMsg9.can_dlc = 8;
  canMsg9.data[0] = 0x04;
  canMsg9.data[1] = 0x4D;
  canMsg9.data[2] = 0x30;
  canMsg9.data[3] = 0x38;
  canMsg9.data[4] = 0x38;
  canMsg9.data[5] = 0x36;
  canMsg9.data[6] = 0x31;
  canMsg9.data[7] = 0x33;
    
  while (!Serial);
  Serial.begin(115200);
  
  mcp2515.reset();
  mcp2515.setBitrate(CAN_1000KBPS);
  mcp2515.setNormalMode();
  
  Serial.println("CONECTADA");
  mcp2515.sendMessage(&canMsg1);
  mcp2515.sendMessage(&canMsg2);
  Serial.println("Msj 1 y 2 setup enviado");
}

void loop() {
  unsigned long actual = millis();
  unsigned long current_time = millis(); // Obtener el tiempo actual
  if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK && canMsg.data[0] == 0x48 && canMsg.can_dlc>0 && !respuesta_enviada) {
      Serial.println(current_time);
    if (current_time - last_msg_time1 > 10){
      mcp2515.sendMessage(&canMsg5);
      last_msg_time1 = current_time;
      Serial.println("1:");
      Serial.println(current_time);
      }
    if (current_time - last_msg_time2 > 15){
      mcp2515.sendMessage(&canMsg6);
      last_msg_time2 = current_time;
      Serial.println("2:");
      Serial.println(current_time);
      }
    if (current_time - last_msg_time3 > 20){
      mcp2515.sendMessage(&canMsg7);
      mcp2515.sendMessage(&canMsg8);
      last_msg_time3 = current_time;
      Serial.println("3:");
      Serial.println(current_time);
      }
    if (current_time - last_msg_time4 > 25){
      mcp2515.sendMessage(&canMsg9);
      last_msg_time4 = current_time;
      Serial.println("4:");
      Serial.println(current_time);
      respuesta_enviada = true;
      }
    
    }
  else if (current_time - last_msg_time > 805){
      last_msg_time = current_time; // Actualizar el tiempo del último mensaje
      mcp2515.sendMessage(&canMsg3);
      Serial.println("Valor wb enviado  ");
      Serial.println(last_msg_time);
  }
}   

this is serial monitor and you can see how time is the same:

16:53:28.755 -> Valor wb enviado  
16:53:28.755 -> 8060
16:53:29.575 -> Valor wb enviado  
16:53:29.575 -> 8866
16:53:30.139 -> 9475
16:53:30.139 -> 1:
16:53:30.139 -> 9475
16:53:30.139 -> 2:
16:53:30.139 -> 9475
16:53:30.139 -> 3:
16:53:30.139 -> 9475
16:53:30.139 -> 4:
16:53:30.139 -> 9475
16:53:30.356 -> Valor wb enviado 

how can i resolve it? im nobie... thanks

Do not put code for sending messages into condition of the receive "trigger" message. in this case, the intervals cannot be maintained correctly.

When you receive "trigger" message, the only task that you should do - remember the millis value and set the sending flag.

Example: sending four messages with 10ms intervals between

    if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK && 
         canMsg.data[0] == 0x48 && canMsg.can_dlc>0 && ! respuesta_enviada) 
         { last_message_time = millis();
            respuesta_enviada = 1;
         }      

    if ((respuesta_enviada == 1) && (current_time - last_msg_time > 10))
      {
       
        /// sending 1st message

        last_message_time = millis();
        respuesta_enviada =2;
      }
     if ((respuesta_enviada == 2) && (current_time - last_msg_time > 10))
      {
       /// sending 2nd message

        last_message_time = millis();
        respuesta_enviada =3;
      }
    if ((respuesta_enviada == 3) && (current_time - last_msg_time > 10))
      {
       /// sending 3rd message

        last_message_time = millis();
        respuesta_enviada =4;
      }

     if ((respuesta_enviada == 4) && (current_time - last_msg_time > 10))
      {
       /// sending 4th message
     
       // reset message counter
        respuesta_enviada =0;
      }

Also, on a busy CAN bus there may be a interval of several milliseconds between when the message is queued in the MCP2515 and the time the message is successfully placed on the CAN bus.

The only way to prioritize your messages over other messages is by using low CAN ID values. Using high CAN IDs such as those shown in your example will likely result in random transmission delays.

Thank you, this works fine... I have a bigger problem, what I need is that when another device sends me a specific message Can I have to respond with 5 segmented messages to form the desired information among those 5... so far I managed to identify the message and Starting from that, answering the problem is that either it takes a long time to send or not all of them are sent. I don't know if this is a hardware problem. Has this happened to anyone? I am using the code that is in the first message

By definition on CAN only one message can be sent at a time. The messages are priority based. Depending on priority for the order of transmission if more then one message is to be sent. The arbitration takes place on the bus as they are being sent. Improper termination of the bus can cause similar problems. It needs to have a 120 ohm resistor at each physical end and nothing in between. If you are using CAT 5 or similar you may have to go to 100 ohm resistors. With everything off the bus should measure about 60/50 ohms depending on termination.

At 1Mbps your Arduino hardware needs to be fast enough to receive a message in less than a millisecond. A 16MHz Uno or Mega is too slow. Choose a faster more modern Arduino that has an operating voltage compatible with your MCP2515 module.

I do that all the time, you are assuming it is a steady stream of data. The MCP2515 has three transmit and two receive buffers , two acceptance masks (one for each receive buffer ) and a total of six acceptance filters. You do not have to run it at that baud rate, slower is no problem. In this case the baud was not specified. If you use the filters you only need to respond to messages for you and ignore all the rest. They have CAN running in Automotive with processors much slower then the Arduino.

With three transmit buffers it is possible for a train of 3 messages with the same Id to be placed on the bus in quick succession. You as the sketch programmer have no control over this behavior. With two receive buffers the last of those three messages will be lost unless your Arduino can quickly read a message thus freeing one of the two buffers before the third message arrives. Filters are no help in this situation.

In theory you alleviate this issue by modifying the library to use fewer than 3 transmit buffers, however this is not a task for a beginner.

I am working at a speed of 1 mbps, in the Can network I have few messages working... I attach a photo of how my program should work: when the "master" responds 48 02, I must respond quickly to those 5 messages in the time indicated in the capture that make up a set of segmented packets which identify me and allow me to start sending the data I need, otherwise I cannot identify my device and the master will not read my packet with the data.

Why don't you use the same approach as in post#2?

Looking at the code in post #1 you are using mcp2515.sendMessage without checking the return code, therefore you are assuming that it always works, but you don't know for sure.

Anything other than a zero indicates a problem of some kind.
From mcp2515.h

        enum ERROR {
            ERROR_OK        = 0,
            ERROR_FAIL      = 1,
            ERROR_ALLTXBUSY = 2,
            ERROR_FAILINIT  = 3,
            ERROR_FAILTX    = 4,
            ERROR_NOMSG     = 5
        };

How can I add check code?

In your example it's something like
MCP2515::ERROR result = mcp2515.sendMessage(...

If i try it doesnt work...

  else if (current_time - last_msg_time > 806){
      last_msg_time = current_time; 
      MCP2515::ERROR_OK = mcp2515.sendMessage(&canMsg3);
      Serial.println("Data msg sent ");
      Serial.println(last_msg_time);
  }
}

this is the error:

 error: lvalue required as left operand of assignment
       MCP2515::ERROR_OK = mcp2515.sendMessage(&canMsg3);
                                                       ^

exit status 1

Compilation error: lvalue required as left operand of assignment

I wrote
MCP2515::ERROR result =
You wrote
MCP2515::ERROR_OK =

"result" is the variable that holds the value you need to check.

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