1

I want to check for specific string (like "RecordStart") in a UART stream (115 200 baud 8N1) from a camera, to know when it is recording or not/if there is an SD. I am using an ESP32-WROOM-32UE with 16MB flash. I wired the Tx from the camera to one of the pin of the ESP. The ESP32 is programmed with VsCode (platformIO) through Arduino framework. I am using freeRTOS.

The thing is, "RecordStart" or "RecordStop" or other strings, appear just one time. Sometimes (when the camera is powering on), there are many many strings sended, very fast. So, from time to time, I lose some bytes and I can't find the strings I am looking for. I would like to optimize my code to never miss a string.

How the code works ? If there is at least 1 byte in the serial buffer, the taskUART priority is set to 2 (while other tasks are priority 1. If a null character is detected, the message_UARTcam buffer starts to be filled. Then, each time a byte enters the buffer, I am checking if the buffer contains the strings I am looking for. It is working quite well but sometimes, I lose some bytes and the strings are not detected. I think It is because many other tasks are running and the serial buffer fills up faster than it empties. Increase temporarily the priority of the UART task improves the detection but I am still missing some bytes.

The code:

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(message);

        if (message_UARTcam.indexOf(stringStart_app) != -1 || message_UARTcam.indexOf(stringStart_button) != -1)
        {
          // Serial.println("Start recording");
          SD_UARTcam = 1;
          record_UARTcam = 1;
          bufferIndex_UARTcam = 0;
          message_UARTcam = "";
        }
        else if (message_UARTcam.indexOf(stringStop) != -1)
        {
          // Serial.println("Stop recording");
          record_UARTcam = 0;
          bufferIndex_UARTcam = 0;
          message_UARTcam = "";
        }
        else if (message_UARTcam.indexOf(stringSdError) != -1)
        {
          // Serial.println("SD error");
          SD_UARTcam = 0;
          record_UARTcam = 0;
          bufferIndex_UARTcam = 0;
          message_UARTcam = "";
        }
        else if (message_UARTcam.indexOf(stringSdInitOk) != -1)
        {
          // Serial.println("SD init OK");
          SD_UARTcam = 1;
          bufferIndex_UARTcam = 0;
          message_UARTcam = "";
        }
        else if (message_UARTcam.indexOf(stringSdRemoved) != -1)
        {
          // Serial.println("SD removed");
          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);
    }
  }
}

Camera output example:

␛[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 Answer 1

1

Here is an idea that may work: instead of buffering the input stream and comparing the buffer with the search string, you could do the comparison on the fly, as you receive the characters. Then you have no buffering at all, and no time spent in scanning through the buffer.

Below is a function that searches for the "RecordStart" marker, while being fed one character at a time. This function remembers how many correct characters it has received so far (this is the static variable pos), and updates this count on each received character. It returns true when it has just detected the marker, and false otherwise:

bool marker_found(int c) {
    const char marker[] = "RecordStart";  // search string
    static int pos = 0;  // correct characters received so far
    if (c == -1) return false;  // shortcut for a common case
    if (c == marker[pos]) {
        pos++;                      // count a correct character
        if (marker[pos] == '\0') {  // we got the complete string
            pos = 0;                // reset for next time
            return true;            // report success
        }
    } else if (c == marker[0]) {
        pos = 1;        // we have the initial character again
    } else {
        pos = 0;        // we received a wrong character
    }
    return false;
}

You would use it like this:

if (marker_found(SerialPortCam.read())) {
    // handle the incoming record
}

Note that you do not need to test for SerialPortCam.available() > 0, as this is already handled by marker_found().

1
  • I tried your code and it is working very well. I am going to test the performances when multiple tasks are running. Commented Jul 7, 2023 at 9:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.