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)
...
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! "));
}
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
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?
... 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
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
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! "));
}
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.