Reset millis when button is not pressed

Hey, Snoop the noob dev here. Ive read many topics and im aware that reseting millis() is a bad option. However im trying to make a program that starts a timer when the button is pressed and reset the timer when its not pressed. Example:

  • Holding button*

if (time_now == 1000) {

  • do something
    }

if (time_now == 2000) {

  • do something

}

if (time_now == 4000) {

  • do something

}

My code:

const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  13;      // the number of the LED pin
unsigned long time_now = 0;
// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status

void setup() {
 pinMode(ledPin, OUTPUT);
 pinMode(buttonPin, INPUT);


void loop() {
 // read the state of the pushbutton value:
 buttonState = digitalRead(buttonPin);

 // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
 if (buttonState == HIGH) {
   time_now = millis();
   // turn LED on:
   digitalWrite(ledPin, HIGH);
   if (time_now == 1000) {
     
 } if (time_now == 2000) {
   
 } if (time_now == 4000) {

 }
   
   
 } else {
   // turn LED off:
   digitalWrite(ledPin, LOW);
   time_now = 0;

 }

}

I want the timer to only count while button is pressed, and always start to count from 0 without using Delay.

why don't you record the time at which the button was pressed, and use time_press-millis() as your time_now?

You don't do it like this:

if (time_now == 1000) {
- do something
}

you do something like:

if (millis() - lastEventAtMs >= 1000) {
   // Timer expired because 1000mS has passed since last event, so do something
}

6v6gt:
You don't do it like this:

if (time_now == 1000) {
  • do something
    }



you do something like:



if (millis() - lastEventAtMs >= 1000) {
  // Timer expired because 1000mS has passed since last event, so do something
}

Thanks for the reply, i will update my code. However Millis() runs all the time, so how do i prevent it from running if the button is not pressed, and how do i "reset it" so it starts at 0 next time button is pressed?

snoopynoob:
However Millis() runs all the time, so how do i prevent it from running if the button is not pressed, and how do i "reset it" so it starts at 0 next time button is pressed?

You don't. That is a nonsensical suggestion.

You use the answer you were given.

OK, I confess, he was pulling you leg somewhat. :roll_eyes:

You were supposed to figure out the "obvious" - to "start" your timer you use:

lastEventAtMs = millis();

having defined

unsigned long lastEventAtMs

at the start.

Paul__B:
having defined

long lastEventAtMs

at the start.

OOPs --- that should be unsigned long

...R

Robin2:
OOPs --- that should be unsigned long

Corrected.

I was a bit vague trying to get it all in order. :roll_eyes:

snoopynoob:
Thanks for the reply, i will update my code. However Millis() runs all the time, so how do i prevent it from running if the button is not pressed...

millis is supposed to run all the time. What if you needed multiple timers with differing presets and unpredictable start times? Resetting millis would destroy that.

snoopynoob:
and how do i "reset it" so it starts at 0 next time button is pressed?

Resetting a timer is, essentially, holding its value at zero. This is done by constantly loading the time with the value of millis so the *difference between them *(millis() - yourTimer) is zero. When you stop resetting the timer the value of millis() - yourTimer begins to increase. That *difference *is what is compared to decide if time has expired.

Creating a separate yourTimerX for each interval is how multiple timers are implemented.

Perhaps an illustration will help.

You can stop and restart the millis timer by disabling timer0's ISR. I do not know the syntax out of my head for that. This is perfectly safe to do if this is the only thing you want to do with millis().

Out of the box the arduino library does not allow you to reset the millis counter. You could look the source code up and add a clear function yourself. It is doable if you really really want it. It is just not recommendable as you see in earlier responses as you might break other things.

A workaround is relative easy. I believe that this code does what you want.

unsigned long yourCounter;
unsigned long lastTime;

const int intervalTime = 10; // every 10ms?
const int yourButton = 12; // fill in your button

void setup() {
    pinMode(yourButton, INPUT_PULLUP); // pullup desirable?

    Serial.begin(115200);
}

void loop() {

    unsigned long currentTime = millis();

    if( currentTime - lastTime >= intervalTime ) {
        lastTime = currentTime;

        if( digitalRead(yourButton) == LOW ) { // if we use pullup resistor
            yourCounter += ( currentTime - lastTime );
            Serial.println(yourCounter);
        }
        else {
            yourCounter = 0;
        }
    }
}

currentTime minus lastTime is the difference. If the button is pressed this difference will be added to your own counter and it will be printed on the serial monitor. If the button is not pressed your counter will be continously set at 0.