Coding issues adding a push button with a start/stop function

Hi all,
I'm trying to write the code to program the following functions for a building 7 LED sequence but I want to add one push button with start/stop function.
the sequence would run as follows:
Push button press to start the sequence -> first led switches on -> second led switches on, first light remains lit -> third led switches on, previous 2 stay lit ->fourth led switches on, previous 3 stay lit -> [..] -> 7th led switches on, previous 6 leds stay lit -> all leds remain on until push button pressed again then all leds switch off.

I have written the following code allowing for button bounce etc but when I run it as a demo the button starts the sequence but doesn't turn it all off when pressed again. I am guessing I am missing a crucial bit of code OR I have put my code lines in the wrong place? is anyone able to help!

#define LED_PIN1 2
#define LED_PIN2 3
#define LED_PIN3 4
#define LED_PIN4 5
#define LED_PIN5 6
#define LED_PIN6 7
#define LED_PIN7 8
#define BUTTON_PIN 9

byte lastButtonState;
byte ledState = LOW;

unsigned long lastTimeButtonStateChanged = millis();
unsigned long debounceDuration = 50; // millis 

void setup()
{
  pinMode(LED_PIN1, OUTPUT);
  pinMode(LED_PIN2, OUTPUT);
  pinMode(LED_PIN3, OUTPUT);
  pinMode(LED_PIN4, OUTPUT);
  pinMode(LED_PIN5, OUTPUT);
  pinMode(LED_PIN6, OUTPUT);
  pinMode(LED_PIN7, OUTPUT);
  pinMode(BUTTON_PIN, INPUT);
  lastButtonState = digitalRead(BUTTON_PIN);
}


void loop() {
  if (millis() - lastTimeButtonStateChanged >= debounceDuration){  
  byte buttonState = digitalRead(BUTTON_PIN);
  if (buttonState != lastButtonState) {
    lastTimeButtonStateChanged = millis();
    lastButtonState = buttonState;
    if(buttonState == LOW) { //released
      if (ledState == HIGH) {
        ledState = LOW;
      }
      else {
        ledState = HIGH;  
      } 
      digitalWrite(LED_PIN1, ledState);
      
      }
    {
        digitalWrite(LED_PIN1, HIGH); // turn on LED1
        delay(1000); // Wait for 1000 millisecond(s)
        digitalWrite(LED_PIN2, HIGH); // turn on LED2
        delay(1000); // Wait for 1000 millisecond(s)
        digitalWrite(LED_PIN3, HIGH); //turn on LED3
        delay(1000); // Wait for 1000 millisecond(s)
        digitalWrite(LED_PIN4, HIGH); // turn on LED4
        delay(1000); // Wait for 1000 millisecond(s)
        digitalWrite(LED_PIN5, HIGH); // turn on LED5
        delay(1000); // Wait for 1000 millisecond(s)
        digitalWrite(LED_PIN6, HIGH); // turn on LED6
        delay(1000); // Wait for 1000 millisecond(s)
        digitalWrite(LED_PIN7, HIGH); // turn on LED7
        delay(1000); // Wait for 1000 millisecond(s)
      }
    }  
  }
}

Many thanks and apologies if this is in the wrong sub, I tried to find the best match but it was a bit confusing.

the button isn't being checked while the sequence is running

It looks like your code works upon button RELEASE, not button PRESS. The following code should function the same way. Try this slightly modified but untested version with plenty of comments:

#define LED_PIN1 2
#define LED_PIN2 3
#define LED_PIN3 4
#define LED_PIN4 5
#define LED_PIN5 6
#define LED_PIN6 7
#define LED_PIN7 8
#define BUTTON_PIN 9

// Store previous button state to detect changes
byte lastButtonState;

// Store whether or not the LED sequence should be ON or OFF
byte ledState = LOW;

// Button debounce timing
unsigned long lastTimeButtonStateChanged = millis();
unsigned long debounceDuration = 50;  // debounce time in milliseconds


void setup() {
  // Configure all LED pins as outputs
  pinMode(LED_PIN1, OUTPUT);
  pinMode(LED_PIN2, OUTPUT);
  pinMode(LED_PIN3, OUTPUT);
  pinMode(LED_PIN4, OUTPUT);
  pinMode(LED_PIN5, OUTPUT);
  pinMode(LED_PIN6, OUTPUT);
  pinMode(LED_PIN7, OUTPUT);

  // Configure the button pin as an input
  // IMPORTANT- The assumption is that a pull down resistor is being used
  pinMode(BUTTON_PIN, INPUT);

  // Read the initial button state at startup
  lastButtonState = digitalRead(BUTTON_PIN);
}


void loop() {

  // Check debounce timing
  if (millis() - lastTimeButtonStateChanged >= debounceDuration) {

    // Read current state button
    byte buttonState = digitalRead(BUTTON_PIN);

    // If button state changed since the last check...
    if (buttonState != lastButtonState) {

      // Record the time of this change (later used for debounce timing)
      lastTimeButtonStateChanged = millis();

      // Update stored button state
      lastButtonState = buttonState;

      // Only act when the button is RELEASED (LOW)
      // This should ensure only one trigger per button cycle
      if (buttonState == LOW) {

        // Toggle the LED state variable
        if (ledState == HIGH) {
          ledState = LOW;  // If LEDs were ON, turn them OFF
        } else {
          ledState = HIGH;  // If LEDs were OFF, start the sequence
        }

        // If LEDs are supposed to be ON
        if (ledState == HIGH) {

          // Turn on LEDs one at a time with a delay
          //IMPORTANT--You have 7 seconds of delay that prevents anything else from happening
          digitalWrite(LED_PIN1, HIGH);
          delay(1000);

          digitalWrite(LED_PIN2, HIGH);
          delay(1000);

          digitalWrite(LED_PIN3, HIGH);
          delay(1000);

          digitalWrite(LED_PIN4, HIGH);
          delay(1000);

          digitalWrite(LED_PIN5, HIGH);
          delay(1000);

          digitalWrite(LED_PIN6, HIGH);
          delay(1000);

          digitalWrite(LED_PIN7, HIGH);
          delay(1000);
        }

        // If LEDs are supposed to be OFF
        else {
          digitalWrite(LED_PIN1, LOW);
          digitalWrite(LED_PIN2, LOW);
          digitalWrite(LED_PIN3, LOW);
          digitalWrite(LED_PIN4, LOW);
          digitalWrite(LED_PIN5, LOW);
          digitalWrite(LED_PIN6, LOW);
          digitalWrite(LED_PIN7, LOW);
        }
      }
    }
  }
}

You could probably light your LEDs in a for loop. It would be a little tidier. Also, if nothing NEVER needs to happen while the LEDs are being lit, the delays are fine. If you ever want to expand the code to where something else might need to happen while they are being lit, time them using the millis().

need to use a timer so that the button can be checked while the sequence is running

logic is someone tricky to recognize what when off, the sequence is running or has completed

// start/reset LED sequence when button pressed

const byte PinBut     = 9;
const byte PinLeds [] = { 2, 3, 4, 5, 6, 7, 8 };
const int  Nled       = sizeof(PinLeds);

enum { Off = HIGH, On = LOW };      // depends on hardware
const int Pressed = LOW;

int           butState;
int           idx = 0;
bool          run;
unsigned long msec0;

// -----------------------------------------------------------------------------
void loop ()
{
    unsigned long msec = millis ();
    if (run && msec - msec0 >= 1000) {
        msec0 = msec;

        digitalWrite (PinLeds [idx], On);
        if (Nled <= idx++)
            run = false;
    }

    byte but = digitalRead (PinBut); 
    if (butState != but)  {
        butState  = but;
        delay (30);             // debounce

        if (Pressed  == but)  {
            if (0 < idx)  {                         // 1 or all LEDs on
                for (int n = 0; n < Nled; n++)
                    digitalWrite (PinLeds [n], Off);
                idx = 0;
                run = false;                        // may still be running
            }

            else if (! run)  {                      // not running
                msec0 = 0;                          // turn on immediately
                idx   = 0;
                run   = true;
            }
        }
    }
}

// -----------------------------------------------------------------------------
void setup ()
{
    Serial.begin (9600);

    pinMode (PinBut, INPUT_PULLUP);
    butState = digitalRead (PinBut);

    for (int n = 0; n < Nled; n++)  {
        pinMode (PinLeds [n], OUTPUT);
        digitalWrite (PinLeds [n], Off);
    }
}

At no time does the original code turn the LEDs off.

The main goal is to change from a state of "cycling LEDs" to "NOT cycling LEDs" which is initiated by a button press. This sketch uses a "turn all LEDs off" function in both "cycle LEDs" and "NOT cycle LEDs" to simplify the code.

#define BUTTON_PIN 9
int ledPin[] = {2, 3, 4, 5, 6, 7, 8};
int numLeds = sizeof(ledPin) / sizeof(ledPin[0]);
bool cyclestate = LOW, buttonState, lastButtonState;
unsigned long timer, timeout = 50; // milliseconds
int i, j;

void setup() {
  for (byte i = 0; i < numLeds; i++) {
    pinMode(ledPin[i], OUTPUT);
  }
  pinMode(BUTTON_PIN, INPUT_PULLUP);
}

void loop() {
  byte buttonState = digitalRead(BUTTON_PIN);
  delay(10); // cheap button debounce
  if (buttonState == LOW && lastButtonState == HIGH) // LOW = button PRESSED
    cyclestate = !cyclestate; // ... change LED cycle state

  if (cyclestate == HIGH)
    ledCycle(); // cycle the LEDs
  if (cyclestate == LOW)
    ledOff(); // turn LEDs off

  lastButtonState = buttonState; // store last button state
}

void ledCycle() {
  if (millis() - timer > timeout) { // cycle timeout exceeded...
    timer = millis(); // ... reset cycle timer
    if (i == numLeds) // count number of LEDs
      i = 0; // reset count
    ledOff(); // turn all LEDs OFF
    digitalWrite(ledPin[i], HIGH); // turn this LED ON
    i++; // next LED
  }
}

void ledOff() {
  for (byte i = 0; i < numLeds; i++) // count all LEDs...
    digitalWrite(ledPin[i], LOW); // ... turn OFF
}

Here’s a way to approach it..