Count Down Timer Misbehaving

Newbie here, looking for some assistance again. I am trying to write a sketch that when a button is pushed, a relay will close (or for testing turn on an LED). When the button is released the relay will remain closed (LED stays on) for a 30 second interval. If the button is pushed again before the count down reaches zero, the timer is reset. The time remaining (in seconds) before the LED will turn off is displayed in the serial monitor. When the button is released the timer will count down the first few ticks too fast and then resume to the one second interval between ticks. I have added a debounce to the button as well, but still end up with the same results. If the button is held down for a while before release it seems to exaggerate the problem of the countdown timer counting down too fast for the first few ticks. What am I missing here? Thanks in advance for any help.

bool buttonState;
bool previousButtonState = HIGH;
bool buttonRead;
bool relayState;

byte LEDpin1 = 9;
byte buttonPin1 = A0;

int countDown = 30;
int debounceDelay = 200;
int minutes;
int seconds;
int countDownDelay = 1000;

unsigned long lastTick;
unsigned long timerMillis;
unsigned long debounceMillis;

void setup() {
  Serial.begin(9600);
  pinMode (LEDpin1, OUTPUT);
  pinMode (buttonPin1, INPUT_PULLUP);
  delay (1000); // delay to set LEDpin1 low before loop
}

void loop() {

  debounce();
  setState();
}

void debounce() {

  buttonRead = digitalRead(buttonPin1);
  if (buttonRead != previousButtonState) {
    debounceMillis = millis();
  }
  if ( millis() - debounceMillis > debounceDelay) {
    if (buttonRead !=  buttonState) {
      buttonState = buttonRead;
    }
  }
  previousButtonState = buttonRead;
}

void setState() {
  switch (buttonState) {
    case 0:
      relayState = 1;
      countDown = 30;
      digitalWrite (LEDpin1, HIGH);
      break;
    case 1:
      startTimer();
      if (countDown <= 0) {
        digitalWrite (LEDpin1, LOW);
      }
      relayState = 0;
      break;
  }
  //Serial.println (relayState);
}

void startTimer() {

  timerMillis = millis();
  if (timerMillis - lastTick >= countDownDelay) {
    countDown--;
    displayCountdown();
    lastTick = lastTick + 1000;
  }
}

void displayCountdown() {
  // seconds = countDown % 60;
  seconds = countDown;
  Serial.print(" Time Remaining = ");
  Serial.println(seconds);
}

The problem is lastTick only gets incremented whenever startTimer() gets called AND (timerMillis - lastTick >= countDownDelay). When you hold the button down lastTick gets way behind millis() because startTimer() isn't being called so it takes several increments to get caught up.

Instead of:

lastTick = lastTick + 1000;

Use:

lastTick = millis();

Also, you shouldn't need 200ms for your debounce. Try 50 or 20.

Also think about what the value of the lastTicks variable is when you first enter startTimer() (i.e. what is the starting value of lastTicks, and how will that compare to millis()?)

Thank you! I almost want to face palm myself right now as I was so close in some previous trials of this sketch. The timer is working correctly now. Thanks again.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.