Serial.Read and Serial.available difference

Hi

First time creating a topic, so i hope it is in the right categori.

i am writing a project with where i have connected a max485 to the serial port for reading out data from a rs485 bus..

i am a bit confused on what the difference is to these 2 ways of reading and filtering serial data.
Do i need Serial.available when i check if the serial.read is greater than 0 ?

  1. way
char SerialRead_char = (char)Serial1.read();
if ((SerialRead_char > 0) { // do something}
  1. way
if (Serial1.available() > 0)
{
char SerialRead_char = (char)Serial1.read();
if ((SerialRead_char > 0) { // do something}
}

Thanks in advance

Serial.available is used to check if there is anything available to be read.

Serial.read reads the next byte, or returns -1 if there is nothing available.

Normally you would code as follows...

while (Serial.available() > 0)   // Anything to read?
{
  char x = Serial.read();  // Read the next byte available.

  // Do something with x
}

There is nothing really “normal" about this. It’s just the way most examples have been written (probably as it’s easy to understand for beginners “if something is available then deal with it”)

When you program, the reasonable way to do something is to use the less costly function for the task at hand. So the question is why would you calculate the count just to know if it is not zero for then reading one byte?. Just reading it and checking against -1 makes more sense in my opinion.

So in a nutshell:
available() does not remove any byte from the serial buffer and calculates the total count of pending bytes. It uses modulo arithmetic which is kinda costly if you read again afterwards (will do the modulo again).

read() will actually get the first byte out of the serial buffer if there is one available (and If you don’t want to remove the byte from the buffer yet, peek() will do that)

Both actions are possible, I prefer to read() and handle the data if it’s there and use available() if I actually need to know the exact count of bytes in the Serial buffer (eg you want to wait until 4 bytes are available before reading them and dealing with it).
.

Each to their own I guess.

There are always use cases that don't fit. In my experience, there has "normally" been more than one character to read, and that implies a loop.

Not the only consideration... ease of maintenance by following a common design pattern should not be underestimated... it's not all about minimising the number of lines of code.

That does not qualify for a design pattern, it’s just a function call in both cases with different effects.
As I wrote I think the main purpose for using it in examples is for ultra beginners.

Both are fine and easily maintained and it’s more personal preference.

The loop can be done upon checking the result with variations upon

while ((r = Serial.read()) != -1) {
  …
}

You can also handle only one byte and let the loop loops to come get the next byte to give a chance to other parts of your code

Note though that the first post is not suited for handling binary communication as 0xFF could be a valid byte so you don’t want to store the result in a char but really stick to an int.

Like I said... each to their own.

The OP is beginner or wouldn't be asking, but your programming prowess is acknowledged, although pretty bad form to continually update your posts after you've had time to think about it...

The answer, as always is "it depends".

Serial read returns an int for a very good reason - it allows you to distinguish between the case where no data has been received, and the case where the value 255 was received.

Typing from the phone. I don’t think I updated anything critical / changing the point before you answered. Sorry about that

I was just commenting on « Normal » as you see both (as OP noted).

Thanks alot for all the answers, but i am still at bit confused..

does one char equals one byte or does one char need serveral bytes?

i want to handle every char individual and i dont want to empty the buffer before there is one char..

All good my friend.

I should have updated my original post to say "as typically shown in examples" instead of "normally"...

We would agree on that

To OP, no you don’t want to do

if ((SerialRead_char > 0) { // do something}
}

In your second example - hope it’s clear why now

Yes.

A char is a signed integer datatype, and in Arduino (unlike Java) byte is an unsigned integer datatype.
Both are eight bits, and both are capable of representing a single ASCII character (0 to 127)

does one char equals one byte or does one char need serveral bytes?

If you mean char As the data type in C++ then yes most compiler / architectures will use 1 byte (you can read about what the standard says here Fundamental types - cppreference.com)

If you mean a glyph / symbol like an alphabetical character then it depends. The IDE is using UTF8 for representing characters and an ASCII character will fit on one byte but some others like éèàåçč¿ etc that you find in many languages around the world require multiple bytes.

Is not. Whether "char" is signed or not is "Compiler dependent" - with the Arduino compilers, "char" is normally unsigned.

Serial.read() returns an int, though. Not a char. That's what permits -1 to mean "no character."

Either code in the original post looks fine. Serial.available can be used to check whether an expected number of chars have been received:

  if (Serial.available() >= 10) { // wait for expected  "xxx.yy.zz\n"
    x = Serial.parseInt();
    y = Serial.parseInt();
    z = Serial.parseInt();
}

Oops me.

If anyone could let me know which of the Arduino platforms uses unsigned char as the default char, I'd be grateful.

with the Arduino compilers, "char" is normally unsigned.

Actually, I believe I miss-spoke. "char" is normally SIGNED. (just like "int" is normally signed.)

ARM targets seem to default to unsigned, though!

Here's a test program

void setup() {
  Serial.begin(9600);
  while (!Serial);
  delay(5000);
  char c = -1;
  if (c < 0) {
    Serial.println("Char is signed");
  } else {
    Serial.println("Char is unsigned");
  }
}
void loop() {}

You might even get a compile-time warning, depending on whether your board and preferences turn on warnings...

...sketchbook/sketch_feb02a/sketch_feb02a.ino:7:9: warning: comparison is always false due to limited range of data type [-Wtype-limits]
   if (c < 0) {
       ~~^~~

At least ARM, ESP8266, ESP32.

I imagine this is exactly the face the compiler pulls when we make our errors:

1 Like

That is probably why it is so rare to see a "signed char" declaration.