Serial receiving the last byte

Hi guys I am using esp32 on arduino and serially receiving some data from another module. My data contains 0x6F as the first byte of every packet to differentiate between packets and the last byte is 0x7F to stop receiving and do some stuff. But the problem is sometimes I donot go to that flag which I have set when receive 0x7F. Kindly look at the code.

The data I receive is like: 0x6F 0x01 0x02 0x6F 0x03 0x04 0x7F

The output should be : device1 = 0x01 0x02
device2 = 0x03 0x04

It is working but not always. Kindly tell me if I am missing something or what is the better approach to do this.

I appreciate your suggestions.

Regards,

void main(){
  if (Serial2.available()) {
    uint8_t temp = Serial2.read();
    if (temp == 0x6F) {
      getMyDesiredDevice();
    }
    else if (temp == 0x7F) {
      data_flag = true;
    }
  }



  if (data_flag == true)
  {
    // do some stuff
    data_flag = false;

  }
}

Please post your full sketch.

Does the problem still occur if you use the standard Arduino setup() and loop() functions instead of overriding them by defining main() in your sketch?

Why do you override the main() function?

For the problem
1)
wait for 0x6F
2)
read all data into an array till you receive 0x7F
3)
split the data on 0x6F, e.g. using strtok()

To get ideas, read the updated Serial Input Basics thread.

If you are both transmitting and receiving with Arduinos, I suggest using this serial data transfer library. It's easy to use and 100% reliable - I even use it for wirelessly controlling Arduino RC planes. It will mitigate the need to debug your own serial data parser.

@OP

1. This is your example reception frame: 0x6F 0x01 0x02 0x6F 0x03 0x04 0x7F; where. 0x6F is the marker of a data item and 0x7F is the marker for the end of transmission/reception frame.

2. Receive and store all the bytes until 0x7F is found.

mySerial.readBytesUntl(0x7F, myData, 10);

3. The byte type array will hold all data bytes except 0x7F.

4. You know the structure of your array. If it is a fixed structure, you can reconstruct the data items.
(1) int device1 = myData[1]<<8 | myData[2]; // device1 = 0102
(2) int device2 = myData[4]<<8 | myData[5]; // device2 = 0304

Here is how I read Serial on an ESP32

void fReceiveSerial_LIDAR( void * parameters  )
{
  bool BeginSentence = false;
  sSerial.reserve ( StringBufferSize300 );
  char OneChar;
  for ( ;; )
  {
    EventBits_t xbit = xEventGroupWaitBits (eg, evtReceiveSerial_LIDAR, pdTRUE, pdTRUE, portMAX_DELAY);
    // vTaskDelayUntil( &xLastWakeTime, xFrequency );
    if ( LIDARSerial.available() >= 1 )
    {
      while ( LIDARSerial.available() )
      {
        OneChar = LIDARSerial.read();
        if ( BeginSentence )
        {
          if ( OneChar == '>')
          {
            if ( xSemaphoreTake( sema_ParseLIDAR_ReceivedSerial, xSemaphoreTicksToWait10 ) == pdTRUE )
            {
              xQueueOverwrite( xQ_LIDAR_Display_INFO, ( void * ) &sSerial );
              xEventGroupSetBits( eg, evtParseLIDAR_ReceivedSerial );
              //
            }
            BeginSentence = false;
            break;
          }
          sSerial.concat ( OneChar );
        }
        else
        {
          if ( OneChar == '<' )
          {
            sSerial = ""; // clear string buffer
            BeginSentence = true; // found begining of sentence
          }
        }
      } //  while ( LIDARSerial.available() )
    } //if ( LIDARSerial.available() >= 1 )
    xSemaphoreGive( sema_ReceiveSerial_LIDAR );
  }
  vTaskDelete( NULL );
} //void fParseSerial( void * parameters  )

Note that I use if ( LIDARSerial.available() >= 1 ) instead of if ( LIDARSerial.available() >= 0 ). I found the 1 works better with the ESP32 than the 0.

Thank you guys for your support. I will try what you guys have suggested and see what best works for me. The reply from sterretje and GolamMostafa looks good as it describes the best what I want to achieve. Sorry, I was writing my code instead of copy paste, so I wrote main() instead of loop() by mistake.

There is also one thing which confuses me, whether to use while(serial2.available()) or if(serial2.available()) as both works in the same manner.

Also, I will try if(serial2.available() >= 1) as mentioned by idahowalker.

Regards,

I’m not sure how you synchronize the device sending the identifiers and the Arduino but you can try this to see if it’s close:

#define MAX_NUM_DEVS        50
#define MSG_DEV_DEMARCATOR  0x6f
#define MSG_EOT             0x7f

unsigned int
    grDevices[MAX_NUM_DEVS];

void setup() 
{
    Serial2.begin(9600);
    Serial.begin(9600);
    memset( grDevices, 0, sizeof( grDevices ) );
    
}//setup

void loop() 
{
    ReceiveDeviceIDs();

}//loop

void ReceiveDeviceIDs( void )
{
    char
        cRxed;
    static bool
        bSynced = false,
        bByte = true;
    static byte
        devidx = 0;
                
    if( Serial2.available() == 0 )
        return;
        
    while( Serial2.available() )
    {        
        cRxed = Serial2.read();

        if( !bSynced )
        {
            //wait until we see a device demarcator or EOT symbol
            if( cRxed == MSG_DEV_DEMARCATOR || cRxed == MSG_EOT )
            {
                bByte = true;
                bSynced = true;
                
            }//
            
        }//if
        else
        {
            if( cRxed == MSG_DEV_DEMARCATOR )
                bByte = true;
            else if( cRxed == MSG_EOT )
            {
                PrintResults( devidx );
    
                //you can do whatever else you need here
                //DoOtherStuff();
    
                //clear the device array ready for the next sequence of msgs
                memset( grDevices, 0, sizeof( grDevices ) );
                
                //make sure we're filling the array starting at element 0
                devidx = 0;
                    
            }//if
            else
            {                    
                //is this byte the MSB (true) or LSB (false)?
                if( bByte == true )
                {
                    //MSB
                    grDevices[devidx] = (unsigned int)(bByte << 8);
                    //and set to receive the LSB
                    bByte = false;
                    
                }//if
                else
                {
                    //LSB
                    grDevices[devidx] |= bByte;                
    
                    //after LSB, bump to next entry in table
                    //but don't overrun it
                    //the last value will be over-written int the event there
                    //are more than MAX_NUM_DEVS devices                   
                    if( devidx < (MAX_NUM_DEVS-1) )
                        devidx++;
                    
                }//else   
                
            }//if

        }//else
    
    }//while

}//ReceiveDeviceIDs

void PrintResults( int numdevs )
{
    if( numdevs == 0 )
    {
        //if no devices were found (so msg was 0x6f-0x7f), print as much
        //to debug monitor
        Serial.println( "No devices found." );
        
    }//if
    else
    {
        //non-zero devidx means we found at least one
        Serial.print( numdevs );
        Serial.println( " devices found:" );    

        //print results & reset SM
        for( int i=0; i<numdevs; i++ )
        {
            Serial.print( "Device #" );
            Serial.print( i+1 );
            Serial.print( ": " );
            Serial.print( grDevices[i], HEX );
            Serial.println("");

        }//for
        
    }//else
    
}//PrintResults

Workaholic:
There is also one thing which confuses me, whether to use while(serial2.available()) or if(serial2.available()) as both works in the same manner.

I use the following signal flow diagram to decide when to use if() or while():
uartSignalFlow.png

1. I check if the receiver has stored at least 1-byte data/character in the FIFO Buffer.

byte n = SUART.available();
If( n != 0 )  //there is at least one data item in the FIFO Buffer
{
   char x = SUART.read();     //let us read it assuming that the incoming data item is an ASCII character
}

2. If() structure reads data one-by-one from the FIFO Buffer; the while() structure reads all the available data items from the FIFO Buffer. Example codes:

if() structure:
//Sender Codes:

SUART.print("abcd");

//Receiver Codes:

void loop()
{
   byte n = SUART.available();
   If( n != 0 )  //there is at least one data item in the FIFO Buffer
   {
      char x = SUART.read();  //let us read it assuming that the incoming data item is an ASCII character
      Serial.print(x);              //shows: a
   }

   while(1);
}

while() structure:
//Sender Codes:

SUART.print("abcd");

//Receiver Codes:

void loop()
{
   while(SUART.available()>0)
   {
      mychar[i] = SUART.read();  //let us read it assuming that incoming data item is an ASCII character
      i++;
   }
   Serial.print(myChar);             //shows: abcd
   while(1);
}

uartSignalFlow.png

OP, did you consider using the library I suggested?