0

Examples online always show this code to read bytes from the serial interface:

while(serial.available() > 0)
{
      char receivedByte = serial.read();
}

But I don't understand why it works.

The read() operation "removes" a single byte from the queue, so the while loop should consume all the bytes from the queue.

However, what guarantees that the incoming bytes are being pushed into the queue faster than the consuming process? I would imagine that any Arduino board is order of magnitude faster than a standard serial transmission, so it would starve the queue and effectively exit the while loop even though there are more incoming bytes to process. What am I missing here?

3
  • 1
    You're right. It depends on what else is done in the while block. BTW: byte is a data type in the Arduino environment, better don't use it as a variable name. Commented Dec 10, 2023 at 15:36
  • @DataFiddler fixed Commented Dec 10, 2023 at 16:18
  • an if block would make more sense than a while block
    – jsotola
    Commented Dec 10, 2023 at 19:05

2 Answers 2

4

what guarantees that the incoming bytes are being pushed into the queue faster than the consuming process?

Nothing. In the code handling the transmitted data you need to account for that. The fact, that serial transmission is not as fast as the code runs, doesn't matter, when you regularly check execute that while loop again (on each iteration of a non-blocking loop() for example). The code shouldn't rely on a full message being received inside that while loop. The data is normally saved into its own buffer and only processed, when a full valid message is in there (which can be checked by using a delimiter byte at the end of each message). So this makes more sense in the context of the rest of the corresponding serial code.

Though you should always keep in mind, that there are many many codes for Arduino online and that many of them are not that good.

2
  • That's the answer I was hoping for. Some sloppy implementations use a small delay(x); inside the loop to guarantee that at least 1 new byte is present when re-checking the while condition. The x depends on the baud rate. Reading piece by piece over the main loop() makes sense, but then one has to guarantee that the overall loop() execution time does not exceed the time required to fill up the serial queue, otherwise bytes would be lost. Isn't it ? Commented Dec 10, 2023 at 16:13
  • Yes, in that case loop() should be non-blocking. Though this is recommended either way, because it enables you to do multiple things simultaneously, basically multitasking, and keeping everything responsive.
    – chrisl
    Commented Dec 10, 2023 at 16:21
1

Examples online always show this code ...

 while(serial.available() > 0)
 {
       char receivedByte = serial.read();
 }

You wouldn't have seen this "always" because it is Serial and not serial.

Also the code you posted would be useless because it would repeatedly read into the same byte and do nothing with it.

Assuming you are taking a bit of a licence with what you actually saw, it would be better for the code to gradually fill a buffer (and check for overflow) and then when a newline or other delimiter arrives, do something with it.

You are right that you would, generally speaking, read faster than data arrives. You are also right that putting delays in is a silly way of trying to allow for that.

I have an answer on this site plus a page with suggested code which goes into more detail.

Those posts might help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.