Serial.available() useful?

Hello,

Maybe stupid question but should I use Serial.available() ????

void readDatas()
{
  if (Serial.available() > 0)
  {
      int c = Serial.read();
      Serial.print(c); Serial.print(" ");
      Serial.println((char)c);
  }
}
void readDatas()
{
    int c = Serial.read();
    if (c != -1)
    {
      Serial.print(c); Serial.print(" ");
      Serial.println((char)c);
    }
}

Both program are working !!

If you've used available() correctly the received character should never be -1, so no need to test .

available() gives the number of bytes (characters) available for reading from the serial port

Serial.read() inherits from the Stream utility class. The specification states that it returns as an int the first byte of incoming serial data available or -1 if no data is available.

So if you don't need to know how many bytes are pending, you can use read() and test against -1 before proceeding and if you need to wait (why would be another discussion) for a given number of bytes before doing something then available() is your friend and there for you.

I don't use available() and go for read() right away (or peek()) if I'm listening to the Serial port because it's faster (since available needs to do some maths on the circular buffer pointers with a modulo to calculate how many bytes are pending).

I think you see the construct with available() being tested as non null in most demo script because it's easier to explain to beginners: "if a byte is available in the buffer, then deal with it"... And then everyone started using it...

1 Like

Thanks!

You are using the version with -1 test ?

Yes. Either way works.

You could also use serialEvent():
https://www.arduino.cc/reference/en/language/functions/communication/serial/serialevent/

...on some platforms.

yes testing against -1, with peek() or read() depending if I want to always extract the byte from the Serial buffer or not

Is there a processing overhead with Serial.read() compared with Serial.available()?

I ask because @potzli's second method always calls Serial.read() regardless of whether there's a character in the buffer. If there's a significant overhead to Serial.read() it might (arguably) be better to check first using Serial.available() if that saves time.

Or is the difference too small to consider?

We could look at the AVR sources:

int HardwareSerial::available(void)
{
  return ((unsigned int)(SERIAL_RX_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail)) % SERIAL_RX_BUFFER_SIZE;
}

int HardwareSerial::read(void)
{
  // if the head isn't ahead of the tail, we don't have any characters
  if (_rx_buffer_head == _rx_buffer_tail) {
    return -1;

Looks like .read() does less math but then you have to compare the return value against -1. I don't expect the difference to be as much as a microsecond.

1 Like

But, if I remember, if there is nothing in the buffer, it will be 1.5s, by default, before Serial.read() returns -1. That would be very inconvenient if your code had some other task to perform such as multiplexing a display or scanning buttons.

Also, -1 could be valid data to receive. Maybe not if you are using serial monitor, but if receiving raw binary data from some other source like a python script running on your PC or some sensor, then -1 (= 0b11111111) might be valid data, which your second code would ignore.

not the case... it returns immediately.. the read functions starts with this

if (_rx_buffer_head == _rx_buffer_tail)  return -1;

so basically comparing if the head and tail in the buffer are the same

it's the other way around as I explained in #3. Available needs to do some "complex" maths to provide an answer. if you don't care about the exact count but just want to know if there is something to deal with, then don't call available().

The default 1-second timeout doesn't apply to a simple read(), just to iterative reads like 'readString()', 'readStringUntil()', 'parseInt()', 'parseFloat()'...

1 Like

Ah, thanks @J-M-L @johnwasser I expected the timeout to apply to any read. That would have caught me out at some point! I am a little disappointed that it is not consistent for any function that reads from Serial.

But my second point stands? If receiving raw binary data, -1 could be valid...

that's why read() returns an int and not a byte 0xFFFF versus 0x00FF

2 Likes

Right again! Thanks.

you're welcome. Joy of playing with Streams :wink:

Just don't cross them.
(Unlike ABBA)

I feel there is a pun intended there but I lack probably the reference. (I heard about ABBA tough :wink: )

Ghostbusters (don't) vs. ABBA (I'll)

1 Like