Using BufferedSerial for receiving data with a high error package rate

bool receiveData(float& speed, uint16_t& direction) {
        uint8_t buffer[FRAME_SIZE];
        ssize_t bytes_read = 0;

        // Reading exact number of bytes for one frame
        memset(buffer,0,sizeof(buffer));
        if (uart.readable()) {
            ThisThread::sleep_for(1ms);  // Polling interval
            bytes_read += uart.read(buffer ,FRAME_SIZE);
        }
          // Validate frame header and length
        if (buffer[0] == 0x42 && buffer[1] == 0x01 && buffer[2] == 10) {
            // Parsing speed
            
            UInt16Union directionUnion;
            FloatUnion speedUnion;
            speedUnion.bytes[0]=buffer[3];
            speedUnion.bytes[1]=buffer[4];
            speedUnion.bytes[2]=buffer[5];
            speedUnion.bytes[3]=buffer[6];
            
            directionUnion.bytes[0]=buffer[7];
            directionUnion.bytes[1]=buffer[8];

            direction = directionUnion.asUInt16;
            speed = speedUnion.asFloat;
            
            unsigned char check=0;
            for (size_t i = 0; i < 9; i++)
                {
                    check += buffer[i];
                }
            if (check!=buffer[9]) return false;

            sendData(speed,direction);
            // buffer[9]=check;
            // uart.write(buffer, 10);
            // sendData(speedUnion.asFloat,directionUnion.asUInt16);

            return true;
        }

        return false;
    }
int main() {    
    UARTCommunication uartCom(P0_10, P0_11, 115200);
    float speed = 0.0;
    uint16_t direction = 0;
    while (1)
    {
        if (uartCom.receiveData(speed, direction)) {
            // uartCom.sendData(speed,direction);
            icarStr.SpeedSet=speed;
            icarStr.ServoPwmSet=direction;
        } 
    }
}

I am exhausted in debugging the code above on the purpose of parsing data from the BufferedSerial (for almost two days :sob: ) .
However,as I tested the code , I encountered a high error package rate (5 times sending, only 1 time correct on average).
Is it normal? maybe the wrong way for coding? Thank you for your help :sob:

Is it possible it could be this issue? STM32 processors cannot receive UART at even moderate baudrates while asleep · Issue #205 · mbed-ce/mbed-os · GitHub

It will cause Rx bytes to be dropped on STM32 processors if they’re received while the MCU is asleep.

Hello,

first, you have variable bytes_read in your code without any usage. From my point of view and experiences this is most important one when you want collect a message from UART. You check first 3 positions of buffer for Validate frame header and length but you have to check how many bytes you received. The problem is the MCU is usually much faster than UART receiving bytes. So you have to repeat read operation until you have complete frame.

Something like below (I do not say it is working but i tried to demonstrate how it should be)

#define  FRAME_SIZE  10    // fill your one, this is just for example
#define  BUFFER_SIZE 10    // fill your one, this is just for example
ssize_t bytes_read = 0;
uint8_t buffer[BUFFER_SIZE] = {0};

bool receiveData(float& speed, uint16_t& direction) {
        if(bytes_read >= FRAME_SIZE ){
			memset(buffer,0,sizeof(buffer));
			bytes_read = 0;
		}

		// this just say "something were received" but it mean buffer size > 0
		// and not "whole msg is in buffer"
        if (uart.readable()) { 
            //ThisThread::sleep_for(1ms);  // Polling interval
			// just address where the read method can continue to write received data
            bytes_read += uart.read(&buffer[bytes_read] ,BUFFER_SIZE); 
        }

        if(bytes_read >= FRAME_SIZE)
          // Validate frame header and length
			if (buffer[0] == 0x42 && buffer[1] == 0x01 && buffer[2] == 10) {
				// Parsing speed
				
				UInt16Union directionUnion;
				FloatUnion speedUnion;
				speedUnion.bytes[0]=buffer[3];
				speedUnion.bytes[1]=buffer[4];
				speedUnion.bytes[2]=buffer[5];
				speedUnion.bytes[3]=buffer[6];
				
				directionUnion.bytes[0]=buffer[7];
				directionUnion.bytes[1]=buffer[8];

				direction = directionUnion.asUInt16;
				speed = speedUnion.asFloat;
				
				unsigned char check=0;
				for (size_t i = 0; i < 9; i++)
					{
						check += buffer[i];
					}
				if (check!=buffer[9]) return false;

				sendData(speed,direction);
				// buffer[9]=check;
				// uart.write(buffer, 10);
				// sendData(speedUnion.asFloat,directionUnion.asUInt16);

				return true;
			}
		}
        return false; // message is not compleane we need another iteration
    }
int main() {    
    UARTCommunication uartCom(P0_10, P0_11, 115200);
    float speed = 0.0;
    uint16_t direction = 0;
    while (1)
    {
        if (uartCom.receiveData(speed, direction)) {
            // uartCom.sendData(speed,direction);
            icarStr.SpeedSet=speed;
            icarStr.ServoPwmSet=direction;
        } 
		ThisThread::sleep_for(1ms);
    }
}

BR, Jan