Data parsing

Hi all

I am attempting to read and interpret some data over serial - one module is sending a message in the form of: [start character] [data 1] [delimiter] [data 2] [end character].

In this case the start character is '!', the delimited is ',' and the end character is ';', so a message might look like this: !2,87;

The process by which this code is sent is simply printing over serial, where data1 and data2 are the values to be sent:

const char startChar = '!';
const char endChar = ';';
const char delimiter = ',';

mySerial.print(startChar);
mySerial.print(data1);
mySerial.print(delimiter);
mySerial.print(data2);
mySerial.print(endChar);

I have (I think) created a piece of code that looks out for the start character and writes the message into an buffer until the end character is seen:

void loop()
{ 
  while (mySerial.available()>0)  // While serial data is available....
  {
    char c = mySerial.read(); //read in character
    if (c == startChar)  // Check for start character
    {
      index = 0;  // set buffer index to 0
      storeString = true;  // start storing data
    }

    if(storeString == true) // whilst storing data...
    {
      if(c == endChar) // stop filling buffer when end character is seen
      {
        buffer[index] = 0; //reset buffer
        storeString = false; // stop storing data
      }  
      else
      {
        buffer[index++] = c; // write character into buffer
      }  
    }
  }  

}

How does this look so far, along the right lines?
I have done some reading around but cannot suss out what the next stage is. I wish to save the 2 integer values of data1 and data2, possibly into an array?

Some help would be greatly appreciated - thank you!

How does this look so far, along the right lines?

Yes. You should have two booleans, though, started (in place of storeString) and ended, set to true when the end of packet marker arrives. Leave started set to true when the end of packet marker arrives.

Then,

} // end of serial data collection

if(started && ended)
{
   // A complete packet has arrived

I have done some reading around but cannot suss out what the next stage is.

strtok() and atoi().

Brilliant thanks.

Will my data operations then be completed in the " if(started && ended) " loop?

I will look into the functions you mentioned. Thanks

I have something working, although no doubt it could be done better! ?

I have changed buffer from a char array to a string, seems to make things a bit simpler. Any downsides to this I should be aware of?

if(started && ended)
    {
      int data1;
      int data2;

      char buffer2[buffer.length()+1];
      buffer.toCharArray(buffer2, buffer.length()+1);
      char *token = strtok(buffer2, ",");

      // data 1
      if (token)
      {
        data1 = atoi(token);
        token = strtok(NULL, ",");
      }

      // data2
      if (token)
      {
        data2 = atoi(token);
        token = strtok(NULL, ",");

        Serial.print(data1);
        Serial.print(" ");
        Serial.println(data2);

        started = false;
        ended = false;  
      }
    }
I have changed buffer from a char array to a string, seems to make things a bit simpler.

You'll find that the String class uselessly pisses away resources. It is NOT necessary. People wrote text processing applications in C for 30 years before C++ came along.

Any downsides to this I should be aware of?

Well, maybe a few...

Since you-know-who brought up Strings: 8)

//zoomkat 11-12-13 String capture and parsing  
//from serial port input (via serial monitor)
//and print result out serial port
//copy test strings and use ctrl/v to paste in
//serial monitor if desired
// * is used as the data string delimiter
// , is used to delimit individual data 

String readString; //main captured String 
String angle; //data String
String fuel;
String speed1;
String altidude;

int ind1; // , locations
int ind2;
int ind3;
int ind4;
 
void setup() {
  Serial.begin(9600);
  Serial.println("serial delimit test 11-12-13"); // so I can keep track of what is loaded
}

void loop() {

  //expect a string like 90,low,15.6,125*
  //or 130,hi,7.2,389*

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == '*') {
      //do stuff
      
      Serial.println();
      Serial.print("captured String is : "); 
      Serial.println(readString); //prints string to serial port out
      
      ind1 = readString.indexOf(',');  //finds location of first ,
      angle = readString.substring(0, ind1);   //captures first data String
      ind2 = readString.indexOf(',', ind1+1 );   //finds location of second ,
      fuel = readString.substring(ind1+1, ind2+1);   //captures second data String
      ind3 = readString.indexOf(',', ind2+1 );
      speed1 = readString.substring(ind2+1, ind3+1);
      ind4 = readString.indexOf(',', ind3+1 );
      altidude = readString.substring(ind3+1); //captures remain part of data after last ,

      Serial.print("angle = ");
      Serial.println(angle); 
      Serial.print("fuel = ");
      Serial.println(fuel);
      Serial.print("speed = ");
      Serial.println(speed1);
      Serial.print("altidude = ");
      Serial.println(altidude);
      Serial.println();
      Serial.println();
      
      readString=""; //clears variable for new input
      angle="";
      fuel="";
      speed1="";
      altidude="";
    }  
    else {     
      readString += c; //makes the string readString
    }
  }
}

I have changed buffer from a char array to a string, seems to make things a bit simpler.

I don't see that it is much simpler, particularly as you convert the String to a char array anyway.

Use a char array and stick with it.