Stopping Input buffering from skipping over Serial.read() commands WITHOUT setting the Serial Monitor to "No new Lines"

It...

it follows me everywhere

It lurks in the Shadows to mask its presence

Anytime I think I killed it for good, it always comes back

Anytime I think I ran far enough away from it, it always finds its way back to me

My personal troubleshooting demon: Char input buffers.


Anyways, it's time for the probably daily "Help input buffering took my wife and children" post! I'm trying to squash an input buffer bug so my crap code can chug along just for a few more seconds. I don't have an Arduino (using emulators), so I sadly can't activate the no new lines part of the Serial monitor. I've tried every variation of this I can think of:

while (! Serial.available()) {
Serial.read(); // here to try to eat the buffers before they come
}
Actual code down here, and I've already tried vice versa. 
Also tried if instead of while statements

But it still is buffering worse than a youtube video in 2007. Any other ideas? Might not reply for a bit because I'm tired after troubleshooting this dumb bug for the 3rd time in the 3rd different language I semi-know for the 3rd time in a row (I've had a mental breakdown for the last week or so)

Show us all your code… it sounds like your just not handling the received data very efficiently.

What’s sending the serial stream? What sort of payload ?

what emulator are you using?

why posting now then? I might spend time here when you are ready to provide answers

General comments:

  • why do you just empty the Serial buffer without doing anything with the data? just leave it alone...
  • I would suggest to study Serial Input Basics and stick at this until you get it.

...
fair
I'll show you the parts that matter (most of it is just code to control motors)

Code:
void askUser() {
  String Input;
 char charInput;
  bool leave = false;
  Serial.println(F("Which one do you want-- centimeters or inches? \nI only need the first letter of what you choose."));
  while (leave == false) {
    if (Serial.available()) {
      charInput = Serial.read();
/*
Input = Serial.read();      
Input.remove(1 , Input.length() - 1); //Set @ 1 on purpose; trying to isolate the first letter of string

It does indeed isolate it to one char, but it converts it into a 
string of #s that's definitely not translated to ASCII code. Still 
have no idea why, and I tried other things like .toCharArray()  to
still no avail, thus it was commented

      switch (Input[0]) {  
*/
        switch(charInput) {
         case 'i':
          Serial.println("You selected inches!");
          inches = true;
          leave = true;
          Serial.flush();
          break;
        case 'I':
          Serial.println("You selected inches!");
          inches = true;
          leave = true;
          Serial.flush();
          break;
        case 'c':
          Serial.println("You selected centimeters!");
          inches = false;
          leave = true;
          Serial.flush();
          break;
        case 'C':
          Serial.println("You selected centimeters!");
          inches = false;
          leave = true;
          Serial.flush();
          break;
      	
      	default:
          Serial.println(String("uhhhh... idk what '") + Input + String("' is. Try again for me: "));
          delay(1000);
        break;
      }
    }
  }
  askMinimum();
}
//This is where the code starts to screw up:
void askMinimum() {
  String bait;
  Serial.println(F("With that out of the way, please input how far the robot should be from a wall before it freaks out."));
  Serial.println(F("Input any number here (decimals are welcome!): "));
  while (Serial.available() < 0) {
    bait = Serial.read(); //Tying to cycle through any unused input data, but nothing happens
  }
  minimum = Serial.read();
  Serial.println(F("Ok, You're all set! "));
}

Arduino Uno w/ 9600 set as the listening channel

While nothing is there, read and discard the non-existent byte.

Sounds pretty unclever to me.

Made code in the Arduino web editor, then tested mostly on TinkerCAD's built-in editor. Also used Wokwi to confirm that this is because of my crap code:


Because I have a negative IQ + it was very late


The code is in another comment that I replied to if you want to see that atrocity

:wink:

(IQ is an unsigned byte so can't go negative :slight_smile: )

➜ well if really nothing is available (< 0) then try to read won't get you far...

I would really suggest to study Serial Input Basics to handle this

Question: do you expect the user to type enter at the end of the command (like in using the Serial monitor) or are you using a serial monitor that will send the bytes as you type them?

My brain when writing this piece of code:

The former. The user Will type stuff through the monitor, their choices get sent to the uno, and they can unplug it and see what happens next

... Not me thinking that Serial.available() returns a negative until it's ready to receive another input. Yeah, give me a sec, and I'll try changing some stuff around

if you want to do this in a blocking way, and you are really keen on using the String class, then using Serial.readStringUntil() would make your life easy

try something like this

(it would NOT be the recommended approach)

Assuming I did this right after checking the guide, the buffer barricade did not hold up

Ran this:

void askMinimum() {
  String bait;
  Serial.println(F("With that out of the way, please input how far the robot should be from a wall before it freaks out."));
  Serial.println(F("Input any number here (decimals are welcome!): "));
    while (Serial.available() > 0) {
   //Tried this line too: bait = Serial.read();      
minimum = Serial.read();
      Serial.println(F("Ok, You're all set! "));
    }  
}

And this:

oid askMinimum() {
  String bait;
  Serial.println(F("With that out of the way, please input how far the robot should be from a wall before it freaks out."));
  Serial.println(F("Input any number here (decimals are welcome!): "));
  while (Serial.available() > 0) {
    Serial.read(); // Also tried: bait = Serial.read();
  }
minimum = Serial.read();
Serial.println(F("Ok, You're all set! "));
}

Along with my other code, and it still skipped over the 2nd Serial read. Hopefully, sleep deprived me just made a dumb mistake somewhere

A couple of comments:

Do you have the serial monitor set for "No line ending"? If not, the code needs to handle the carriage return and/or linefeed characters properly.

Serial.flush() has no effect on the receive buffer, it's only function is to wait for all the data in the send buffer to be sent.

If you are having problems with the receive buffer overflowing, or a slow response time after sending something from the serial monitor, you are likely spending too much time in other parts of the code.

Do not expect to receive characters on serial immediately after printing to serial, even at 115200 baud it takes a long time to actually send the text then get a reply.

Try this, it should be a little more stable, but still is likely to not work properly if the user types extraneous characters into the serial monitor.
You need to first make sure all the previous data is out of the receive buffer, then after printing the prompt wait for a character to be received. This doesn't account for any characters that are still in the process of being transmitted from the serial monitor, which may arrive while you are printing to serial.

void askMinimum() {
  while (Serial.available() > 0){
    Serial.read(); //empty the receive buffer
  }
  Serial.println(F("With that out of the way, please input how far the robot should be from a wall before it freaks out."));
  Serial.println(F("Input any number here (decimals are welcome!): "));
  while (Serial.available() == 0); //wait for character to be received
  minimum = Serial.read();
  Serial.println(F("Ok, You're all set! "));
}

nvm stupid question

Definitely helped a crapton with the problem, but as you predicted, if I try to type out something like centimeters the problem comes back like in full throttle. What I might do is Frankenstein parts of this + Serial.readSrtingUntil() and if that doesn't work, I'll bodyblock ppl from typing more than 1 or 2 characters.

Serial.flush is named terribly. I'll take those out or put them somewhere else

I gave you a code to try in post 13, did you test it?