Serial Doesn't Wait on Input

fritest.ino (804 Bytes)

Not a frequent user here so possibly missed something in the documents. I am doing serial i/o which works a lot of the time but the particular combination in the attachment does not.
when I run it the first statement waits on input (Serial.available() ) just fine. But as the code proceeds the second statement just moves on thru and does not wait on data.
I have attempted to clear the buffer of ANY characters in the subroutine call. Not sure what I am missing here.

Any ideas appreciated
thanks
Fritz

Can you please post the code inline, I can't open attachments at the moment.

Sure--Sorry-
I reduced the code to its simplest elements-
fs

int spd;
int ext;
char stpsize[100];
int sizparm;
char stpdir[100];
int dirparm;

void setup() {
Serial.begin(9600); // set up Serial library at 9600 bps
Serial.println("TEST\r\n\r\n");
}

void serclear()
{ //clear out old bytes in buffer
char wrk[1];
while(Serial.available() != 0)
{
Serial.readBytes(wrk,1);
} //endfor
} //end serclear

void loop(){

serclear();
Serial.println("Enter Direction (F,f or B,b)");
while (Serial.available() == 0);
Serial.readBytes(stpdir,1);
if(stpdir[0] == 'F' || stpdir[0] == 'f')
{dirparm = 1;}
else
{dirparm=2;}

serclear();
Serial.println("Enter Speed (1-100)");
while (Serial.available() == 0);
spd = Serial.parseInt(SKIP_ALL);

} //end loop

I have attempted to clear the buffer of ANY characters in the subroutine call. Not sure what I am missing here.

You have attempted to second guess timing on a asynchronous protocol and likely got it wrong… the data might still have been incoming

I would suggest to study Serial Input Basics to handle this

In view of the fact that I don't often use arduinos, I am not sure if they handle the signal timing in their routines. Apparently not.
I didn't see anything in the code in the doc that you sent regarding timing (they do say it is 'slow').

Regardless I put a 2 second delay (overkill) in the buffer flush and still have the same problem so--probably not in the async timing..

Thanks
Fritz

Post your latest code.

Your serclear() function empties what currently is in the serial buffer but there might be incoming characters that have not made it to the arduino. It’s not that arduino is slow, it’s 9600 bauds that is and you would be in a better position if you had an end marker to wait for or a timeout

Really, study the serial input basics tutorial that @J-M-L linked. It will help you, it sure helped me.

here--with a couple of delays-it does not work.

int spd;
int ext;
char stpsize[100];
int sizparm;
char stpdir[100];
int dirparm;

void setup() {
Serial.begin(9600); // set up Serial library at 9600 bps
Serial.println("TEST\r\n\r\n");
}

void serclear()
{ //clear out old bytes in buffer
char wrk[1];
while(Serial.available() != 0)
{
Serial.readBytes(wrk,1);
} //endfor
delay(1000);
} //end serclear

void loop(){

serclear();
Serial.println("Enter Direction (F,f or B,b)");
while (Serial.available() == 0);
Serial.readBytes(stpdir,1);
if(stpdir[0] == 'F' || stpdir[0] == 'f')
{dirparm = 1;}
else
{dirparm=2;}

serclear();
Serial.println("Enter Speed (1-100)");
while (Serial.available() == 0);
delay(1000);
spd = Serial.parseInt(SKIP_ALL);

} //end loop

It's exactly as J-M-L said. There are characters inflight I suspect. Likely CR and LF.

Fungus--Nothing about sig timing that I can see in the doc. They mention a C snippet almost identical to mine for flushing the buffer but that is all I can see.

Can you be more explicit about where in the doc this issue is addressed?

thanks
fritz

OK---now I see. There apparently is refuse in the write buffers-so I added a 100ms timer to my buffer clear and put it AFTER the writes. And it all works. (Probably would help if the subroutine code was published but I can't find it).

Thanks all for your help!
Fritz

int spd;
int ext;
char stpsize[100];
int sizparm;
char stpdir[100];
int dirparm;

void setup() {
Serial.begin(9600); // set up Serial library at 9600 bps
Serial.println("TEST\r\n\r\n");
}

void serclear()
{ //clear out old bytes in buffer
char wrk[1];
delay(100); //arduino vendor routines don't clear buffers
while(Serial.available() != 0)
{
Serial.readBytes(wrk,1);
} //endfor
delay(1000);
} //end serclear

void loop(){
Serial.println("Enter Direction (F,f or B,b)");
serclear();
while (Serial.available() == 0);
Serial.readBytes(stpdir,1);
if(stpdir[0] == 'F' || stpdir[0] == 'f')
{dirparm = 1;}
else
{dirparm=2;}

Serial.println("Enter Speed (1-100)");
serclear();
while (Serial.available() == 0);     
spd = Serial.parseInt(SKIP_ALL);

} //end loop

All of it is due to is the glacial baud rate and your serial monitor line ending setting. You read one character but there are one or two more on the way.

Each one takes one millisecond, which is plenty of time for your clear routine to check for characters, find none and stop looking. Thus, you end up with unexpected stuff in the input buffer.

Yep-its all about signal timing -- I guess I thought the Arduino would have cared for some of this. Their doc is rather terse-but all told a nice product that I am not too familiar with.

I usually code interrupt mode serial and often with machines talking to each other but in those cases I am writing more fundamental code and have closer access on what is happening.

Thanks for your help
Fritz

Unfortunately Serial Basics does not do input flush() correctly.
As noted in previous posts you can have chars on the fly. The code example in Serial Basics, like your code, ignores these
Look the detailed example sketches in my Arduino Software Solutions for various ways to read from Serial with the pros and cons of each.
There are a couple of sketches there that correctly clear out the input including on the fly chars.

baloney … another selfish attempt…

Robin’s code for flushing does exactly what it says it does, : it empties the Serial input buffer. There was no other promise done.

If you interpret things, You don’t flush correctly either, you have a canned 1s timeout and you have no clue what’s sending the information on the other side. You could still have incoming data that has not been emitted yet or a noisy line… So any bet is as good as any other. Blindly flushing the input is also a risk of getting rid of one meaningful input.

The way to deal with input is to have a documented protocol that lets you get in sync with the sender and reject malformed input. The parser should deal with this. For example You read until the end marker and you look for coherence (use a CRC, assess if all the fields are there, are of meaningful values, check length, etc…) or If you have both a start and end marker then use also that to get in sync.

The knowledge of the case at hand and understanding of how the buffering works is what developers need to have. That’s exactly what Robin’s tutorial conveys. At the end of the day the A in UART , stands for Asynchronous (Universal Asynchronous Receiver Transmitter), trying to second guess a timing for something asynchronous is a recipe for failure, you need to add a way to get in sync + verify input coherence depending on your application.

In my. Opinion That’s why there is no input flushing method to the Serial class, there is nothing generic that can guarantee to work in all possible scenarios.

1 Like

You comment says it all. Data might still be coming.
Serial Basics' 'flush' of the RX buffer does not handle this. It might do what it says but it does not do what is needed to clear the data the might still be coming

The OP was already trying to use Serial Basics inadequate version of flushing and has been told, by you and other posters, that it is not enough,

You need to keep reading until the data stops coming to completely 'flush' the input.
You can adjust the timeout to suit the sender.
The usual case is a series of print's one after another so 1 sec seems fine to me.
Arduino Serial timed reads use that time as the 'end of data' indicator.

Particularly when dealing with user input from the IDE, waiting for the data to stop coming is simple and ideal way to 'sync'.

0s is as good as a choice as 1s because it’s all specifics related. Robins tutorial does not say it will boil coffee for you too. It just says it will empty whatever was already there and it does.

Reality is that you have no way of knowing when it stops because you don’t know for sure what’s on the other side of the serial line. I luckily still have my dad and he is typing very slowly and many serial input terminals will send data as you type, not submit in one go as in the IDE. So 1s would not cut it for him if that was used as an end marker.

A robust code will do what’s appropriate, provide UI feedback on what it received, allow for editing etc.

That’s why it’s important for anyone interested in writing code to read an introduction tutorial on the basics. Once you get that and the associated techniques and more (like using millis for non blocking code) then you can write code like you are offering, with the intimate knowledge of how it works and why you did it that way.

Acquiring knowledge is important, or as I said earlier, you can also shut your brain off and use bloated libraries and functions without understanding what they do or why. It is fine too, depends on the goal.

Non-blocking "getline()":

My flush() code with 1sec timeout, works well for me, particularly when reading from IDE monitor.

A telnet input is another issue, but have so far not seen that form of Serial device in the questions posted on this forum, so not very relevant.