Serial.available(); drives me crazy!

According to the reference Serial.available() should return the number of bytes in the serial buffer.

But, in reality, it behaves really strange. If you try to pass its value to integer variable or you try to check it with switch case statement, it always returns 1, no metter how many bytes are in the buffer.

Now, if you try to print that number, with Serial.print(Serial.available()); than the printout will show true length of the buffer.

Totally weird. Wasted whole afternoon on that.

Does anybody know how can one extract number of bytes in the serial input buffer.

Post an example that shows the problem.

Here is the code. All I am trying to do is to extact the number of characters in the serial buffer. Strangely, Serial.available() prints length, but it always retruns 0 or 1 to a variable.

How can I get the lenght out, not just 0 or 1:

byte bytBufferLength;
int  intBufferLength;
char chrBufferLength;

char  arrCharCommand[5];

void setup() {
  
  // initialize the serial communication:
  Serial.begin(9600);

  Serial.println("Ard.> Ready ..."); Serial.println();
}

void loop() {

  bytBufferLength = Serial.available();
  intBufferLength = Serial.available();
  chrBufferLength = Serial.available();
  
  switch (Serial.available()) {
    
    case 1:

      Serial.print("DEBUG.00: bytBufferLength: "); Serial.println(bytBufferLength, DEC);  
      Serial.print("DEBUG.00: intBufferLength: "); Serial.println(intBufferLength, DEC);
      Serial.print("DEBUG.00: arrBufferLength: "); Serial.println(chrBufferLength, DEC);
      Serial.println();
      
      Serial.print("DEBUG.01: Serial.available(): "); Serial.println(Serial.available(), DEC); 
      // Read the first four bytes from serial buffer:
      arrCharCommand[0] = Serial.read();
      arrCharCommand[1] = Serial.read();
      arrCharCommand[2] = Serial.read();
      arrCharCommand[3] = Serial.read();
      arrCharCommand[4] = '\0';
      Serial.print("DEBUG.02: Serial.available(): "); Serial.println(Serial.available(), DEC);
  
      // Report back to Arduino IDE's Serial Monitor:
      Serial.print("Ard.> arrCharCommand[5]= "); Serial.println(arrCharCommand);
      // Send only four character commands at one time. Characters after
      // the fourth will be flushed out of the serial buffer.
      Serial.print("DEBUG.03: Serial.available(): "); Serial.println(Serial.available(), DEC);
      FlushSerialInput();
      Serial.print("DEBUG.04: Serial.available(): "); Serial.println(Serial.available(), DEC);

      break;
  
    case 0:
      
      break;
      
    default: 

      Serial.print("DEBUG.05: intBufferLength: "); Serial.println(intBufferLength, DEC);
      Serial.print("DEBUG.06: Serial.available(): "); Serial.println(Serial.available(), DEC);
      FlushSerialInput();
      Serial.print("DEBUG.07: Serial.available(): "); Serial.println(Serial.available(), DEC);
  
      Serial.println("Ard.> Command need to be four characters long."); Serial.println();
      
  } // ... switch (intBufferLength)

} // ... loop()


/*
 * FlushSerialInput() - deletes all the characters in the serial output buffer.
 *
 * Serial.flush() substentially changed its use in the later versions of the Arduino's
 * IDE. Before, Serial.flush() was deleting all the characters in the input and output
 * buffer. But, since 0022 or maybe even earlier, Serial.flush() is not deleting
 * characters. It now only forces the remaining characters in the serial output buffer 
 * to go out of the buffer.
 */
void FlushSerialInput() {
  
  while (Serial.available() > 0) Serial.read();
}

DROBNJAK:
Totally weird.

I agree. Hard to believe, in fact. Once the value has been returned back from the function call it is completely independent of the function call, so I can't think of any possible mechanism to produce effects like that. More likely imo there is something else going on to produce the effects you're seeing. I suggest you produce a minimal sketch to show the problem.

Yeah, I've tried an endless number of variations. These are all very rudimentary instructions.

It boils down to the fact that Serial.available() doesn't return length of the serial input buffer. Or it has a bug.

Yes, that's really weird.
Your code, I mean.

The program seems to be doing exactly what you told it to do.
If I type one long line of x into the serial monitor and then type return, this is the output:

Ard.> Ready ...

DEBUG.00: bytBufferLength: 0
DEBUG.00: intBufferLength: 0
DEBUG.00: arrBufferLength: 1

DEBUG.01: Serial.available(): 58
DEBUG.02: Serial.available(): 63
Ard.> arrCharCommand[5]= xxxx
DEBUG.03: Serial.available(): 63
DEBUG.04: Serial.available(): 0

It looks correct to me.
Follow your code through carefully.

Pete

It is not correct.

Serial.available() returns the number of bytes in the serial buffer only if used inside Serial.print() or Serial.println() functions. I need to extract number of bytes in the buffer into an integer variable, to be able to use it inside the code.

if, for example, you typed in 58 'x' characters, than variable intBufferLength should return 58 not 0 or 1.

Serial.available() returns the number of bytes in the serial buffer only if used inside Serial.print() or Serial.println() functions

This doesn't make sense.

Pete

Weird, but true. That is exactly what code demonstrates.

I'll try again and spell it out a bit more.

Serial.available() returns the number of bytes in the serial buffer only if used inside Serial.print() or Serial.println() functions

What do you mean by inside.
And while you're at it, what does Serial.available(), which returns the number of bytes in the input buffer, have to do with .print and .println which are (wait for it) output functions?

Pete

DROBNJAK:
If you try to pass its value to integer variable or you try to check it with switch case statement, it always returns 1, no metter how many bytes are in the buffer.

The following code works using the Arduino 1.0 IDE and a Uno R2 board.

void setup() {
  Serial.begin(9600);
  Serial.println("ready");
}

void loop() {
  int count = Serial.available();
  switch (count) {
    case 0:  Serial.println("0"); break;
    case 1:  Serial.println("1"); break;
    default: Serial.println("d"); break;
  }
}

Those two lines of code, taken from the above code, should produce the same result:

Serial.print("DEBUG.00: intBufferLength: "); Serial.println(intBufferLength, DEC);

Serial.print("DEBUG.01: Serial.available(): "); Serial.println(Serial.available(), DEC);

But first one produces input buffer length of 0, and second one produces input buffer length of 58.

if, for example, you typed in 58 'x' characters, than variable intBufferLength should return 58 not 0 or 1.

This statement is wrong as I have already demonstrated. What you clearly do not understand is that it takes time to transmit those 58 characters to the Arduino (I leave as an exercise for you to figure out how long it is) and during that time the Arduino is executing the loop() function thousands of times.

Now, as I said, you need to sit down with the output and follow your program through very carefully. If you can't figure out how the output happens then it isn't the program that's wrong, it's you.
[edit] Once you accept that you don't understand what is happening, then then you can perhaps ask more meaningful questions.

Pete

OK, OK, the reason I am posting here is for somebody to explain to me how this works?

DROBNJAK:
Those two lines of code, taken from the above code, should produce the same result:

Serial.print("DEBUG.00: intBufferLength: "); Serial.println(intBufferLength, DEC);

Serial.print("DEBUG.01: Serial.available(): "); Serial.println(Serial.available(), DEC);

But first one produces input buffer length of 0, and second one produces input buffer length of 58.

There is nothing in your code that guarantees your statement to be true. It may be true based on how you send data to the board. 'Serial.available()' returns the "current" count of bytes in the buffer. 'intBufferLength' contains the count of bytes in the buffer as of sometime ago.

Ok, I got it. That is useful clue.

Than if I execute ...

Serial.print("DEBUG.00: intBufferLength: "); Serial.println(intBufferLength, DEC);

after:

Serial.print("DEBUG.01: Serial.available(): "); Serial.println(Serial.available(), DEC);

... they should be the same.


That's what I did, and you were right! Thanks.

Is there a way to force Serial input to wait till bytes stop coming in?

Yes keep reading the number of bytes in buffer and when it hasn't changed for a set amount of time then they are all in.

DROBNJAK:
Than if I execute ...

Serial.print("DEBUG.00: intBufferLength: "); Serial.println(intBufferLength, DEC);

after:

Serial.print("DEBUG.01: Serial.available(): "); Serial.println(Serial.available(), DEC);

... they should be the same.

No.

DROBNJAK:
Is there a way to force Serial input to wait till bytes stop coming in?

How can the code stop external devices from sending it bytes? What are you trying to do?

Let's see if I understood the process... I hope to be helpful to you and to me at the same time :slight_smile:

Let's suppose you type 100 'x' characters into serial terminal, then send them all at once. Let's also suppose the baud rate is set to 9600.
Those 100 'x' take a significant (from the Arduino perspective) amount of time to flow from the PC, through the serial line, into the Arduino serial buffer.
While the bytes accumulate into that buffer, you're calling Serial.available() hundreds or thousands of times per second. Therefore each time the value it returns will likely be different from the previous call, depending on how many 'x' have arrived in the meantime.

        0   1   2   3   4   5   6   7
PC ------ x...x...x...x...x...x...x -------> Arduino Serial buffer
        ^   ^   ^   ^   ^   ^   ^   ^

Time flows from left to right.

The numbers represent how many 'x' chars the serial buffer contains.

x = the 'x' characters flowing through the serial line.

^ = Serial.available() calls happening while the serial transmission is going on

If you call serial.available() in the middle of the transmission, you'll get something like 3 or 4. If you wait long enough, instead, you'll get 7. And if no other chars are transmitted, you'll continue to get 7 until you call read() or some other bytes arrive.

I also suspect that calling Serial.available() so often while chars are received can lead to problems related to R/W simultaneous access to state variables inside the Serial class.

HTH

I hope I have written something meaningful. I also hope I got it correctly. Corrections are obviously welcome :slight_smile: