Как оптимизировать проверку конкретной строки в потоке UART

Я хочу проверить наличие определенной строки (например, "RecordStart") в потоке UART (115 200 бод, 8N1) с камера, чтобы узнать, когда она записывает или нет/есть ли запись является СД. Я использую ESP32-WROOM-32UE с флэш-памятью 16 МБ. Я подключил Tx от камеры к одному из контактов ESP. ESP32 программируется с помощью VsCode (platformIO) через среду Arduino. Я использую freeRTOS.

Дело в том, что "RecordStart" или "Остановка записи" или другие строки появляются только один раз. Иногда (когда камера включается) очень быстро отправляется много-много строк. Итак, время от времени я теряю несколько байтов и не могу найти нужные строки. Я хотел бы оптимизировать свой код, чтобы никогда не пропускать ни одной строки.

Как работает код? Если в последовательном буфере есть хотя бы 1 байт, приоритет taskUART устанавливается на 2 (в то время как другие задачи имеют приоритет 1. Если обнаружен нулевой символ, message_UARTcam Буфер начинает заполняться. Затем каждый раз, когда байт поступает в буфер, я проверяю, содержит ли буфер строки, которые я ищу. Он работает довольно хорошо, но иногда я теряю некоторые байты, и строки не обнаруживаются. Я думаю, это потому, что выполняется много других задач, и последовательный буфер заполняется быстрее, чем опустошается. Временно увеличьте приоритет задачи UART, чтобы улучшить обнаружение, но мне все еще не хватает некоторых байтов.

Код:

void taskUART(void *parameter)
{
  while (1)
  {
    if (SerialPortCam.available() > 0)
    {
      vTaskPrioritySet(nullptr, 2);
      char incomingChar = SerialPortCam.read();
      // Serial.write(incomingChar);

      if (flagNullChar == 1 || bufferIndex_UARTcam > 0 && bufferIndex_UARTcam < BUFFER_LEN_UART_CAM)
      {
        message_UARTcam += incomingChar;
        // Serial.println(сообщение);

        if (message_UARTcam.indexOf(stringStart_app) != -1 || message_UARTcam.indexOf(stringStart_button) != -1)
        {
          // Serial.println("Начать запись");
          SD_UARTcam = 1;
          record_UARTcam = 1;
          bufferIndex_UARTcam = 0;
          message_UARTcam = "";
        }
        else if (message_UARTcam.indexOf(stringStop) != -1)
        {
          // Serial.println("Остановить запись");
          record_UARTcam = 0;
          bufferIndex_UARTcam = 0;
          message_UARTcam = "";
        }
        else if (message_UARTcam.indexOf(stringSdError) != -1)
        {
          // Serial.println("Ошибка SD");
          SD_UARTcam = 0;
          record_UARTcam = 0;
          bufferIndex_UARTcam = 0;
          message_UARTcam = "";
        }
        else if (message_UARTcam.indexOf(stringSdInitOk) != -1)
        {
          // Serial.println("Инициализация SD ОК");
          SD_UARTcam = 1;
          bufferIndex_UARTcam = 0;
          message_UARTcam = "";
        }
        else if (message_UARTcam.indexOf(stringSdRemoved) != -1)
        {
          // Serial.println("SD удален");
          SD_UARTcam = 0;
          record_UARTcam = 0;
          bufferIndex_UARTcam = 0;
          message_UARTcam = "";
        }

        bufferIndex_UARTcam++;
        flagNullChar = 0;
      }

      if (incomingChar == 0x00)
      {
        flagNullChar = 1;
        message_UARTcam = "";
        bufferIndex_UARTcam = 0;
      }
    }
    else
    {
      vTaskPrioritySet(nullptr, 1);
    }
  }
}

Пример вывода с камеры:

␛[0;36m[00105849][CA9] ␀[App - Connected] <OnMessage> Received msg: 0xE001000C (param1 = 0x0 / param2 = 0x0)␛[0m
␛[0m[00105849][CA9] ␀RecCapState:0 RecCurrMode:0 RecNextMode:0 GFlags:0X7 Flags:0 StreamType:0␛[0m
␛[0m[00105849][CA9] ␀[App - Widget] <Off> widgetId: -1␛[0m
␛[0;33m[00105849][CA9] ␀[App_Glob_PWM_Buzzer] PWM Buzzer : 2␛[0m
␛[0m[00105849][CA9] ␀[App - ButtonOp] <MgrTask> Received msg: 0x0 (Param1 = 0x0 / Param2 = 0x0)␛[0m
␛[0m[00105849][CA9] ␀[App - ButtonOp] <MgrTask> Received msg: 0x1 (Param1 = 0x0 / Param2 = 0x0)␛[0m
␛[0m[00105899][CA9] ␀[rec_connected_cam_record_start] Start␛[0m
␛[0m[00105899][CA9] ␀[App - Connected] <RecordStart> REC_CONNECTED_CAM_RECORD_START␛[0m
␛[0m[00105899][CA9] ␀Dechi.motion_detec: 0␛[0m
␛[0m[00105899][CA9] ␀[Applib - ExtendEnc] <_ExtendEnc_SetEnableStatus> Enable flag: 0␛[0m
␛[0m[00105899][CA9] ␀[AppLib - MuxMp4] <SetTrickRecDivisor> Cur TrickRecDivisor: 1, New TrickRecDivisor: 1␛[0m
␛[0;34m[00105899][CA9] ␀[App - Sensor] <GetVinMode> Vin Mode = 11␛[0m

, 👍1


1 ответ


Лучший ответ:

1

Вот идея, которая может сработать: вместо буферизации входного потока и сравнивая буфер со строкой поиска, вы можете сделать сравнение на лету, по мере получения символов. Тогда у тебя нет буферизации вообще и не тратится время на сканирование буфера.

Ниже приведена функция, которая ищет маркер "RecordStart", в то время как кормят по одному персонажу за раз. Эта функция запоминает, сколько правильные символы, которые он получил на данный момент (это статическая переменная pos) и обновляет этот счетчик для каждого полученного символа. Он возвращает true, когда маркер только что обнаружен, и false в противном случае:

bool marker_found(int c) {
    const char marker[] = "RecordStart";  // строка поиска
    static int pos = 0;  // правильные символы, полученные на данный момент
    if (c == -1) return false;  // ярлык для обычного случая
    if (c == marker[pos]) {
        pos++;                      // подсчитываем правильный символ
        if (marker[pos] == '\0') {  // мы получили полную строку
            pos = 0;                // сброс для следующего раза
            return true;            // сообщаем об успехе
        }
    } else if (c == marker[0]) {
        pos = 1;        // у нас снова есть начальный символ
    } else {
        pos = 0;        // мы получили неправильный символ
    }
    return false;
}

Вы могли бы использовать это следующим образом:

if (marker_found(SerialPortCam.read())) {
    // обрабатываем входящую запись
}

Обратите внимание, что вам не нужно проверять SerialPortCam.available() > 0, поскольку это уже обрабатывается с помощью marker_found().

,

Я попробовал ваш код, и он работает очень хорошо. Я собираюсь протестировать производительность при выполнении нескольких задач., @AyubowanPro