I'm working on an application for which milliseconds may matter. I would like to be able to get control inputs over the Serial connection, so the timing associated with Serial.parseInt() is important. I ran into the issue that there are awkward delays due to the use of this function, which other users have experienced. That thread, however, did not have a coherent answer. So here is what I found after testing with the following sketch:
long a;
char c;
void setup() {
Serial.begin(19200);
Serial.setTimeout(5000);
}
void loop() {
if (Serial.available()) {
a = Serial.parseInt();
if (Serial.available()){
c = Serial.read(); //clear the buffer
}
Serial.print("I heard: ");
Serial.println(a);
}
}
So, as per documentation, Serial.parseInt() either waits until Serial.setTimeout() runs out (which is set intentionally high in my example), or a non-digit character is encountered. It also ignores everything from the start of the buffer until it finds either a digit or a minus sign.
The key point is that when it encounters a non-digit character, it does not clear it from the buffer.
So if there are digits, but no terminating character, it waits until time runs out. Then returns the number. If there is a terminating character, parseInt() waits until time runs out, then returns zero (which means no number was found).
Therefore, if there is a terminating character, it will stay in the buffer. On the next iteration, parseInt() finds it, then waits forever since the buffer is empty and nothing else is coming.
The solution is to read a single character out of the buffer. In my code, this is accomplished using the if statement block.
System behavior in various cases is below. In all cases, the input is "56,78".
- No terminating character, no buffer clearing: 56, (long pause), 78
- Terminating character, no buffer clearing: 56, 78, (long pause), 0
- No terminating character, with buffer clearing: 56, (long pause), 78
- Terminating character, with buffer clearing: 56, 78
The last combination produces no unnecessary pauses and no extra numbers. Note that multiple trailing non-digit characters will still screw it up, causing pauses and returning a zero.
Setting the timeout to be very short (1, for example) can cause a single number to be split up.
Hopefully this is clear and helpful for those confounded by this behavior, as I was.