Arduino: Unwanted delay & "0" after Serial.parseInt

  • Thread starter Thread starter Swamp Thing
  • Start date Start date
  • Tags Tags
    Arduino
Click For Summary
SUMMARY

The forum discussion addresses an issue with an Arduino sketch that experiences an unwanted delay and an extra "0" output when using the Serial.parseInt() function. The problem arises due to the default timeout behavior of Serial.parseInt(), which returns 0 when no valid digits are read within a specified time. A solution is provided by modifying the code to use Serial.readStringUntil('\r') instead of blocking the loop with while(Serial.available()==0), effectively eliminating the delay and the extra "0". This adjustment allows for more efficient input handling and is particularly beneficial for future interactions with Python.

PREREQUISITES
  • Understanding of Arduino programming and syntax
  • Familiarity with Serial communication in Arduino
  • Knowledge of the Serial.parseInt() function and its timeout behavior
  • Basic experience with input handling in programming
NEXT STEPS
  • Learn about Serial.readStringUntil() in Arduino for improved input handling
  • Explore the configuration of Serial.setTimeout() to customize timeout behavior
  • Investigate efficient data exchange between Arduino and Python
  • Study best practices for non-blocking code in Arduino sketches
USEFUL FOR

Arduino developers, hobbyists working on serial communication projects, and anyone looking to optimize input handling in Arduino sketches.

Swamp Thing
Insights Author
Messages
1,047
Reaction score
780
This Arduino sketch is supposed to wait for a number and then print it back with a message. But for some reason its gets an extra "0" from the TTY each time I actually type a number. There is about half second delay before the "0" is responded to.
Code:
int num;
void setup() {
  // put your setup code here, to run once:
Serial.begin(115200);
}

void loop() {
Serial.print("Enter a number: ");
while(Serial.available()==0){}
num=Serial.parseInt();
//Serial.parseInt();           //    <----  Tried reading and discarding the "0". Well, that works -- but the delay remains.
Serial.println(num);
Serial.print("Your number is: ");
Serial.println(num);
Serial.println("=====\n");
}

Here is what happens in the TTY:
Code:
Your number is: 1
=====

Enter a number: 0
Your number is: 0
=====

Enter a number: 22
Your number is: 22
=====

Enter a number: 0
Your number is: 0
=====

Enter a number:

I can read and discard the "0" as per the commented line #11 --- but that doesn't remove the small delay.

How can I get rid of the extra delay?
 
Last edited:
Technology news on Phys.org
I think it has to do with this:
https://www.arduino.cc/reference/en/language/functions/communication/serial/parseint/ said:
  • Parsing stops when no characters have been read for a configurable time-out value, or a non-digit is read;
  • If no valid digits were read when the time-out (see Serial.setTimeout()) occurs, 0 is returned;
I'm not familiar with Arduino, but while(Serial.available()==0){} seems to be a weird statement. An if(Serial.available()>0) seems to be more appropriate somewhere inside a loop.
 
  • Like
Likes   Reactions: Swamp Thing
I'm not familiar with Arduino Serial.available. Do you enter a carriage return after the number and is it handling a carriage return as you expect?
 
If I put a LF, CR, or CR+LF or even any non-numeric like "Q" at the end, then the response is immediate ("Your number is 125"). This is followed by a delay before prompting for the next input. The "0" thing does not happen in this case. So it doesn't seem to care whether the number is terminated by a CR, CRLF or something else -- it just responds to the numeric part BUT delays the prompt for the next number. This would be the acceptable option if the delay didn't matter. But I will be having Python talking to the Arduino at some stage, and the delays wouldn't be nice then.

If I don't put any terminating character, the delay happens before the response. After the required response it asks for the next input right away, gets a "0" and responds to that, and finally asks for the next actual input. This would also be somewhat acceptable for manual interaction if we added the read-and-discard line, but not so good for programmatic data exchange.

I think I will try inputting the number as a string and then converting it to integer. I will post back later how this works out.
 
If the input device is an actual TTY (TeleType machine), try cleaning the commutator (serializer) in it. Also check for dirty or intermittents in the connecting cables between there and the computer.
 
It's just a virtual TTY window within the Arduino IDE :smile:

Maybe TTY is a misnomer here, my bad.

The connection is actually via USB and gets converted to plain vanilla serial lines in an IC on the Arduino PCB.
 
OK. I would suspect the extra Zero may be sent by the transmitting device then, perhaps as an End-Of-Message character. Is there any way of checking; perhaps in assembly language?

Cheers,
Tom
 
Just found these lessons -- maybe the right method is explained here. I'll update after watching and trying his tips.

Using an Arduino with Python LESSON 1: Introduction, Prerequisites and Class Gear​


 
  • Like
Likes   Reactions: FactChecker
Based on the video...
The key point is to use Serial.readStringUntil('\r') which waits for a CR.
jack action said:
but while(Serial.available()==0){} seems to be a weird statement. An if(Serial.available()>0) seems to be more appropriate somewhere inside a loop.
The video also uses while which is funny, given that's it's already within a polling loop.
Based on jack action's suggestion I changed it to an if.

So this is the code that works nicely without the delay and the "0" thing...
Code:
String cmd;

void setup() {
  // put your setup code here, to run once:
Serial.begin(115200);
pinMode(13,OUTPUT);
Serial.println("Waiting for Input...");

}

void loop() {
  // put your main code here, to run repeatedly:

//while(Serial.available()==0){}   // blocks the polling loop --- bad!
if(Serial.available())        // won't block the loop (thanks, jack action!)
{

    cmd=Serial.readStringUntil('\r');
    Serial.println(cmd);
    if(cmd=="ON")
        {digitalWrite(13,HIGH);}
    else
        {digitalWrite(13,LOW);};

}
 
  • Like
Likes   Reactions: jack action and FactChecker
  • #10
The parseInt() function has a timeout (which can be set). I guess it defaults to about half a second. When you enter a number and hit return you send a number plus some sort of line termination, probably CRLF. The parseInt() function handles the number part fine and then chokes for half a second on the non-numeric part.

You can kludge by adding this code right after the parseInt() call:

Code:
while (Serial.available()) Serial.read();

That will work okay as long as you are just a human typing at human speed. But a better method would be to read the characters into a buffer using Serial.read() and then parse the buffer.

Then again, for a simple sketch it's often the case that a quick and dirty solution actually is better since it will save you a lot of time. But it might be instructive to learn to do it the "proper" way.

Good luck!
 
  • Like
Likes   Reactions: Swamp Thing

Similar threads

  • · Replies 7 ·
Replies
7
Views
7K
  • · Replies 9 ·
Replies
9
Views
2K
  • · Replies 1 ·
Replies
1
Views
3K
  • · Replies 1 ·
Replies
1
Views
4K
  • · Replies 1 ·
Replies
1
Views
7K
  • · Replies 5 ·
Replies
5
Views
6K
  • · Replies 2 ·
Replies
2
Views
12K
  • · Replies 1 ·
Replies
1
Views
3K
  • · Replies 3 ·
Replies
3
Views
10K
  • · Replies 1 ·
Replies
1
Views
3K