Uno - Serial.print() timing causes wrong printing

Problem: Serial printing from loop(), with an if statement to limit number of prints, does not limit as it should. It just keeps on printing, "1212121212...." Code, as last tested

// Bob Larkin 11 Jan 17 
// BUG??  - Prints "12121212..."
// Unless delay is added.  Then prints "12" as expected
// Using both Uno (delay>=1) and Teensy 3.6 (delay>400) with same result.
 
uint16_t n;
void setup()
  {
  Serial.begin(115200);  // For instance
  n=0;
  }

void loop()
 {
 // delay(1);      // <-- OR UN-COMMENT TO FIX PROBLEM
 if(n++ < 2)      // 1, 2, 3, ... doesn't matter
    {
    Serial.println(n);
    }
    //  Or put delay here---same result
 }

This started out as a problem with a big program running on Teensy 3.6, where printing from startup() is problematic, so putting it once into loop() is needed. I reduced the problem to its basics and then tried it on an UNO, where it behaved very much the same. So, it looks more generic than a Teensy problem. Or, if I'm doing something wrong, it is on both devices.

Notes:
The loop should be able to run without a delay, as the Serial.print() should only happen once, or twice as shown above. It would not seem like buffer overload is the issue. A delay of a millisecond prevents the run-on printing in UNO.

Teensy 3.6 with its much faster processor needed almost 400 msec---seems backwards .

The delay can be before or after the if() { print } with the same result.

A delay in startup() had no effect for me.

Slow baud rates had no effect for me.

What is wrong?? Thanks, Bob

Is this repeating forever? Or just a few times.

Without the delay, it repeats forever, so to speak.

boblark:
What is wrong??

Your understanding of the increment operator scope. Separating the increment operator from the if will solve the problem.

boblark:
This started out as a problem with a big program running on Teensy 3.6, where printing from startup() is problematic,

Problematic in what way? Something that while (!Serial); before printing won't fix?

You have n as a unint16_t - a 16bit integer.
So your loop prints 1 and then 2, and then stops printing, but still increments N each loop. After 65534 additional increments, the increment of n overflows, it resets to 0, and it prints it out again. The AVR is fast; those 65534 loops of doing nothing only takes a fraction of a second, so it looks like it's printing continuously. (well, not really. It's obviously printing much slower than a full 115200bps!) If you add the delay(), it will take longer (about 65 seconds), but it will still print over and over again.
I'm not sure exactly what you did on the Teensy; it should print faster with no delay (since it can loop doing nothing faster), but adding a delay() should "equalize" them (both spending much more time in delay() than in the loop.)

SOLVED. Thanks folks. westfw thanks for pointing out the wrap-around. Yes, and that explains why moving the n++ fixes things on the UNO.

On the use of n++, the cleaner way to do a one time operation would be to use a logical variable, more like

bool notDone = true;
void setup() {
 }

void loop() {
 if(notDone) 
    {
    notDone = false;
    // Do something once
    }
 }

That can't wrap around.

On the Teensy, thanks for the hint, oqlbidipo on "while(!Serial);" I was not aware of that fix. In playing with that, it appears it could always be there, and insures that Serial.print is available in startup() or loop(). If one likes macros, something like
#define START115200 Serial.begin(115200); while(!Serial);
will keep them hooked together. In going back to play with some of this stuff on Teensy, I have been seeing strangeness off and on, and "while(!Serial);" fixes all, as best that I can tell.

And, finally, I believe that if(n++ < 2) is valid code, assuming it does what you want.

Thanks again for the help. Bob