Push button problems - repeated loop on toggle

I'm writing a simple program that senses a push button and initiates a countdown sequence and pulses a flash relay. The event sequence looks like this:

  1. Green "Ready" LED is on
  2. Push button is activated, Green LED turns off
  3. Red LED on for 1 sec
  4. Red LED off, Orange LED on for 1 sec
  5. Orange LED off, Yellow LED on for 1 sec
  6. Yellow LED off, Green LED on, pulse Flash relay
  7. Wait for push button to be activated again

My problem is that the sequence will loop itself 2 or more times every push of the button. I'm using a common debounce code I've used in the past with no problems. NOTE my push button has +5 on the NO contact, GND on the NC contact, and the COM contact connected to my BUTTON pin.

int BUTTON = 18; // Pin connected to push button.
int FLASH = 19; // Pin connected to flash relay

int RED = 14; // Countdown LED
int ORANGE = 15; // Countdown LED
int YELLOW = 16; // Countdown LED
int GREEN = 17; // Ready LED

int BUTstate; // Current reading from BUTTON pin
int lastBUTstate = LOW; // Previous reading from BUTTON pin

long lastDebounce = 0; // Last time output was changed
long Delay = 25; // Debounce Time

void setup()
{
  pinMode (BUTTON, INPUT);
  pinMode (FLASH, OUTPUT);
  pinMode (RED, OUTPUT);
  pinMode (ORANGE, OUTPUT);
  pinMode (YELLOW, OUTPUT);
  pinMode (GREEN, OUTPUT);
  
  digitalWrite(GREEN, HIGH);
}

void loop()
{
  
  int reading = digitalRead(BUTTON); 
  
    if (reading != lastBUTstate)
  {
    lastDebounce = millis();
  }
  
  if ((millis() - lastDebounce) > Delay)
  {
    BUTstate = reading;
  }
  
  if (BUTstate == HIGH)
  {
    digitalWrite(GREEN, LOW);
    digitalWrite(RED, HIGH);
    delay(1000);
    digitalWrite(RED, LOW);
    digitalWrite(ORANGE, HIGH);
    delay(1000);
    digitalWrite(ORANGE, LOW);
    digitalWrite(YELLOW, HIGH);
    delay(1000);
    digitalWrite(YELLOW, LOW);
    digitalWrite(GREEN, HIGH);
    digitalWrite(FLASH, HIGH);
    delay(100);
    digitalWrite(FLASH,LOW);
  }

  lastBUTstate = reading;
  
}

I just can't seem to figure out why it's looping itself. Once the button is released its grounded on and LOW, so why is the loop repeating?

Adam

You already have delays in the sequence, why complicate it with debounce?

What's wrong with just the if statement for the sequence?

You never reset BUTstate back to LOW once the loop runs. Just addin,

(Just a snippet from your code.)
if (BUTstate == HIGH)
{
BUTstate = LOW; // resets it back to LOW
digitalWrite(GREEN, LOW);
digitalWrite(RED, HIGH);
delay(1000);
digitalWrite(RED, LOW);
digitalWrite(ORANGE, HIGH);
delay(1000);
digitalWrite(ORANGE, LOW);

HazardsMind:
You never reset BUTstate back to LOW once the loop runs. Just addin,

(Just a snippet from your code.)
if (BUTstate == HIGH)
{
BUTstate = LOW; // resets it back to LOW
digitalWrite(GREEN, LOW);
digitalWrite(RED, HIGH);
delay(1000);
digitalWrite(RED, LOW);
digitalWrite(ORANGE, HIGH);
delay(1000);
digitalWrite(ORANGE, LOW);

That's what the lastBUTstate = reading at the end of the code is for. It compares the current state to the last state and if they are different it then compares the time to the delay, and if it's greater it takes it as a reading and not "noise".

Arrch:
You already have delays in the sequence, why complicate it with debounce?

What's wrong with just the if statement for the sequence?

Good point. I guess I am just in the habit of debouncing after the past few programs i've written.

Removed the debounce sequence, works perfectly now.

I guess it's the simple solutions that are so easily overlooked....

Thanks Arrch

aalexa5588:
Good point. I guess I am just in the habit of debouncing after the past few programs i've written.

Removed the debounce sequence, works perfectly now.

I guess it's the simple solutions that are so easily overlooked....

Thanks Arrch

It's good practice, but if was certainly the cause of your trouble in this case because the debounce code is intended to run often. What was happening was that after the display sequence, loop() was called again, It wasn't prepared to say it was LOW quite yet because as far as it was concerned, it just switched to ground.

Arrch:
It's good practice, but if was certainly the cause of your trouble in this case because the debounce code is intended to run often. What was happening was that after the display sequence, loop() was called again, It wasn't prepared to say it was LOW quite yet because as far as it was concerned, it just switched to ground.

Well shucks, that makes a whole lotta sense. Now that i think of it you're right about the debounce intended to be ran often, most of my other programs are always looking and receiving key presses, where as this one is idle for much longer in between key presses.