Why does the LED turn on after the while loop becomes false?

I don't understand why the LED won't blink until I let go of the button, (making the while loop false.) Would it not continue to blink the LED until the while loop becomes false?

void setup(){
  pinMode(13,OUTPUT);
  pinMode(3, INPUT_PULLUP);                      //Not required
}

void loop(){

  if(digitalRead(3)== 0)
  {
    while(digitalRead(3) == 0);
    digitalWrite(13, HIGH);
    delay(1000);
    digitalWrite(13, LOW);
    delay (1000);

    digitalWrite(13, HIGH);
    delay(1000);
    digitalWrite(13, LOW);
    delay (1000);
  
  }
}

the ";" at the end of the line is the while loop body which will be executed while the pin is LOW.

i don't think you need the while loop

I see. I'm just trying to understand other people's code so I can implement their pieces into mine.

I think I understand it now though...
The while loop will continue to check the button's value once it is low. But when you let go to make it high, the while loop stops and it executes the blinks.

This question is off topic, but to avoid making another thread I thought asking you would be much easier...

When you use the increment operator, is there a way to make it continuously increment until a certain value (ex. 8), then reset to 0 and repeat?

As this code only increments every time the button is pressed.

void loop(){

  if(digitalRead(3)== 0)
  {
    while(digitalRead(3) == 0);

    ledMode++; 
  
  }

no. you'll need to test for that value and reset it or use the mod operator

ledMode = ++ledMode % 8;

it's odd the way this code is conditional on the button being pressed (== 0) and then waits for it to go HIGH.

doing things in conventional ways makes it easier to recognize what the code is doing and recognizing bugs

Ah, okay. Thank you, your help is much appreciated!

Agreed, I thought this was an interesting workaround for the debounce and button press issue I had earlier. But, I suppose it's best for the long term to stay conventional.

Hi,
How have you got your button wired?
1.Between digital input and gnd.
OR
2. Between digital input and 5V

If 1. Have you got a 10K pullup resistor between the digital input and 5V?
If 2. Have you got a 10K pulldown resistor between the digital input and gnd?

What model Arduino are you using?

Thanks... Tom... :smiley: :+1: :coffee: :australia:

because the code being executed has delays, there's no need to debounce.

in other cases recognizing a change and delaying for 20 msec is sufficient

1 Like

The button is just wired via GND and pin 3. To workaround using an external resistor I just implemented pinMode(3, INPUT_PULLUP);

  • UNO r3 (Third party - ELEGOO)
1 Like

I do this alla time, it is a lazy man’s deboincing. Sprinkle a few 10 ms delays around in there and get on with the bigger problem.

Although here it does seem wrongly done even as a hack.

I am so lazy. Usually I just use an externally denounced pushbutton… so catch the press and hang until it goes unpressed.
.
a7

Isn't that undefined behavior according to the standard? I am no expert but

ledMode = (ledMode+1) % 8;

will always work

why?

++ledMode (vs ledMode++) mean increment before the value is used

But I don't believe there is a sequence point in that expression that guarantees the preincrement completes before the assignment. But again, I am NOT a standards expert guy.

what do you think preincrement means?

1 Like

the following output and code

      1
      2
      3
      4
      5
      6
      7
      0
      1
      2
#include <stdio.h>

int
main ()
{
    int ledMode = 0;
    for (int i = 10; i > 0; i--)  {
#if 1
        ledMode = ++ledMode % 8;
#else
        ledMode = ledMode++ % 8;
#endif
        printf (" %6d\n", ledMode);
    }
}

and this is the result doing a post increment

      0
      0
      0
      0
      0
      0
      0
      0
      0
      0

#include <stdio.h>

int
main ()
{
    int ledMode = 0;
    for (int i = 10; i > 0; i--)  {
#if 1
        ledMode = ++ledMode % 8;
#else
        ledMode = ledMode++ % 8;
#endif
        printf (" %6d\n", ledMode);
    }
}

@adrianoles
I think you will find the following tutorials helpful:

My take on reading and responding to buttons:

There is also blink without delay in the Arduino IDE.

I hope those help you.

preincrement means exactly what you think, you add 1 to the variable before using said value. It also stores this incremented value back into the original location. The assignment operator also stores a value back into the same location. You now have two writes to the same memory location and no guarantee about which one will happen first. Just because the arduino code does the right thing, does not mean it doesn't fall into the undefined behavior category.

EDIT: This article confirms it: c++ - Undefined behavior and sequence points - Stack Overflow

So let’s don’t learn from you all about this confusing matter you bring up.

google out of curiosity, I found this

 i = ++i + 2; // undefined behavior until C++11

I tend to have trouble learning about these things, so I’m just as happy to write things like that out as a few statements. Clearer for every body, no disagreements.

 number++; number &= 0x7; // ;-)

a7

the pre-increment is performed first before the value is used for other operations.

arduino uses the industry standard GNU CC compiler

i don't understand what is underfined. the compiler needs to access the value of the variable. the value is affected by the increment -- first.

There is nothing to order the two times when a value of the variable is put into the memory for that variable.

The sequence points idea is exploited by compiler optimisations, this is exactly why the statement as it was written can produce unintended effects.

Until C++11.

But I’m not standards and experts “guy”.

a7