Как оптимизировать проверку конкретной строки в потоке 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
@AyubowanPro, 👍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()
.
- esp32, platformio A fatal error occurred: Packet content transfer stopped (received 8 bytes) *** [upload] Error 2
- I2C связь между Arduino Uno и Nodemcu32-s (ESP32)
- Лучшая практика буферизации для непрерывной записи на SD-карту
- Аппаратное управление последовательным потоком ESP32 и полная поддержка espressif/arduino-esp32
- Не могу подключиться к плате ESP32 через последовательный порт
- Нужен пример того, как отправлять КОМАНДЫ AT на модуль SIm7000E GPS+LTE из ESP32 и читать эти ответы в последовательном мониторе
- Таблица разделов ESP32 и место записи
- ESP отправить строку в Arduino
Я попробовал ваш код, и он работает очень хорошо. Я собираюсь протестировать производительность при выполнении нескольких задач., @AyubowanPro