Two Buttons Delay Start LED Timer

Here is what I am trying to do with Arduino UNO.

  1. Set up two push buttons (red and blue).

  2. Pressing the red button once starts a 1 minute delay then turns on the LED for 3 minutes then turns it off and is ready for either of the buttons to be pressed again.

  3. Pressing the blue button once starts a 2 minute delay then turns on the LED for 5 minutes then turns it off and is ready for either of the buttons to be pressed again.

I eventually want to set this up for other than lighting the LED but figure this should get me into what I need to do to make this happen.

Figure using the built in LED on pin 13 for output and pin 2 as the input for the red button and pin 4 as the input for the blue button.

I think I can handle the wiring, it is writing the sketch to do this that confuses me. I have done the sketches to blink the led, changed the timing of the blinking, had the led stay on with one push and turn off with a second.

Any help would be appreciated.

Thanks.

Well, this is a program that can be written with simple delay() functions. Nothing fancy like millis() actually needed. I suggest you try coding it and post it here in code tags. It's really just do this, then do this, then do this kind of logic.

As aarg has said, you can use simple delay() functions.

If you want the program to be able to respond to the buttons during either delay/lighting sequence you can use a library like this Timer library or you can do a loop delay with button polling in it.

I like the Timer library approach, but both are useful.

Again, if you don't want or need to interrupt the LED on and delay once a button is pushed, then just do the delay() method.

Bdartm1:
2. Pressing the red button once starts a 1 minute delay then turns on the LED for 3 minutes then turns it off and is ready for either of the buttons to be pressed again.

  1. Pressing the blue button once starts a 2 minute delay then turns on the LED for 5 minutes then turns it off and is ready for either of the buttons to be pressed again.

How accurate do you need the timings to be?

Does it matter whether the 3:00 minutes are actually 2:59 or 3:01 minutes or if the 5:00 minutes is actually 4:58 or 5:02 minutes?

Within a second or two would be fine.

If you are OK within a second or two, I would do this with states and millis() timers. Taking a look at this pseudo code for the case of the red button. It should give you some ideas.

Initial Variables

boolean redButtonPressed = false;
unsigned long timeRedButtonPressed;
boolean LEDon = false;
unsigned long timeLedTurnedOn;
unsigned long delayedOnRed = 60000UL; 
unsigned long periodOnRed = 180000UL;

You said that you know how respond to the changing state of a button press. When you determine the red button is pressed, change the boolean state variable that says it was pressed, and grab the time that happened. Your logic then looks like this

if(redButtonPressed==true && milies() - timeRedButtonPressed >=delayedOnRed)
{
digitalWrite(13,HIGH);// turn led on
redBottonPressed = false;//reset state
LEDon = true; //change state for led and grab start time
timeLEDon=millis();
}
if(LEDon ==true && millis() - timeLEDon>=periodOnRed)
{
digitalWrite(13,LOW)//turn led off
LEDon = false;
}

There will be similar code for the blue button.

Bdartm1:
Within a second or two would be fine.

In that case the internal timing of the Arduino board using delay() or millis() should fit your needs and you don't need a more accurate realtime clock (RTC) to do what you want.

Here is some initial code (untested, commented, with some debug output on the serial monitor):

// connect red and blue buttons to GND and to their respective pin number
const byte redButtonPin=2;
const byte blueButtonPin=3;
// on pin-13 there is a board LED already on most Arduino boards (UNO, MEGA etc.)
const byte LedPin=13;

void setup() {
  Serial.begin(9600); // set up debugging in the Serial monitor
  Serial.println("Ready for button press");
  pinMode(redButtonPin, INPUT_PULLUP);  // by using the internal pull-up resistor we don't need an external pulll resistor
  pinMode(blueButtonPin, INPUT_PULLUP); // by using the internal pull-up resistor we don't need an external pulll resistor
  pinMode(LedPin, OUTPUT);
}

void loop() {
  if (digitalRead(redButtonPin)==LOW)  // the red button goes LOW when pressed
  {
    Serial.println("Starting 1 minute delay");
    delay(60000L); // halt program execution for 60 seconds = 60000 milliseconds
    Serial.println("then turns on the LED for 3 minutes");
    digitalWrite(LedPin, HIGH); 
    delay(3*60000L); // halt program execution for 3 minutes
    Serial.println("then turns it off ");
    digitalWrite(LedPin, LOW); 
  }
  else
  {
    Serial.println("Starting 2 minute delay");
    delay(2*60000L); // halt program execution for 2 minutes
    Serial.println("then turns on the LED for 5 minutes");
    digitalWrite(LedPin, HIGH); 
    delay(5*60000L); // halt program execution for 5 minutes
    Serial.println("then turns it off ");
    digitalWrite(LedPin, LOW); 
  }
}

Hint: This example is using "blocking code" by using the "delay()" function to stop the program execution while "nothing else is to be done".

If you do not want to halt the program execution, but if you want "to do different things at the same time", you are not allowed to use delay() for stopping the program execution, you would have to use a different "non-blocking" programming logic. For an example of non-blocking programming which is required to do "cooperative multitasking" with Arduino, see this example which is provided with the Arduino IDE:
Files - Examples - 02.Digital - BlinkWithoutDelay

Thank you all. I will give this a try.

I have played around with this quite a bit. Got the red button to work properly. If watching on Serial Monitor it will loop on "Ready for Button Press" until the red button is pressed. Then it will do a two minute delay and then turn on the LED for four minutes.

However, when I press the blue button instead of the red button, nothing happens. In fact, if I just use the code up to "state = 0" before the "else" it works fine for the one button as well.

Trying to tell the Arduino that if the blue button is pushed instead of the red button that it should run the blue button instructions instead of the red button ones.

Code below, hopefully in acceptable format.

Thanks!

//Tun on LED while the button is pressed

const int LED = 13; //the pin for the LED
const int redBUTTON = 7; //the input pin where the red pushbutton connects
const int blueBUTTON = 4;//the input pin where the blue pushbutton connects
int val = 0;  //val will be used to store state of input pin
int val_b = 0;
int old_val = 0; //this stores the previous value of val
int old_val_b = 0;
int state = 0; //0 = LED off and 1 = LED on


void setup() {
  Serial.begin(9600); // set up debugging in Serial Monitor
  pinMode(LED, OUTPUT); //LED is an output
  pinMode(redBUTTON, INPUT); //and redBUTTON is an input
  pinMode(blueBUTTON, INPUT); //and blueBUTTON is an input

}

void loop() {
  Serial.println("Ready for button press.");
  val = digitalRead(redBUTTON);
  if ((val == HIGH) && (old_val == LOW)){
  state = 1;
  
  if (state == 1){
    Serial.println("Starting 2 Minute delay.");
    delay(2*60000L);
    Serial.println("Turn on LED for 4 minutes.");
    digitalWrite(LED, HIGH);
    delay(4*60000L);
    Serial.println("Turn off LED.");
    digitalWrite(LED, LOW);
    state = 0;
   
  }  else {
     val_b = digitalRead(blueBUTTON);
  if ((val_b == HIGH) && (old_val_b == LOW)){
  state = 1;

  if (state == 1){
    Serial.println("Starting 2 Minute delay.");
    delay(2*60000L);
    Serial.println("Turn on LED for 6 minutes.");
    digitalWrite(LED, HIGH);
    delay(6*60000L);
    Serial.println("Turn off LED.");
    digitalWrite(LED, LOW);
    state = 0;
  }  
  }
  }
  }
}

You are not really using the state variable as it will always be ==1 when you test for it, and you don't ever update old_val. I don't know if you are planning to do something with these in the future, but for now, simplify the code and leave them out.

The main problem is that the digitalRead(blueButton) is within an else statement which will not be executed if the redButton is not pushed. There should be two independent conditionals.

You were advised to use INPUT_PULLUP and you have not done so. I will assume you have the correct external pull down on the switch and it goes HIGH when pressed

See if this does what you need

const int LED = 13; //the pin for the LED
const int redBUTTON = 7; //the input pin where the red pushbutton connects
const int blueBUTTON = 4;//the input pin where the blue pushbutton connects
int val = 0;  //val will be used to store state of input pin
int val_b = 0;

void setup() {
  Serial.begin(9600); // set up debugging in Serial Monitor
  pinMode(LED, OUTPUT); //LED is an output
  pinMode(redBUTTON, INPUT); //and redBUTTON is an input
  pinMode(blueBUTTON, INPUT); //and blueBUTTON is an input
}

void loop() {
  Serial.println("Ready for button press.");

  val = digitalRead(redBUTTON);
  if (val == HIGH) {
  Serial.println("Starting 2 Minute delay.");
    delay(2 * 60000L);
    Serial.println("Turn on LED for 4 minutes.");
    digitalWrite(LED, HIGH);
    delay(4 * 60000L);
    Serial.println("Turn off LED.");
    digitalWrite(LED, LOW);
  }
  
  val_b = digitalRead(blueBUTTON);
  if (val_b == HIGH) {
  Serial.println("Starting 2 Minute delay.");
    delay(2 * 60000L);
    Serial.println("Turn on LED for 6 minutes.");
    digitalWrite(LED, HIGH);
    delay(6 * 60000L);
    Serial.println("Turn off LED.");
    digitalWrite(LED, LOW);
  }
}

Thanks. Yes I did put resistors in place to replace the pullup.

I believe what you sent me will also work. I found an example while searching the forum from a poster looking to have his Arduino tweet when a washer cycle or dryer cycle finished. I was able to apply the ideas to this project and changed the code around. Also added a second LED to tell me when the delay before the timer was running so that I could test it without the serial monitor. (Left serial monitor in so that I can use that as well.)

Finished code is as follows and works great.

Thanks again all for suggestions and help!!

//Constants won't change. Used to set pin numbers

const int LED = 13; //the pin for the red LED
const int LEDG = 12;//the pin for the green LED
const int redBUTTON = 7; //the input pin where the red pushbutton connects
const int blueBUTTON = 4;//the input pin where the blue pushbutton connects

//Variables will change
int redBUTTONState = 0;
int blueBUTTONState = 0;


void setup() {
  Serial.begin(9600); // set up debugging in Serial Monitor
  pinMode(LED, OUTPUT); //LED is an output
  pinMode(LEDG, OUTPUT); //Green LED is an output
  pinMode(redBUTTON, INPUT); //and redBUTTON is an input
  pinMode(blueBUTTON, INPUT); //and blueBUTTON is an input

}

void loop() {
  Serial.println("Ready for button press.");
  //Read the state of pushbutton value
  redBUTTONState = digitalRead(redBUTTON);
  blueBUTTONState = digitalRead(blueBUTTON);
  
  
  if (redBUTTONState == 1){
    Serial.println("Starting 2 Minute delay.");
    digitalWrite(LEDG, HIGH);//Turn on Green LED as standby
    delay(2*60000L);
    digitalWrite(LEDG, LOW); //Turn off Green LED as standby
    Serial.println("Turn on LED for 4 minutes.");
    digitalWrite(LED, HIGH);
    delay(4*60000L);
    Serial.println("Turn off LED.");
    digitalWrite(LED, LOW);
  }
  

  if (blueBUTTONState == 1){
    Serial.println("Starting 2 Minute delay.");
    digitalWrite(LEDG, HIGH);//Turn on Green LED as standby
    delay(2*60000L);
    digitalWrite(LEDG, LOW); //Turn off Green LED as standby
    Serial.println("Turn on LED for 6 minutes.");
    digitalWrite(LED, HIGH);
    delay(6*60000L);
    Serial.println("Turn off LED.");
    digitalWrite(LED, LOW);
  }  
}