Reading serial data packets

I need to read the following packet of data into an 8266 and parse it.
*X;1:000; 0;0;000;1
I have the following code working but data comes in as characters rather than one packet.

  if (Serial.available()) {
    char data = Serial.read();  // read the received character
    display.print("data= ");
    Serial.print(data);         // echo back to data to the sender
    display.println(data);
  }

I did read the 'Serial Input Basics' but the example there has an end of data code, I don't have that.
My data set always stars with a * and is 19 chars long...

Any assistance how to get started to pull this data in would be appreciated.

Thanks

I would suggest to study Serial Input Basics to handle this

Sscanf() can then be used or strtok() and strtol() if the numbers are integers

I have read that, as I said the examples there are based on an ending which I dont have. Is there a way to bring in 19 characters after a starting character?

The '*' is effectively the line ending character

1 Like

Is there a new line at the end ?

If not, either you handle the next star as the end character or need to build a timeout or use the fact it’s always 19 chars (is it?)

(Sorry for not reading carefully your first post)

1 Like

You can use the following codes to receive/store the arrived string (data packet) and then use strtok() function of post #2 @J-M-L to parse the string for the extracton of the individual data items.

char myData[19];   //'*' not saved; 18 chars are saved, last one for null

void loop()
{
    byte n = Serial.available();
    if(n !=0)
    {
       char ch = Serial.read();
       if(ch == '*')
       {
          byte m = Serial.readBytes(myData, 18); //
          myData[m] = '\0';  //inset null-byte
          Serial.println(myData);  //see the arrived string
          //--insert codes to extract data items from myData[] array-------
       }
   }
}

Is it "line ending character" or "line beginning character (the Start Mark of a New Frame)"?

It may looks obvious, but what about to catch the start character and then count received chars until it became a 18... ?

1 Like

a small state machine could do. I count only 18 characters including the star though

*X;1:000; 0;0;000;1
I have counted 19 including the * and the space after the 2nd data item.

I need to get my eye surgery done... 19th of feb !

so something like this should work (typed here, fully untested)

// read incoming messages with format "*X;1:000; 0;0;000;1"
const char startMarker = '*';   // our payload start marker
const byte payloadSize = 18;    // without the start marker
char payload[payloadSize + 1];  // +1 for the trailing null char.

bool receivePayload() {
  static enum State : byte {WAITING_STAR, WAITING_PAYLOAD} state = WAITING_STAR;
  static byte count = 0;

  bool payloadReady = false;

  if (Serial.available()) {
    char r = Serial.read();
    switch (state) {
      case WAITING_STAR:
        if (startMarker == r) {
          count = 0;                // reset the count
          payload[0] = '\0';        // mark the buffer empty
          state = WAITING_PAYLOAD;  // get ready for receiving the payload
        }
        break;

      case WAITING_PAYLOAD:
        payload[count++] = r;
        payload[count] = '\0'; // mainatin a readable payload
        payloadReady = (count >= payloadSize);
        if (payloadReady) state = WAITING_STAR;
        break;

    }
  }
  return payloadReady;
}

void handlePayload() {
  Serial.print(F("Parsing ["));
  Serial.print(payload);
  Serial.println(F("]"));

  char X;
  int num1, num2, num3, num4, num5, num6;
  int fieldsParsed =  sscanf(payload, "%c;%d:%d; %d;%d;%d;%d", &X, &num1, &num2, &num3, &num4, &num5, &num6);

  if (7 == fieldsParsed) {
    Serial.print("X: ");    Serial.println(X);
    Serial.print("num1: "); Serial.println(num1);
    Serial.print("num2: "); Serial.println(num2);
    Serial.print("num3: "); Serial.println(num3);
    Serial.print("num4: "); Serial.println(num4);
    Serial.print("num5: "); Serial.println(num5);
    Serial.print("num6: "); Serial.println(num6);
  } else {
    Serial.println("Error: Failed to parse all fields correctly.");
  }
}

void setup() {
  Serial.begin(115200);
  Serial.println(F("ready"));
}

void loop() {
  if (receivePayload())handlePayload();
}

you could add further error testing once you extracted the values as the code as it stands does not worry about one or 3 digits for the numbers.

are the field widths of the data within the frame fixed?
e.g. X; followed by one digit : followed by three digits etc etc

is the data continuous or periodic etc
e.g.

*X;1:000; 0;0;000;1*X;1:000; 0;0;000;1*X;1:000; 0;0;000;1

once you have read the data into a byte array you could parse it using sscanf(), e.g.

  byte data[] = "*X;1:000; 0;0;000;1";
  int d1, d2, d3, d4, d5, d6;
  if (sscanf((char *)data, "*X;%d:%d;%d;%d;%d;%d", &d1, &d2, &d3, &d4, &d5, &d6) == 6) {
    Serial.printf("\n\nD1 %d\n", d1);
    Serial.printf("D2 %d\n", d2);
    Serial.printf("D3 %d\n", d3);
    Serial.printf("D4 %d\n", d4);
    Serial.printf("D5 %d\n", d5);
    Serial.printf("D6 %d\n", d6);
  }

gives

D1 1
D2 0
D3 0
D4 0
D5 0
D6 1

Thank you, this works

1 Like

Can you print here the outputs that you have got as well as your complete sketch?

Literally just your code, I havent had time to start parsing the data yet.

Thank you for your code, however I just get no response at all in the serial monitor when i send some test data....

can you post the full code you use and describe the wiring / power ?

Post the interface requierement specification to see how we can help.

The code you posted as below does not work.
GolemMastafa's code does.
Circuit is just an RS232-TTL board Tx & Rx to Tx & Rx on an 8266

// read incoming messages with format "*X;1:000; 0;0;000;1"
const char startMarker = '*';   // our payload start marker
const byte payloadSize = 18;    // without the start marker
char payload[payloadSize + 1];  // +1 for the trailing null char.

bool receivePayload() {
  static enum State : byte {WAITING_STAR, WAITING_PAYLOAD} state = WAITING_STAR;
  static byte count = 0;

  bool payloadReady = false;

  if (Serial.available()) {
    char r = Serial.read();
    switch (state) {
      case WAITING_STAR:
        if (startMarker == r) {
          count = 0;                // reset the count
          payload[0] = '\0';        // mark the buffer empty
          state = WAITING_PAYLOAD;  // get ready for receiving the payload
        }
        break;

      case WAITING_PAYLOAD:
        payload[count++] = r;
        payload[count] = '\0'; // mainatin a readable payload
        payloadReady = (count >= payloadSize);
        if (payloadReady) state = WAITING_STAR;
        break;

    }
  }
  return payloadReady;
}

void handlePayload() {
  Serial.print(F("Parsing ["));
  Serial.print(payload);
  Serial.println(F("]"));

  char X;
  int num1, num2, num3, num4, num5, num6;
  int fieldsParsed =  sscanf(payload, "%c;%d:%d; %d;%d;%d;%d", &X, &num1, &num2, &num3, &num4, &num5, &num6);

  if (7 == fieldsParsed) {
    Serial.print("X: ");    Serial.println(X);
    Serial.print("num1: "); Serial.println(num1);
    Serial.print("num2: "); Serial.println(num2);
    Serial.print("num3: "); Serial.println(num3);
    Serial.print("num4: "); Serial.println(num4);
    Serial.print("num5: "); Serial.println(num5);
    Serial.print("num6: "); Serial.println(num6);
  } else {
    Serial.println("Error: Failed to parse all fields correctly.");
  }
}

void setup() {
  Serial.begin(115200);
  Serial.println(F("ready"));
}

void loop() {
  if (receivePayload())handlePayload();
}

are you communicating at 115200 bauds ?