UART Parsing

Using the below code to parse between the below messages… I can’t seem to ever get into flag 3 case even though I know it is being sent. I think is has to do when I am trying to check myCode[2] byte value.

int flag = 0;
byte myData[20];
byte myCode[3];

void recHRData() {
  byte n = Serial2.available();
  if (flag == 0)
  {
      myCode[0] = Serial2.read();
      myCode[1] = Serial2.read();
      myCode[2] = Serial2.read();
      Serial.print(myCode[0],HEX);
      Serial.println(" was rec!.....1");
      Serial.print(myCode[1],HEX);
      Serial.println(" was rec!.....2");
      Serial.print(myCode[2],HEX);
      Serial.println(" was rec!.....2");
    int x = (int)myCode[0] << 8 | (int)myCode[1];
    if (x == 0xAAAA)
    {
      Serial.println("Preamble found.");
      //memset(myCode, 0, 2);
    int y = (int)myCode[2];
    if(y==0x12){
       flag = 2;
       memset(myCode, 0, 3);   
    }
    if(y==0x04){
       flag = 3;
       memset(myCode, 0, 3);   
    }
    }
  }
  else if(flag == 2)
  {
    Serial2.readBytes(myData, 19);
    for(int i=0; i<19; i++)
    {
      byte x = myData[i];
      if(x <0x10)
      {
        Serial.print('0');  //prints leading zeo of a byte
      }
      Serial.print(myData[i], HEX);
    }
    Serial.println();
    Serial.println("Sending Heart Rate to App.");
    Serial.println(myData[3], DEC);
    flag = 0;
    memset(myData, 0, 19);
    Serial.println("=====================");
  }
    else if(flag == 3)
  {
    Serial2.readBytes(myData, 5);
    for(int i=0; i<5; i++)
    {
      byte x = myData[i];
      if(x <0x10)
      {
        Serial.print('0');  //prints leading zeo of a byte
      }
      Serial.print(myData[i], HEX);
    }
    Serial.println();
    Serial.println("Raw Data Found");
    flag = 0;
    memset(myData, 0, 5);
    Serial.println("=====================");
  }
}

Raw data msg 1 = [ 0xAA , 0xAA, 0x04, 0x80, 0x02, 0xXX, 0xXX, 0xXX]
rest data msg 2 = [ 0xAA , 0xAA, 0x12, 0x02, 0x00, 0x03, 0x4E , 0x84, 0x05, 0x00, 0xF9, 0x00,0x03,0x44,0x08,0x39,0x85,0x03,0xFF,0xFF,0xFF,0xXX]

Bold is the value I want to send back to device serially.

Using the below code to parse between the below messages… I can’t seem to ever get into flag 3 case even though I know it is being sent. I think is has to do when I am trying to check myCode[2] byte value.

int flag = 0;
byte myData[20];
byte myCode[3];

void recHRData() {
  byte n = Serial2.available();
  if (flag == 0)
  {
      myCode[0] = Serial2.read();
      myCode[1] = Serial2.read();
      myCode[2] = Serial2.read();
      Serial.print(myCode[0],HEX);
      Serial.println(" was rec!.....1");
      Serial.print(myCode[1],HEX);
      Serial.println(" was rec!.....2");
      Serial.print(myCode[2],HEX);
      Serial.println(" was rec!.....3");
    int x = (int)myCode[0] << 8 | (int)myCode[1];
    if (x == 0xAAAA)
    {
      Serial.println("Preamble found.");
      //memset(myCode, 0, 2);
    int y = (int)myCode[2];
    if(y == 0x12){
       flag = 2;
       Serial.println("HR Data");
       memset(myCode, 0, 3);
    }
    if(y == 0x04){
       flag = 3;
       Serial.println("Raw Data");
       memset(myCode, 0, 3);   
    }
    memset(myCode, 0, 3);
    }
  }
  else if(flag == 2)
  {
    Serial2.readBytes(myData, 19);
    for(int i=0; i<19; i++)
    {
      byte x = myData[i];
      if(x <0x10)
      {
        Serial.print('0');  //prints leading zeo of a byte
      }
      Serial.print(myData[i], HEX);
    }
    Serial.println();
    Serial.println("Sending Heart Rate to App.");
    Serial.println(myData[3], DEC);
    flag = 0;
    memset(myData, 0, 19);
    Serial.println("=====================");
  }
    else if(flag == 3)
  {
    Serial2.readBytes(myData, 5);
    for(int i=0; i<5; i++)
    {
      byte x = myData[i];
      if(x <0x10)
      {
        Serial.print('0');  //prints leading zeo of a byte
      }
      Serial.print(myData[i], HEX);
    }
    Serial.println();
    Serial.println("Raw Data Found");
    flag = 0;
    memset(myData, 0, 5);
    Serial.println("=====================");
  }
}

Raw data msg 1 = [ 0xAA , 0xAA, 0x04, 0x80, 0x02, 0xXX, 0xXX, 0xXX]
rest data msg 2 = [ 0xAA , 0xAA, 0x12, 0x02, 0x00, 0x03, 0x4E , 0x84, 0x05, 0x00, 0xF9, 0x00,0x03,0x44,0x08,0x39,0x85,0x03,0xFF,0xFF,0xFF,0xXX]

Bold is the value I want to send back to device serially.

The first 4 bytes of both messages are always constant as well.

Please post your complete sketch. The snippet you posted does not send any data.

When you do

 myCode[0] = Serial2.read();
myCode[1] = Serial2.read();
myCode[2] = Serial2.read();

how do you know that 3 bytes are available for reading?

I would suggest to study Serial Input Basics to handle this

Also Don’t post snippets (Snippets R Us!)

@sykotikk23

Other post/duplicate MOVED and MERGED
Please do NOT cross post / duplicate as it wastes peoples time and efforts to have more than one post for a single topic.

Continued cross posting could result in a time out from the forum.

Could you take a few moments to Learn How To Use The Forum.
It will help you get the best out of the forum in the future.
Other general [help and troubleshooting advice can be found here./url

I apologize for that here is the current code I am working with seems to work well. I took this approach to be able to filter each byte before

int flag = 0;
byte myData[20];
byte myCode[3];

void setup() {
  Serial.begin(9600);
  Serial2.begin(57600);
}

void loop(){
  recHRData();
}

void recHRData() {
  byte n = Serial2.available();
  int x;
  if (flag == 0)
  {
    myCode[0] = Serial2.read();
    x = (int)myCode[0];
    if(x == 0x00AA)
      {
        Serial.print(myCode[0],HEX);
        Serial.println("..Preamble Part 1 Found!");
        myCode[1] = Serial2.read();
        x = (int)myCode[1];
        if(x==0x00AA)
        {
          Serial.print(myCode[1],HEX);
          Serial.println("..Preamble Part 2 Found!");
          myCode[2] = Serial2.read();
          x = (int)myCode[2];
          if(x == 0x0012)
          {
            Serial.print(myCode[2],HEX);
            Serial.println("...Type 1 Message Found=====================================================");
            flag = 2;
            memset(myCode, 0, 3); 
          }
          else if(x == 0x0004)
          {
            Serial.print(myCode[2],HEX);
            Serial.println("...Type 2 Message Found");
            flag = 3;            
            memset(myCode, 0, 3); 
          }
          else
          {
            memset(myCode, 0, 3);              
          }
          
        }
        else
        {
          memset(myCode, 0, 3);           
        }
      }
    else
      {
        memset(myCode, 0, 3);  
      }
    //x = (int)myCode[0] << 8 | (int)myCode[1];
  }
  else if(flag == 2)
  {
    Serial2.readBytes(myData, 19);
    for(int i=0; i<19; i++)
    {
      byte x = myData[i];
      if(x <0x10)
      {
        Serial.print('0');  //prints leading zeo of a byte
      }
      Serial.print(myData[i], HEX);
    }
    Serial.println();
    Serial.println("Sending Heart Rate to App.");
    Serial.println(myData[3], DEC);
    flag = 0;
    memset(myData, 0, 19);
    Serial.println("=====================");
  }
    else if(flag == 3)
  {
    Serial2.readBytes(myData, 5);
    for(int i=0; i<5; i++)
    {
      byte x = myData[i];
      if(x <0x10)
      {
        Serial.print('0');  //prints leading zeo of a byte
      }
      Serial.print(myData[i], HEX);
    }
    Serial.println();
    Serial.println("Raw Data Found");
    flag = 0;
    memset(myData, 0, 5);
    Serial.println("=====================");
  }
}

Is there a simpler way of doing this then checking byte by byte?

If you look at the tutorial in reply #3, you can adapt it to your needs. Rather than a ton of nested if() statements, it is cleaner to use more of a state machine approach.

const byte numChars = 32;
char receivedChars[numChars];

boolean newData = false;

void setup() {
  Serial.begin(9600);
  Serial2.begin(57600);
  Serial.println("<Arduino is ready>");
}

void loop() {
  recvWithStartEndMarkers();
  showNewData();
}

enum { WAITING, START, LENGTH, DATA };

/*
   states
   WAITING == waiting for startMaker1 to arrive, discard everything else
   START   == startMarker1 has arrived, next byte should be startMarker2, else reset
   LENGTH  == startMarker2 has arrived, next byte will be packet length byte
   DATA    == reading in length data bytes, set newData true when complete
*/

void recvWithStartEndMarkers() {
  static int recvState = WAITING;
  static byte ndx = 0;
  const byte startMarker1 = 0xAA;
  const byte startMarker2 = 0xAA;
  static byte len = 0;
  char rc;

  while (Serial2.available() > 0 && newData == false) {
    rc = Serial2.read();

    switch (recvState) {
      case WAITING:
        if (rc == startMarker1) {
          receivedChars[ndx] = rc;
          ndx++;
          recvState = START;
        }
        break;

      case START:
        if (rc == startMarker2) {
          receivedChars[ndx] = rc;
          ndx++;
          recvState = LENGTH;
        }
        else {
          // bad char so reset everything
          ndx = 0;
          recvState = WAITING;
        }
        break;

      case LENGTH:
        len = rc;
        receivedChars[ndx] = rc;
        ndx++;
        recvState = DATA;
        break;

      case DATA:
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
        len--;
        if ( len == 0 ) {
          receivedChars[ndx] = '\0'; // terminate the string
          recvState = WAITING;
          ndx = 0;
          newData = true;
        }
        break;
    }
  }
}

void showNewData() {
  if (newData == true) {
    Serial.print("This just in ... ");
    byte len = receivedChars[2] + 3;  // length is 3rd char in buffer plus preamble
    for (int i = 0; i < len; ++i) {
      if (receivedChars[i] < 0x10 ) Serial.print( "0" );
      Serial.print(receivedChars[i], HEX);
    }
    newData = false;
  }
}

This (untested) code should spit out any message that starts with 0xAA, 0xAA. You can modify it to extract the data of interest out of the receivedChars array.

Thank you for the response. Upon testing, I had to move things around like recvState = 0 to the top since every iteration it was being reset to WAITING. Also changed rc from char to byte to get the compare to work correctly. However, it seems the print out at the end is coming in incorrectly any ideas?

const byte numChars = 32;
char receivedChars[numChars];

int recvState = 0;

boolean newData = false;

void setup() {
  Serial.begin(9600);
  Serial2.begin(57600);
  Serial.println("<Arduino is ready>");
}

void loop() {
  recvWithStartEndMarkers();
  showNewData();
}

enum { WAITING, START, LENGTH, DATA };

/*
   states
   WAITING == waiting for startMaker1 to arrive, discard everything else
   START   == startMarker1 has arrived, next byte should be startMarker2, else reset
   LENGTH  == startMarker2 has arrived, next byte will be packet length byte
   DATA    == reading in length data bytes, set newData true when complete
*/

void recvWithStartEndMarkers() {

  static byte ndx = 0;
  const byte startMarker1 = 0xAA;
  const byte startMarker2 = 0xAA;
  static byte len = 0;
  byte rc;
  while (Serial2.available() > 0 && newData == false) {
    rc = Serial2.read();
    Serial.println(rc,HEX);
    switch (recvState) {
      case WAITING:
          Serial.println("Waiting ... 1");
        if (rc == startMarker1) {
          receivedChars[ndx] = rc;
          ndx++;
          recvState = START;
          Serial.println("Waiting ... 2");
        }
        break;

      case START:
        if (rc == startMarker2) {
          Serial.println("Starting ... 1 ");
          receivedChars[ndx] = rc;
          ndx++;
          recvState = LENGTH;
          Serial.println("Starting ... 2");
        }
        else {
          // bad char so reset everything
          ndx = 0;
          recvState = WAITING;
        }
        break;

      case LENGTH:
        Serial.print("Length is ... ");
        len = rc;
        receivedChars[ndx] = rc;
        ndx++;
        recvState = DATA;
        Serial.println(len,DEC);
        break;

      case DATA:
        Serial.println("Data ... 1 ");
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
        len--;
        if ( len == 0 ) {
          receivedChars[ndx] = '\0'; // terminate the string
          recvState = WAITING;
          ndx = 0;
          newData = true;
        }
        break;
    }
  }
}

void showNewData() {
  if (newData == true) {
    Serial.print("This just in ... ");
    byte len = receivedChars[2] + 3;  // length is 3rd char in buffer plus preamble
    for (int i = 0; i < len; ++i) {
      if (receivedChars[i] < 0x10 ) Serial.print( "0" );
      Serial.print(receivedChars[i], HEX);
    }
    newData = false;
  }
}

Serial Monitor Output

AA
Waiting … 1
Waiting … 2
AA
Starting … 1
Starting … 2
4
Length is … 4
F3
Data … 1
AA
Data … 1
D8
Data … 1
AA
Data … 1
This just in … 0FFFFFFAA0FFFFFFAA040FFFFFFF30FFFFFFAA0FFFFFFD80FFFFFFAAAA

The variable recvState was declared as static inside that function so it was not being reset on every call. It is no different than the ndx or len variables. It is just a way to deduce the number of global variables.

You should also declare the receivedChars array as ‘byte’

Maybe the issue is with the showData() function with how it is determining the length of the array since it really is not a string.
This version just dumps the entire array and then zeros it out

const byte numChars = 32;
byte receivedChars[numChars];

int recvState = 0;

boolean newData = false;

void setup() {
  Serial.begin(9600);
  Serial2.begin(57600);
  Serial.println("<Arduino is ready>");
}

void loop() {
  recvWithStartEndMarkers();
  showNewData();
}

enum { WAITING, START, LENGTH, DATA };

/*
   states
   WAITING == waiting for startMaker1 to arrive, discard everything else
   START   == startMarker1 has arrived, next byte should be startMarker2, else reset
   LENGTH  == startMarker2 has arrived, next byte will be packet length byte
   DATA    == reading in length data bytes, set newData true when complete
*/

void recvWithStartEndMarkers() {

  static byte ndx = 0;
  const byte startMarker1 = 0xAA;
  const byte startMarker2 = 0xAA;
  static byte len = 0;
  byte rc;
  while (Serial2.available() > 0 && newData == false) {
    rc = Serial2.read();
    Serial.println(rc,HEX);
    switch (recvState) {
      case WAITING:
          Serial.println("Waiting ... 1");
        if (rc == startMarker1) {
          receivedChars[ndx] = rc;
          ndx++;
          recvState = START;
          Serial.println("Waiting ... 2");
        }
        break;

      case START:
        if (rc == startMarker2) {
          Serial.println("Starting ... 1 ");
          receivedChars[ndx] = rc;
          ndx++;
          recvState = LENGTH;
          Serial.println("Starting ... 2");
        }
        else {
          // bad char so reset everything
          ndx = 0;
          recvState = WAITING;
        }
        break;

      case LENGTH:
        Serial.print("Length is ... ");
        len = rc;
        receivedChars[ndx] = rc;
        ndx++;
        recvState = DATA;
        Serial.println(len,DEC);
        break;

      case DATA:
        Serial.println("Data ... 1 ");
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
        len--;
        if ( len == 0 ) {
          receivedChars[ndx] = '\0'; // terminate the string
          recvState = WAITING;
          ndx = 0;
          newData = true;
        }
        break;
    }
  }
}

void showNewData() {
  if (newData == true) {
    Serial.print("This just in ... ");
    byte len = receivedChars[2] + 3;  // length is 3rd char in buffer plus preamble
    for (int i = 0; i < numChars; ++i) {
      if (receivedChars[i] < 0x10 ) Serial.print( "0" );
      Serial.print(receivedChars[i], HEX);
    }
    newData = false;
    memset(receivedChars, 0, numChars);
  }
}

@blh64 Thanks great I am testing and works well. I am still not able to find the AAAA12 and I do not think it is a parser issue.

If I were to write the below would it give me output to serial of accurate stream of data? It seems after a certain point it is corrupt.

void setup() {
  Serial.begin(57600);
  Serial2.begin(57600);
  Serial.println("<Arduino is ready>");
}

void loop() {
 //recvWithStartEndMarkers();
 //showNewData();
 byte rc;
 while (Serial2.available() > 0){
      rc = Serial2.read();
 if (rc < 0x10 ) Serial.print( "0" );
 Serial.print(rc, HEX);
 }
}

It seems after a certain point it is corrupt.

Can you give us an example of the serial output which is normal and then turns "corrupt". What exactly are you seeing?

What is the timing of the serial2 stream? How often is it sent?

@cattledog - The stream is being sent constantly with this Raw data message and rest data shows up every 1 second.

Raw data msg 1 = [ 0xAA , 0xAA, 0x04, 0x80, 0x02, 0xXX, 0xXX, 0xXX]
rest data msg 2 = [ 0xAA , 0xAA, 0x12, 0x02, 0x00, 0x03, 0x4E , 0x84, 0x05, 0x00, 0xF9, 0x00,0x03,0x44,0x08,0x39,0x85,0x03,0xFF,0xFF,0xFF,0xXX]

Attached is what is should look like (correct.txt) And the (57600baud.txt) is my log.

correct.txt (70.3 KB)

log57600baud.txt (30.4 KB)

Your data streams appears to be sending 1 more byte than the len byte (len = 0x04 → 5 more bytes, len = 0x12 → 19 more bytes)

You should also set your serial baud rate to 115200 so you don’t overrun the buffer since Serial2 is a constant stream.

const byte numChars = 32;
byte receivedChars[numChars];

int recvState = 0;

boolean newData = false;

void setup() {
  Serial.begin(115200);
  Serial2.begin(57600);
  Serial.println("<Arduino is ready>");
}

void loop() {
  recvWithStartEndMarkers();
  showNewData();
}

enum { WAITING, START, LENGTH, DATA };

/*
   states
   WAITING == waiting for startMaker1 to arrive, discard everything else
   START   == startMarker1 has arrived, next byte should be startMarker2, else reset
   LENGTH  == startMarker2 has arrived, next byte will be packet length byte
   DATA    == reading in length data bytes, set newData true when complete
*/

void recvWithStartEndMarkers() {

  static byte ndx = 0;
  const byte startMarker1 = 0xAA;
  const byte startMarker2 = 0xAA;
  static byte len = 0;
  byte rc;
  while (Serial2.available() > 0 && newData == false) {
    rc = Serial2.read();
    Serial.println(rc,HEX);
    switch (recvState) {
      case WAITING:
          Serial.println("Waiting ... 1");
        if (rc == startMarker1) {
          receivedChars[ndx] = rc;
          ndx++;
          recvState = START;
          Serial.println("Waiting ... 2");
        }
        break;

      case START:
        if (rc == startMarker2) {
          Serial.println("Starting ... 1 ");
          receivedChars[ndx] = rc;
          ndx++;
          recvState = LENGTH;
          Serial.println("Starting ... 2");
        }
        else {
          // bad char so reset everything
          ndx = 0;
          recvState = WAITING;
        }
        break;

      case LENGTH:
        Serial.print("Length is ... ");
        receivedChars[ndx] = rc;
        ndx++;
        recvState = DATA;
        Serial.println(rc);
        len = rc+1;
        break;

      case DATA:
        Serial.println("Data ... 1 ");
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
        len--;
        if ( len == 0 ) {
          receivedChars[ndx] = '\0'; // terminate the string
          recvState = WAITING;
          ndx = 0;
          newData = true;
        }
        break;
    }
  }
}

void showNewData() {
  if (newData == true) {
    Serial.print("This just in ... ");
    byte len = receivedChars[2] + 3;  // length is 3rd char in buffer plus preamble
    for (int i = 0; i < numChars; ++i) {
      if (receivedChars[i] < 0x10 ) Serial.print( "0" );
      Serial.print(receivedChars[i], HEX);
    }
    newData = false;
    memset(receivedChars, 0, numChars);
  }
}

Your data streams appears to be sending 1 more byte than the len byte (len = 0x04 → 5 more bytes, len = 0x12 → 19 more bytes)

Yes, that is the checksum.

See pages 9-11 of this BMD101 product document for the data format and advice on receiving and parsing.

It’s pretty clear on only using data with a valid check sum.

@cattledog and @blh64 Just a side note while I test the code. I will say I was never able to find AAAA12 when using just the code to parse and not to output to Serial. Is it possible that the arduino is not processing Serial2 fast enough?

When I look at the "bad" data, I see the 4 byte payloads become truncated, and I never see an AAAA12 for an 18 byte payload. Is that correct?

Why do you believe that the issue is with the receiver and not the sender?

I will say I was never able to find AAAA12 when using just the code to parse and not to output to Serial.

I would doubt that, but I don't know for certain. Is there any settings available on the BMD101 to slow down the baud rate?

How important is "real time" data?
Do you need every 4 byte message?

Perhaps the data can be dual buffered with one buffer being filled, and the other buffer being parsed. Parsing a completely received message is much easier than trying to parse on the fly.

@cattledog , great questions. I was able to hook this directly up to a FTDI chip to my usb on my computer and was able to validate it was receiving the AAAA12 messages correctly.

I do not need the realtime data at all, I am solely interested in the AAAA12 data as it has the information I want. The AAAA04 messages or and AAAAXX that are not 12 are useless to me.

One suggestion to help figure out where you are, is to modify the reading code you have and just look for AAAA12 in the stream. Forget about reading the message and parsing pieces of it.

Can you just detect AAAA12 on the fly? You seem to know that it is actually there.

@cattledog , I can take and attempt at it for sure. I was thinking something along the lines of having a buffer that fills only with AAAA12 values otherwise the buffer would just look at the next memory position. The only problem there is what can I do do quickly search the incoming(Serial2) stream for AAAA12 without going byte by byte.

The data arrives byte by byte and you should be able to identify a three byte sequence and then grab the payload.