trying to get a switch to work

basically trying a bit of home automation reguarding a light out side, what i want is if the button is pressed for a short period the light turns and a delay is set to turn the light out, but if the button is held for more than the delay period i want the light to turn straight out with out delay this is what ive got so far

const int SW1 = 2;     //Switch 1 
const int L1 =  13;      // Outside light 1 sub pin 13 for now


int buttonState = 0;        

void setup() {
  pinMode(L1, OUTPUT);      
  
  pinMode(SW1, INPUT);     
}

void loop(){

  buttonState = digitalRead(SW1);

  if (buttonState == HIGH){     

    digitalWrite(L1, HIGH);  
    delay(2048);
} 

  
  else if (buttonState == HIGH){
    digitalWrite(L1, HIGH);
}

  
  else {
    digitalWrite(L1, LOW); 
}
}

i dont understand why its not working so if someone can point me in the right direction thanks in advance

i dont understand why its not working

I don't understand what is not working. Care to elaborate?

Do you have an external pulldown resistor wired with that switch? How is the switch wired?

the switch works fine but it delays reguardless of how long the switch is held

but it delays reguardless of how long the switch is held

Of course it does. Because that's what you told it to do. Nowhere do you detect that the switch is pressed now but was not before. Nowhere do you record when that happened. Nowhere do you detect that the switch is released but was not before. Nowhere do you record when that happened. Nowhere do you determine how long the switch was pressed.

  if (buttonState == HIGH)
{     
} 
else if (buttonState == HIGH)
{
}
else
{
}

Nothing will ever cause that else if statement block to be executed. If the buttons state is HIGH, the first block will be executed. The second block can not be executed, because the case for the switch being HIGH has already been handled.

  if (buttonState == HIGH){     
    digitalWrite(L1, HIGH);  
    delay(2048);
} 
  else if (buttonState == HIGH){
    digitalWrite(L1, HIGH);

So if the switch is HIGH, turn on L1 and wait 2.048 seconds.

Otherwise (so the switch is not HIGH), see if the switch is HIGH (which it won't be), and turn on L1 if it is.

Hmmm. Don't see the point to the second part.

CAUTION: Spoiler code follows :wink:

Code to deal with buttons clutters things up and makes the main logic harder to read, and differentiating short and long presses just complicates it that much more. So it's good to have the button handling code moved off into another module or to a library. The sketch below uses a library that I wrote. Note that my switch may not be wired the same way as yours. It looks like you may be using a pull-down resistor. I just wire the switch from the pin to ground and use the internal pull-up resistor.

#include <Button.h>        //https://github.com/JChristensen/Button

#define BUTTON_PIN 2       //Connect a tactile button switch (or something similar)
                           //from Arduino pin 2 to ground.
#define PULLUP true        //To keep things simple, we use the Arduino's internal pullup resistor.
#define INVERT true        //Since the pullup resistor will keep the pin high unless the
                           //switch is closed, this is negative logic, i.e. a high state
                           //means the button is NOT pressed. (Assuming a normally open switch.)
#define DEBOUNCE_MS 20     //A debounce time of 20 milliseconds usually works well for tactile button switches.

#define LED_PIN 13         //The standard Arduino "Pin 13" LED.
#define LONG_PRESS 1000    //Define a "long press" to be 1000 milliseconds.
#define LED_DELAY 5        //Seconds to leave the LED on after the button press.

Button myBtn(BUTTON_PIN, PULLUP, INVERT, DEBOUNCE_MS);    //Declare the button
boolean ledState;          //The current LED status
unsigned long ms;          //The current time from millis()
unsigned long msOn;        //The time we turned the LED on

void setup(void)
{
    pinMode(LED_PIN, OUTPUT);    //Set the LED pin as an output
}

void loop(void)
{
    ms = millis();               //record the current time
    myBtn.read();                //Read the button
    
    if (myBtn.wasReleased()) {
        msOn = ms;
        ledState = true;
        digitalWrite(LED_PIN, HIGH);
    }
    else if (myBtn.pressedFor(LONG_PRESS)) {
        ledState = false;
        digitalWrite(LED_PIN, LOW);
        while (myBtn.isPressed()) myBtn.read();    //wait for button to be released
    }

    if (ledState && ms - msOn >= LED_DELAY * 1000) {
        ledState = false;
        digitalWrite(LED_PIN, LOW);
   }        
}

ok guys let me put it another way, when i press the button in i want the delay to start and finish and that is it, if the button is held in i still want it to delay for the set time then turn off for instance

button pushed
delay 1 second
turn light off reguardless if button still pressed

i just cant seem to get it to work, and im sure its pretty simple ive been spending half hour a night reading arduino basics and i am sitll clueless so if someone can help and explain exactly what the arduino is doing whilst the code is running that would be apreciated

so if someone can help and explain exactly what the arduino is doing whilst the code is running that would be apreciated

It is executing one instruction after another, as fast as it can. If you tell us specifically what code you are talking about, we can provide more details.

and im sure its pretty simple

You are right. It is. Very simple.

Did you try Jack's code? What happened? How did that differ from what you wanted to have happen?

The group's crystal ball is out for cleaning this week. Last time, it took almost two years to get back. So, don't hold your breath.

Often on a project like this, all the possibilities aren't covered in the specs. I think the following fully specifies the action of the code above. Let us know if this is what you want, and whether it works that way for you.

  1. If LED is off
    a. If the button is pressed and released quickly, the LED will turn on for 5 seconds, then turn off.
    b. If the button is pressed and held for at least a second, nothing happens.

  2. If LED is on
    a. If the button is pressed and released quickly, the LED will stay on for 5 more seconds, then turn off.
    b. If the button is pressed and held for at least a second, the LED will turn off.

PaulS:
The group's crystal ball is out for cleaning this week. Last time, it took almost two years to get back. So, don't hold your breath.

XD

tried jacks code it didnt work how i wished but the descriptions helped me understand how his code was executed,
switch pushed led turns on for 5 seconds and turns off even if the switch is still pushed what it is currently doing is waiting for the switch to be released then it will do the 5 second turn off delay after the switch is released
what i want to happen is 5 second light on then turn off regaurdless of switch being held
so if switch pressed led turns on for 5 seconds and turns off even if the switch is held in

i do apreciate all the help i really do but ive been trying to code for so long now i dont think i'll ever get the hang of it

spookyman60:
tried jacks code it didnt work how i wished but the descriptions helped me understand how his code was executed,
switch pushed led turns on for 5 seconds and turns off even if the switch is still pushed what it is currently doing is waiting for the switch to be released then it will do the 5 second turn off delay after the switch is released
what i want to happen is 5 second light on then turn off regaurdless of switch being held
so if switch pressed led turns on for 5 seconds and turns off even if the switch is held in

The way I read the original post was that if the button was held in for some relatively longer period it would turn the LED off.

If that is no longer a requirement, try the code below.

#include <Button.h>        //https://github.com/JChristensen/Button

#define BUTTON_PIN 2       //Connect a tactile button switch (or something similar)
                           //from Arduino pin 2 to ground.
#define PULLUP true        //To keep things simple, we use the Arduino's internal pullup resistor.
#define INVERT true        //Since the pullup resistor will keep the pin high unless the
                           //switch is closed, this is negative logic, i.e. a high state
                           //means the button is NOT pressed. (Assuming a normally open switch.)
#define DEBOUNCE_MS 20     //A debounce time of 20 milliseconds usually works well for tactile button switches.

#define LED_PIN 13         //The standard Arduino "Pin 13" LED.
#define LONG_PRESS 1000    //Define a "long press" to be 1000 milliseconds.
#define LED_DELAY 5        //Seconds to leave the LED on after the button press.

Button myBtn(BUTTON_PIN, PULLUP, INVERT, DEBOUNCE_MS);    //Declare the button
boolean ledState;          //The current LED status
unsigned long ms;          //The current time from millis()
unsigned long msOn;        //The time we turned the LED on

void setup(void)
{
    pinMode(LED_PIN, OUTPUT);    //Set the LED pin as an output
}

void loop(void)
{
    ms = millis();               //record the current time
    myBtn.read();                //Read the button
    
    if (myBtn.wasPressed()) {
        msOn = ms;
        ledState = true;
        digitalWrite(LED_PIN, HIGH);
    }
//    else if (myBtn.pressedFor(LONG_PRESS)) {
//        ledState = false;
//        digitalWrite(LED_PIN, LOW);
//        while (myBtn.isPressed()) myBtn.read();    //wait for button to be released
//    }

    if (ledState && ms - msOn >= LED_DELAY * 1000) {
        ledState = false;
        digitalWrite(LED_PIN, LOW);
   }        
}

that is perfect thank you i now must read the code and understand it thank you very much

I've added a few comments below that may help. Let us know if you have questions. Enjoy!

void loop(void)
{
    //loop executes over and over, very rapidly
    ms = millis();               //record the current time
    myBtn.read();                //Read the button
    
    if (myBtn.wasPressed()) {    //was the button pressed since the last time we checked?
        msOn = ms;               //yes, save the time it was pressed
        ledState = true;         //set the LED state variable to indicate the LED is on
        digitalWrite(LED_PIN, HIGH);    //and turn the LED on
    }

    //check to see if the LED state is on (true) AND has been on for the maximum delay period
    if (ledState && ms - msOn >= LED_DELAY * 1000) {
        ledState = false;            //if so, set the LED state variable to indicate the LED is off
        digitalWrite(LED_PIN, LOW);  //and turn the LED off
   }        
}

that is most helpul thank you very much for all the help