Synchronizing different messages

巧了我就是萌 提交于 2019-12-25 17:48:24

问题


I think it's a general software paradigm problem, so it's not related that much to embedded software.

I have 3 Messages that I get at different time slices, the three messages are Odo, velocity, gps. each one has timeslice 20ms, 1sec, and 1sec.

My problem is how would I sync and get a complete message only when the three are already fetched.

My current approach is to have three circural queues, and put three boolean variables and check if they are all in sync, but that doesn't work if for example odo which has timeslice 20ms, is pulled over and over without the other messages.

Here is what I'm doing:

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{

  HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &RxMessage, RxData);
  static bool t1 = 0, t2=0, t3 =0;

  if (RxMessage.StdId == 0x098)
  {
    insertCirQueue(&q_velocity, 0x098);
    HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);
    t1=1;
  }
  else if (RxMessage.StdId == 0x309)
  {
    /* Rx message Error */
    insertCirQueue(&q_Odo, 0x309);
    t2=1;
    HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_13);
  }
  else if (RxMessage.StdId == 0x3EB)
  {
    /* Rx message Error */
    insertCirQueue(&q_Gps, 0x3EB);
    t3=1;
    HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_14);
  }

  if (t1 && t2 && t3)
  {
    t2 = t3 = t1 = 0;
    isSynced = true;
  }
}

and in the main loop

 if (isSynced)
      {
        isSynced = false;

        int vel[8] = {0}, gps[8] = {0}, odo[8] = {0};
        int counter = 0;
        while (!isEmpty(&q_velocity))
        {
          if (deleteCirQueue(&q_velocity, &vel[counter++]) == -1)
              break;
        }

        counter = 0;
        while (!isEmpty(&q_Gps))
        {
          if(deleteCirQueue(&q_Gps, &gps[counter++]) == -1)
              break;
        }

        counter = 0;
        while (!isEmpty(&q_Odo))
        {

          if(deleteCirQueue(&q_Odo, &odo[counter++]) == -1)
             break;
        }

回答1:


You create a bit-field, and set a bit per received message type.

typedef enum
{
  RECEIVED_NONE = 0x00,
  RECEIVED_ODO  = 0x01,
  RECEIVED_VELO = 0x02,
  RECEIVED_GPS  = 0x04,
  RECEIVED_ALL  = RECEIVED_ODO | RECEIVED_VELO | RECEIVED_GPS,
} can_received_t;



can_received_t can_received = RECEIVED_NONE;

if(/* received odo */)
{
  can_received |= RECEIVED_ODO;
}

...

if(can_received == RECEIVED_ALL)
{
  can_received = RECEIVED_NONE;
  ...
}

Storing queues seem fishy though. The normal procedure for CAN, being a real-time bus, is that you only keep the latest valid package and discard the rest. Particularly when dealing with sensors and control functions.




回答2:


You could just use the last value received every time. So you could receive a bunch of updates for the odometer, but only "latch" it in when the last of gps/velocity have been collected (pick one to sync to). If you're getting them from a system that periodically and predictably sends you messages, that's easy. You don't even need a queue, except for finalized values (if you want to see/use trending history).

If you care about being synchronized and accurate, you could interpolate your velocity. Do the same thing as above for the odometer, and stop saving it once the GPS is collected. Collect 2 values for velocity (before the GPS collection, and after). Interpolate the velocity (linearly) to generate the velocity value at the GPS collection time. Then report that out. This will generate a synchronized and accurate value every time the velocity is collected, delayed by the offset between your velocity/GPS collection timestamps.



来源:https://stackoverflow.com/questions/56669834/synchronizing-different-messages

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!