Help with delay after throwing switch and while loop

Hi,

I'm learning about Arduino. Mostly doing Ok, but.....I'm stuck!

I've got an Arduino Uno, a switch and an LED.

The idea is to throw the switch on and the led comes on for 5 seconds and then goes off. If the switch is thrown off then the LED is off.

All works until I add the delay bit and the While loop. I'm doing something wrong but I can't see where it is.

Any help much appreciated

Thanks Jon

/*
turn on LED when the switch is thrown on
turn off LED after 5 seconds
turn off LED when switch is thrown off
*/
int pinButton = 8; //the pin where we connect the button
int LED = 2; //the pin we connect the LED
int StateButton = 1;

void setup() {
pinMode(pinButton, INPUT); //set the switch pin as INPUT
pinMode(LED, OUTPUT); //set the LED pin as OUTPUT
}

void loop() {
int stateButton = digitalRead(pinButton); //read the state of the switch
if (stateButton == 1) { //if is switched on
digitalWrite(LED, HIGH);//write 1 to LED
delay(5000);
digitalWrite(LED, LOW);//write 0 to LED
} else { //if not pressed
digitalWrite(LED, LOW); //write 0 to LED
}
{ int stateButton = digitalRead(pinButton); //read the state of the switch
while (stateButton == 1) {
delay(1);
}
}
}

If you don't use delay, then you need to use millis(). Also you must track button state changes.
Here is a suggestion:

/*
  turn on LED when the switch is thrown on
  turn off LED after 5 seconds
  turn off LED when switch is thrown off
*/
const int pinButton = 8; //the pin where we connect the button
const int LED = 2; //the pin we connect the LED
int StateButton = 1;
int oldState = 0;
unsigned long chrono = 0;

void setup() {
  pinMode(pinButton, INPUT); //set the switch pin as INPUT
  pinMode(LED, OUTPUT); //set the LED pin as OUTPUT
}

void loop() {
  int stateButton = digitalRead(pinButton); //read the state of the switch
  if (stateButton == 1) { //if is switched on
    delay(20); // only if you use a pushbutton, if not remove the line
    if (oldState == 0) {
      digitalWrite(LED, HIGH);//write 1 to LED
      chrono = millis();
    } else {
      if (millis() - chrono > 5000ul) digitalWrite(LED, LOW); //write 0 to LED
    }
  } else { //if not pressed
    digitalWrite(LED, LOW);  //write 0 to LED
  }
  oldState = stateButton;
}

It compiles, but I didn't test it...

there were some oversites in your code. i've commented out the lines i replace

assuming you just connected a momentary switch to an input, the input needs a pullup resistor to make it high when the switch is not closed. pin can be configured as an input with a pull using INPUT_PULLUP

with a pullup, the pressing the switch causes the input to be LOW not HIGH

you're trapped once you enter the while (statebutton ==1) because there's not way for stateButton to change.

int pinButton = 8;
int LED       = 2;
int StateButton = 1;

void setup() {
 // pinMode(pinButton, INPUT); //set the switch pin as INPUT
    pinMode(pinButton, INPUT_PULLUP);
    pinMode(LED, OUTPUT); //set the LED pin as OUTPUT
}

void loop() {

    int stateButton = digitalRead(pinButton); //read the state of the switch

    Serial.println (stateButton);

 // if (stateButton == 1) { //if is switched on
    if (stateButton == 0) { //if is switched on
        digitalWrite(LED, HIGH);//write 1 to LED
        delay(5000);
        digitalWrite(LED, LOW);//write 0 to LED
    }
    else { //if not pressed
        digitalWrite(LED, LOW);    //write 0 to LED
    }

 // int stateButton = digitalRead(pinButton); //read the state of the switch
 //     while (stateButton == 1) {
 //         delay(1);
 //     }
}

i think the above changes make the code work more like you asked. But my read was that if the switch opens during the 5 seconds while the LED is on, the LED should immediately go off.

The functions delay() and delayMicroseconds() block the Arduino until they complete.
Have a look at how millis() is used to manage timing without blocking in Several Things at a Time.

And see Using millis() for timing. A beginners guide if you need more explanation.

...R

my read was that if the switch opens during the 5 seconds while the LED is on, the LED should immediately go off.

to do so, you need to capture the time (millis()) whenever the switch is open (released). that time can be compared to the current time (delta) and the LED made active while that delta is >0 and < 5000 msec.

while holding the switch down, the LED will turn on and then off after 5 seconds and it will turn off if you release the switch before 5 sec.

Hi,

Many thanks. The code from lesept worked fine, though the detail is a bit baffling (all part of the learning!!).

The next stage of my project is to add another switch in series with the first one. The LED to light for 5 seconds when both switches are thrown and then go off.

I've attached a drawing of my circuit so far:

Thanks

Jon

Not sure to understand your need (not native english speaking here) : do you say that the led should light for 5 seconds only if both buttons are pushed ?

You can simply put the buttons in series, as you seem to say in your message, i.e.

GND -- Button1 -- Button2 -- Arduino
and no need to change the code.

Or if you really need 2 independant buttons, just add the second button :

const int pinButton2 = 7; //the pin where we connect the 2nd button
...
  pinMode(pinButton2, INPUT); //set the switch pin as INPUT
...

add this

    int stateButton2 = digitalRead(pinButton2); //read the state of the 2nd switch

and change this line

  if (stateButton == 1 && stateButton2 == 1) { //if both are switched on

I think it should do it.