While loop gotcha got me - can someone pls explain?

This was a head scratcher for me….

I’ve seen in many code examples while(1) used as a way of halting code execution. Ok, I uderstand it only looks like that, in fact it’s whizzing round and round re-evaluating the truth of 1, finding it to be true and will do forever more. Great.

In a few sketches I’ve written (and seen in other people’s), this code:

while (digitalRead(buttonPin) != 0)

(with the way I’ve wired the button) just keeps looping until the button is no longer pressed. All fine and dandy.

So I wanted the code to give an opportunity for a button to be pressed and, if not, processing was to continue after a 15 second delay:

long dispStart;
:
:
dispStart = millis();

while ((digitalRead(buttonPin) == 0) && ((millis() - dispStart) < 15000)) // auto continue after 15s

But no! It doesn’t auto continue after 15 seconds. I scratched my head, drank a cup of tea, scratched my head some more, and then I tried what I thought was daft, adding a null statement: {} like this:

long dispStart;
:
:
dispStart = millis();

while ((digitalRead(buttonPin) == 0) && ((millis() - dispStart) < 15000)){} // auto continue after 15s

and it worked! Wait, what??

Would someone care to explain the whys and wherefores, please?

Hopefully this post will prevent others going through the same brain-pain that I went through ;)

The condition will only be true if the button is pressed and 15 seconds have elapsed

I think you want the condition to be true if the button is pressed or 15 seconds have elapsed

This is the syntax for the while loop:

https://docs.arduino.cc/language-reference/en/structure/control-structure/while/

As you can see, the braces are part of the syntax. However, it is also possible to omit the braces if the body of the loop is only a single statement. Without a semicolon ; at the end of the line, the statement on the next line would have been treated as the loop statement. Braces open and close a compound statement (a statement comprising of a group of statements). Using ,{} signifies an empty loop that does nothing.

Thanks for chipping in, @UKHeliBob…. but no, what you say isn’t right:

When buttonPin is at 0, it’s NOT being pressed, so if the statement was

while(digitalRead(buttonPin) == 0)

it would loop forever with no button press. With this instead:

while((millis() - dispStart) < 15000))

it would loop for 15 seconds before continuing. With

while ((digitalRead(buttonPin) == 0) && ((millis() - dispStart) < 15000))

then while both are true, it’ll keep on looping. If one goes false it’ll continue past the while loop ie only with a button press or 15 seconds having elapsed, will it continue.

All of the above is one reason why I need to infuse tea into my bod to help with my thinking.

…but it still needed the {} to be added to work!

Aaah, the light of understanding now dawns - thanks so much for pointing it out, @BitSeeker :D

OK. I had misunderstood how the button was wired

It sounds like the problem is solved

Most of the times buttons are wired to a pin with INPUT_PULLUP enabled and so the reading becomes LOW (better than using 0) when pressed - not HIGH

Hence the confusion. Posting a full sketch as a minimal example would have cleared that’.

You can

const auto PRESSED = HIGH:

and later

  if (digitalRead(buttonPin) == PRESSED) { ... 

// or

  if (digitalRead(buttonPin) != PRESSED) {

to unconfuse readers, meet the API where it wants to be met and leave just one place in your code to adjust if you change your mind about how you wire your buttons.

For reasons it is common for ppl to use pulled up switches, and LOW for closed (pressed (conducting)).

a7

…which is why I said about the way I wired the button

I take your point about using LOW and HIGH :slight_smile:

Great tip, thanks @alto777 :smiley: