Buffering Bluetooth Serial.read()

Hello

I have a problem receiving data from Android via Serial Bluetooth. Everytime I assign BluetoothSerial.read() to buffer, the read bytes are broken, mostly 0 or 225. But if I run Serial.println(buffer[index]) after BluetoothSerial.read(), it read bytes perfectly.

Here is my code:

byte buffer[64];
byte header;
byte length;

// I need at least 2 bytes to read otherwise the message assumed to be broken
if (bt.available() > 1) {  
   header = bt.read();
   length = bt.read();

   for (byte i = 0; i < length; i++) {
      buffer[i] = bt.read();
      // The buffer will be assign properly if I add 
      // Serial.println(buffer[i]);
      // Otherwise, the buffer will be broken, mostly 0 or 225
   }
}

// Process received bytes goes here

Can anyone explain why this happens? I’m using Arduino Uno R3 and Bluetooth Module HC-05 running at baudrate 115200

You say "I need at least 2 bytes to read" but then you actually read more than 2 without checking if they are available.

Try the examples in serial input basics.

...R

To further what Robin2 said... The reason that things "appear" to work when you echo each byte read is that doing so takes time, which allows another character to sneak in, while you are printing the last one. With spending that time, you are reading data faster than it can arrive.

Robin2:
You say “I need at least 2 bytes to read” but then you actually read more than 2 without checking if they are available.

Try the examples in serial input basics.

…R

Sorry, I guess I should say the minimum bytes of messages must be 2 bytes. It is okay if it has more. I will read it later. Thank you for the post :slight_smile:

PaulS:
To further what Robin2 said… The reason that things “appear” to work when you echo each byte read is that doing so takes time, which allows another character to sneak in, while you are printing the last one. With spending that time, you are reading data faster than it can arrive.

I agree with you. I don’t want to echo buffer because it waste time. But if I don’t echo it, the data will corrupt. The buffer will consist of 0 and 255 and I can’t process commands. For example, I expect my buffer to be [0,1,49,2]. What happens when I process buffer is [255,255,0,255]

So far my solution is echo header and length without echo the buffer. The data is not broken at all and I can process the buffer.

   header = bt.read();
   length = bt.read();

   Serial.println(header);
   Serial.println(length);

   for (byte i = 0; i < length; i++) {
      buffer[i] = bt.read();
   
   }

It is still interesting because if I don’t echo header and length, the buffer will corrupt again/didn’t expected.

But you still read characters even if you don't know they arrived in the serial port or not. bt.read() will return the oldest character from the input buffer, and remove it. If there is no character in the input buffer, it won't return something useful. So you have to wait for those characters to arrive, before attempting to read them.

guix: If there is no character in the input buffer, it won't return something useful.

It does return something useful: it returns -1 to indicate an empty buffer.

saggafarsyad: Sorry, I guess I should say the minimum bytes of messages must be 2 bytes. It is okay if it has more.

You are missing the point. You are thinking about the matter as a human, not as a computer.

In a computer program you should never read more bytes than you know are already available. Consequently if (Serial.available > 1) { only gives you authority to read 2 bytes

...R