Use a pushbutton as a start button which stops after


For the project I am currently working on I want to use a push button as a start button. Whenever the button is pressed, I want the Arduino to run a certain script for a defined period of time (around 20 seconds).
I did it by using delay() but I don't like this as I need to still control other elements of the system while the time is passing by. I would need to be able to save in a variable that the button has been pushed and keep this variable on till the time has passed.

Can someone help me out with this?

Thanks a lot in advance!!

At the top of the forum this was in before it was moved is a post Using millis for timing. A beginners guide

That's the technique you need to use.


The devil's in the details....

Whenever the button is pressed.....

You need to clarify in your own mind, and in words here for those who may want to help further, if "is pressed" means "becomes pressed" or "while pressed".

"Becomes pressed" means you need to look for an unpressed-to-pressed transition and start timing. "While pressed" means that you'll effectively be adding to your 20 seconds by the length of time you take to release the button.

Then, you also need to clarify what happens if you press the button again during the 20 seconds. Should that be ignored so the original 20 seconds stands, or honoured, effectively starting a new 20 seconds in the middle of the old one.

Thanks both, let me define my project a little further. What I am trying to develop is the following chain of actions:

  1. machine is on - OK
  2. when an object gets close to my machine (I have defined a specific range for this) a first led starts to blink. - OK so far, I am using a Sharp distance sensor and with an easy IF function I can make this work
  3. if step 2 is true (iow object is still in the range), then I can press a push button (just press it, not hold it pressed) to launch a process and switch off the first led. This process runs for a certain period of time which is defined. When the time is completed, the process stops and another led goes on.
  4. when the object leaves the distance range, the second led goes off.

I managed to program this using delay() but the issue is that I need the process to stop and all the led to go off if the object leaves the required distance while the process is in ongoing. This is not possible with delay. I read the beginners' guide on millis() but I don't believe it is really addressing my issue, if i am not mistaken

I wrote the code below based purely on what you said in your opening post, not the second one, which does complicate things but on the face of it still seems to me like a candidate for millis().

FWIW have a look at the code below, which is based on the state change detect example, but with the button wired to ground for active low with the internal pullup enabled.

You’ll see I just make a “note” of the time at which the button becomes pressed, and set a boolean flag. The function doThisStuff() then runs for whatever the required time is. The flag prevents a re-press in the middle of the timer being honoured.

It does what I think you originally asked, and may give you a bit of a kick-start.

// do a thing for X seconds after a button is pressed
// 5 august 2019

  State change detection (edge detection) changed for INPUT PULLUP

// this constant won't change:
const int  buttonPin = 3;    // the pin that the pushbutton is attached to
//   the button must be wired from pin to ground, it's pinmode is input_pullup

// Variables will change:
bool buttonState;         // current state of the button
bool lastButtonState;     // previous state of the button
unsigned long startedDoingStuffAt;
unsigned long currentMillis;
bool doingStuff;
int howLongToDoStuffFor = 2000; //just a short time to test, 20000 in real life

void setup()
  // initialize serial communication:
  Serial.println(".... do a thing for X seconds after a button is pressed ....");
  Serial.print("Compiler: ");
  Serial.print(", Arduino IDE: ");
  Serial.print("Created: ");
  Serial.print(", ");

  // initialize the button pin as a input with pullup so active low
  //    make sure the button is from pin to ground
  pinMode(buttonPin, INPUT_PULLUP);

  //initialize button states
  buttonState = digitalRead(buttonPin);
  lastButtonState = buttonState;

  //turn bulitin led off
  digitalWrite(LED_BUILTIN, LOW);

  Serial.println(" ");
  Serial.println("Setup done... press the button to start doing stuff");
  Serial.println(" ");

void loop()
  currentMillis = millis();
  // read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) // means it changed... but which way?
    if (buttonState == LOW)  // changed to pressed
      // if the current state is LOW then the button was pressed
      if (!doingStuff) //so as not to restart the clock part way through (although, maybe that's what's needed?
        Serial.print("Newly pressed, starting to do stuff at ");
        startedDoingStuffAt = currentMillis;
        doingStuff = true;

    // Delay a little bit to avoid bouncing
  // save the current state as the last state, for next time through the loop
  lastButtonState = buttonState;

  if (doingStuff)
    //see if time is up yet
    if (currentMillis - startedDoingStuffAt <= howLongToDoStuffFor) //time's not up
    else //time is up
      doingStuff = false;
      Serial.print("  Time is up, stopped doing stuff at ");
      Serial.println("      Press the button to start doing stuff again");


} //loop

void doThisStuff()
  Serial.print("Doing stuff for ");
  Serial.println(" ms after button is pressed");

@meltDown, Thanks a lot. Indeed I had to modify your code slightly to my situation but it works!