Синхронизация разных сообщений - PullRequest
0 голосов
/ 19 июня 2019

Я думаю, что это общая проблема программной парадигмы, поэтому она не сильно связана со встроенным программным обеспечением.

У меня есть 3 сообщения, которые я получаю в разные интервалы времени, три сообщения Одо, скорость, GPS. каждый из них имеет временной интервал 20 мс, 1 с и 1 с.

Моя проблема в том, как бы я синхронизировал и получил полное сообщение, только когда три уже получены.

Мой текущий подход состоит в том, чтобы иметь три кольцевые очереди и поместить три логические переменные и проверить, все ли они синхронизированы, но это не сработает, если, например, odo, который имеет временной интервал 20 мс, выполняется снова и снова без других сообщения.

Вот что я делаю:

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;
  }
}

и в основном цикле

 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;
        }

Ответы [ 2 ]

1 голос
/ 19 июня 2019

Вы создаете битовое поле и устанавливаете бит для каждого типа полученного сообщения.

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;
  ...
}

Хотя сохранение очередей кажется подозрительным.Обычная процедура для CAN, являющейся шиной реального времени, заключается в том, что вы сохраняете только последний действительный пакет, а остальные отбрасываете.Особенно при работе с датчиками и функциями управления.

0 голосов
/ 19 июня 2019

Вы можете просто использовать последнее значение, полученное каждый раз.Таким образом, вы можете получить кучу обновлений для одометра, но только «защелкнуть» его, когда будут собраны последние значения gps / speed (выберите одно для синхронизации).Если вы получаете их из системы, которая периодически и предсказуемо отправляет вам сообщения, это легко.Вам даже не нужна очередь, за исключением окончательных значений (если вы хотите просмотреть / использовать историю трендов).

Если вам нужна синхронизация с точностью и , вы можете интерполировать вашискорость.Сделайте то же самое, что и выше для одометра, и перестаньте сохранять его после сбора GPS.Соберите 2 значения скорости (до сбора GPS и после).Интерполируйте скорость (линейно), чтобы получить значение скорости во время сбора данных GPS.Тогда сообщите об этом.Это будет генерировать синхронизированное и точное значение при каждом сборе скорости, задержанное смещением между вашими временными метками скорости / сбора GPS.

...