grab string from serial interface

Hello,

I have connected two microcontrollers over serial interface.

Nr1: Arduino Zero.

Nr2: ESP.

The Zero is sending data to the ESP about each second.

The String the Zero sends looks like this: (it is a frequency spectrum)

[21824712|4165473|21694348|20389292|15398732|16299304|13460764|12566342|11133569|11444554|11731456|13067045|12438698|11396829|11048486|11908403|12153633|12760170|16578676|16782202|12995345|11139516|10831980|10893509|10414233|10751963|10970642|11424326|11543000|10128616|9954139|10467453|9890809|9858426|10474868|10995891|11318952|10196092|10157257|10275950|10296227|10611146|9779192|11463882|11106271|10953664|10153902|10090408|9635546|9992969|10229395|11047898|10077108|10003887|10017455|10936465|10377966|9951652|10474260|11464636|11584795|11705295|11356453|10593168]

The string begins with "[" and ends with "]"

There is the chance that before and after the string some other garbage information is sent from the zero.

What I want to do is to load the entire String beginning from [ to ] into an String variable. All garbage that comes before and after should be ignored.

All my aproaches did not work stable or did just work for short messages, but not for long ones.

I think that this is an relatively common problem - can anyone point me to a function or piece of code that can handle this?

This was my last try:

It did work for short messages, but not for long ones....

void loop() {

  /*** Daten vom Zero empfangen ***/

  String value = "";
    
  while (Serial.available()) {

    char inChar = (char)Serial.read();
    
    inputString = inputString + String(inChar);
            
    if (inChar == ']') {
      message_exists = true;
      break;
    }
  }

  if (message_exists == true) {
    message_exists = false;
    value = inputString;
    inputString = "";
  }

  if (value == "") { value = "XXX"; }
  
  /*** Daten senden ***/
  sendPacket(send_data(value));
    
  /*** Daten empfangen ***/
  
   for (int i=0; i <= 10; i++){
      delay(50);
      String data = readPacket();
      if (data != "") { Serial.print(data); } 
   }
}

Thanks!

"All my aproaches did not work stable or did just work for short messages, but not for long ones."

That gives us nothing to work with. What do you mean that it "didn't work"?

You are most likely experiencing Memory Problems due to: inputString = inputString + String(inChar); being inside a Loop which executes at least 569 times.

The first time through, the string consumes 1 Byte. The second time it consumes 2. The third time it consumes 3.

It consumes the Memory that the variable currently Needs PLUS the Memory the new value will Need.

So, the last time through, it Needs 568 + 569 Bytes.

To make it even worse, all the previous values haven't had time to be cleaned up meaning they are also still occupying Memory.

Your program is probably running out of Memory and crashing.

Because your values are so Long, compared to the amount of Memory you may have (which Arduino are you using? They have different amounts of Memory!), this will be no easy trick to accomplish but I don't think it is possible the way you are doing it.

You Need to try working with char Arrays instead.

JaBa:
You Need to try working with char Arrays instead.

yep.

like this:

const size_t MAX_MESSAGE_BUFFER_LENGTH = 256;  // <<<<<<< check this!!

template<class T> inline Print &operator << (Print &object, T argument)
{
  object.print(argument);
  return object;
}

void setup()
{
  Serial.begin(9600);
  if(Serial)
  {
    Serial << (F("let's go!\n"));
  }
}

void loop()
{
  if (const char* packet = checkForNewMessage(Serial, '[', ']'))  // checks for message on Serial with start marker of ">" and end marker of new line
  {
    Serial << (F("\nthis just in...\n")) << (packet) << (F("\n\n"));
  }
}

const char* checkForNewMessage(Stream& stream, const char startMarker, const char endMarker)
{
  static char incomingMessage[MAX_MESSAGE_BUFFER_LENGTH] = "";
  static unsigned char idx = 0;
  static bool gotStartMarker = false;
  if (stream.available())
  {
    if (!gotStartMarker)
    {
      if (stream.read() == startMarker)
      {
        gotStartMarker = true;
      }
    }
    else
    {
      incomingMessage[idx] = stream.read();
      if (incomingMessage[idx] == endMarker)
      {
        incomingMessage[idx] = '\0';
        idx = 0;
        gotStartMarker = false;
        if (!strlen(incomingMessage)) //startMarker followed immediatly by endMarker (i.e.no data)
        {
          //stream << (F("{\"error\":\"no data\"}\n"));  // you can return an error to sender here
          return nullptr;
        }
        //stream << (F("{\"success\":\"")) << (incomingMessage) << (F("\"}\n"));  // or return a success messaage
        return incomingMessage;
      }
      else
      {
        idx++;
        if (idx > MAX_MESSAGE_BUFFER_LENGTH - 1)
        {
          stream << (F("{\"error\":\"message exceeded ")) << (sizeof(incomingMessage) - 1) << (F(" chars\"}\n"));  // another error to sender here
          idx = 0;
          gotStartMarker = false;
          incomingMessage[idx] = '\0';
        }
      }
    }
  }
  return nullptr;
}

You might get ideas by reading Serial Input Basics; specifically the 3rd example. Just make sure that the declared buffer is large enough.