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

  • Thread starter Swamp Thing
  • Start date
  • Tags
    Arduino
  • #1
Swamp Thing
Insights Author
908
572
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
  • #2
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 Swamp Thing
  • #3
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?
 
  • #4
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.
 
  • #5
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.
 
  • #6
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.
 
  • #7
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
 
  • #8
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 FactChecker
  • #9
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 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 Swamp Thing

1. Why does Arduino add an unwanted delay when using Serial.parseInt()?

The unwanted delay you experience when using Serial.parseInt() in Arduino sketches is due to the function's built-in timeout feature. Serial.parseInt() waits for a specified timeout period to ensure that no more numeric characters are incoming through the serial buffer. This timeout is necessary to accurately parse the incoming string into an integer, but it can introduce a delay, especially if the data transmission is halted or slow. By default, the timeout is set to 1000 milliseconds (1 second).

2. How can I reduce the delay caused by Serial.parseInt()?

To reduce the delay caused by Serial.parseInt(), you can decrease the timeout period according to your project's needs. This can be done by using the Serial.setTimeout() function. For example, setting Serial.setTimeout(100); will reduce the timeout to 100 milliseconds. Adjust this value based on the speed and reliability of your data transmission to find a balance between performance and the risk of incorrect parsing.

3. Why does Serial.parseInt() sometimes return a "0"?

Serial.parseInt() returns "0" when it fails to read a valid integer from the serial buffer. This can happen if the data received is not a number, or if there is no data before the timeout occurs. Another common reason is when non-numeric characters are included in the input, which leads Serial.parseInt() to stop parsing and return the default value of 0.

4. How can I check if Serial.parseInt() has actually read a zero or if it's a timeout?

To differentiate between a legitimately parsed zero and a timeout or error result, you can check the serial buffer immediately after calling Serial.parseInt(). If the function times out without receiving any data, the serial buffer will be empty. You can use Serial.available() to check if there are any remaining characters in the buffer. If this returns zero immediately after calling Serial.parseInt(), it likely indicates a timeout or that no numeric input was received.

5. Are there alternative methods to Serial.parseInt() for parsing integers from serial data?

Yes, there are alternative methods to parse integers from serial data which might offer more control or efficiency depending on your application. One common approach is to read the entire string of data using Serial.readString() or Serial.readStringUntil(), and then convert this string to an integer using the function atoi() or the more robust strtol(). These methods allow for more customized error handling and can potentially operate faster since they don't involve a waiting period like Serial.parseInt()'s timeout.

Similar threads

  • Programming and Computer Science
Replies
7
Views
6K
  • Engineering and Comp Sci Homework Help
Replies
9
Views
1K
  • Programming and Computer Science
Replies
1
Views
2K
  • MATLAB, Maple, Mathematica, LaTeX
Replies
1
Views
3K
  • Computing and Technology
Replies
1
Views
6K
  • Programming and Computer Science
Replies
2
Views
12K
  • MATLAB, Maple, Mathematica, LaTeX
Replies
5
Views
5K
  • Programming and Computer Science
Replies
3
Views
10K
Replies
1
Views
3K
Replies
22
Views
2K
Back
Top