Serial.input and Flush

What I want to be able to do is to enter the time as separate elements, but its not waiting as it should.
Test Code

char hrs[3];
char mins[3];
void setup()
{
  Serial.begin(57600);
  Serial.println("Serial Connected"); 
  
   // Input time 
  Serial.println("Input time hh");
  Serial.flush();
  while (!Serial.available());  // Stop and Wait for input
  for (byte x= 0; x < 2; x++)
  {
    hrs[x] = Serial.read();
    hrs[3] = 0;   //null char
    delay(10);
  }
   Serial.print("Hours are set to ");
   Serial.println(hrs);
   
   
  Serial.println("Input time mm");
  Serial.flush();
  while (!Serial.available());  // Stop and Wait for input
  for (byte x= 0; x < 2; x++)
  {
    mins[x] = Serial.read();
    mins[3] = 0;   //null char
    delay(10);
  }
   Serial.print("Minutes are set to ");
   Serial.println(mins);
}

void loop(){

  // Do Stuff

}

Thanks.

This is a common problem - you wait for available() to return non zero, then read more than one char.

This cannot work, every char you read must be guarded with a call to available(). Chars come in one by one and much much slower than your code runs.

You can either do this one-by-one:

  for (byte x= 0; x < 2; x++)
  {
    while (!Serial.available())
    {}
    hrs[x] = Serial.read();
    hrs[3] = 0;   //null char
    delay(10);
  }

Or you can wait for enough chars to be available, then read them all:

  while (Serial.available() < 2)  // Stop and Wait for input
  {}
  for (byte x= 0; x < 2; x++)
  {
    hrs[x] = Serial.read();
    hrs[3] = 0;   //null char
    delay(10);
  }

The most elegant solution is to create a function that waits:

char wait_read ()
{
  while (Serial.available () < 1)
  {}
  return Serial.read () ;
}

Then you've abstracted away all the details from you main code:

  for (byte x= 0; x < 2; x++)
  {
    hrs[x] = wait_read();
    hrs[3] = 0;   //null char
    delay(10);
  }

By the way a while statement with an empty loop is really really hard to spot if you use just a semicolon - use braces and its obvious that the while isn't applying to the following code.

Thanks for the examples! :slight_smile:

Maybe I`m misunderstanding the way Serial.flush works..

When you type something into the serial monitor and press return or send, a newline char is added.
So, whats in the buffer is whats been typed plus a newline char.

I would have expected to read x number of chars and discard the rest using the Serial.flush function, but thats not what happens, I read two chars, but using Serial.flush leaves the newline char in the buffer?

So, instead of using Serial.flush, I had to add an extra serial.read (wait_read function in my code)to discard the nl char that is added.

Here`s the test code I have now.
Type in two chars and press send or return.

char hrs[3];
char mins[3];

void setup()
{
  Serial.begin(57600);
  Serial.println("Serial Connected"); 
  
   // Input time 
  Serial.println("Input time hh");
      hrs[3] = 0;   //null char
  for (byte x= 0; x < 2; x++)
  {
    hrs[x] = wait_read();   
    Serial.println("serial read char is ");
    Serial.print(hrs[x],DEC);
    Serial.print("\t");
    Serial.println(hrs[x]); 
  }
   Serial.print("Hours are set to ");  
   Serial.println(hrs); 

  wait_read();         // needed for the nl char received - nl char is discarded
  // Serial.flush();   //  <<=======    Not working as expected, leaves nl char in buffer?
  Serial.println("Input time mm");
      mins[3] = 0;   //null char
  for (byte x= 0; x < 2; x++)
  {
        mins[x] = wait_read();    
    Serial.println("serial read char is ");
    Serial.print(mins[x],DEC);
    Serial.print("\t");
    Serial.println(mins[x]);

  }
   Serial.print("Minutes are set to ");
   Serial.println(mins);
}

void loop()
{
  // Do Stuff
}

// Wait for Serial Input
char wait_read ()
{
  
while(!Serial.available())     
  {  }
  return Serial.read () ;
}

Im using IDE 1.0.1, yes Ive seen the reference, its not a big deal really, as I just add an extra read to deal with nl char.

But, I do like to understand why things don`t work as expected.

In the serial monitor you type 12 and press the enter key or press send.
This means there are three chars in the buffer waiting to be read, ascii 1, 2, and the new line char, the code reads the first two chars, leaving the nl char in the buffer, so I would assume that Serial.flush would have cleared the buffer of the nl char, but it does`nt.

But, I do like to understand why things don`t work as expected.

Usually, because your expectations are wrong.

In the serial monitor you type 12 and press the enter key or press send.

OK.

This means there are three chars in the buffer waiting to be read, ascii 1, 2, and the new line char

That depends on what line ending you have selected in the Serial Monitor. There are three choices. None, CR only, CR and LF. We don't know which you have selected, so we don't know that this is a true statement. There may be 2, 3, or 4 characters sent.

It does not mean that the 2, 3, or 4 characters arrive instantly, either. There WILL be a period of time when there are 0, 1, 2, 3 or as many as 4 characters waiting to be read, depending on when you get around to reading them.

the code reads the first two chars, leaving the nl char in the buffer, so I would assume that Serial.flush would have cleared the buffer of the nl char, but it does`nt.

Of course not. If you are using 1.0.1 as you say, then you need to go back an more carefully read what the flush() method does.

In 1.0 and later, flush() blocks until the outgoing buffer is empty. Is no longer has ANYTHING to do with the incoming buffer.

You MUST read every character. Get over it.

In 1.0 and later, flush() blocks until the outgoing buffer is empty. Is no longer has ANYTHING to do with the incoming buffer.

Ok, this is what I was failing to understand.

You MUST read every character. Get over it.

I am now, thanks for your concern. :wink: