4 leds and a button

Hello! I'm new with this forum and Arduino. Currently I'm working with a project with 4 LEDs and a button. The point is, when you're pressing the button, LEDs are turning off and on (first LED is on,then it goes off, then second LED is on, then goes off...). When I press the button, it's working (LED's are turning on and off), but when I release the button, LEDs will go off but only when the former command is completed (for example, when I release the button while the second LED is off, first the third LED will go on and off, then fourth and after that all LEDs will go off). I don't know how to fix this, so if anyone could help me, I will be grateful.

#include <Bounce2.h>
int pin[4] = {7, 6, 5, 4};
int btn = 8;
int dt = 250;
Bounce b = Bounce();
void setup() {
  b.attach(btn, INPUT);
  b.interval(250);
  pinMode(pin[0], OUTPUT);
  pinMode(pin[1], OUTPUT);
  pinMode(pin[2], OUTPUT);
  pinMode(pin[3], OUTPUT);
}
void loop() {
  int g = digitalRead(btn);
  if (g == 0) {
    digitalWrite(pin[0], HIGH);
    delay(dt);
    digitalWrite(pin[0], LOW);
    digitalWrite(pin[1], HIGH);
    delay(dt);
    digitalWrite(pin[1], LOW);
    digitalWrite(pin[2], HIGH);
    delay(dt);
    digitalWrite(pin[2], LOW);
    digitalWrite(pin[3], HIGH);
    delay(dt);
    digitalWrite(pin[3], LOW);
  }
  if (g == 1) {
    digitalWrite(pin[0], LOW);
    digitalWrite(pin[1], LOW);
    digitalWrite(pin[2], LOW);
    digitalWrite(pin[3], LOW);
  }
}

I forgot to mention, when you release the button, all LEDs must go off.

your code is stuck/blocked in the delays as soon as you press the button

study blink without delay. a small state machine would be a good way to architect the code

Thanks! I didn't used millis because I don't know to use it very well. I'll try it, thanks again!

Some millis() tutorials:Non-blocking timing tutorials:
Blink without delay().
Beginner's guide to millis().
Several things at a time.

State change detection might be helpful.

One of the first thing you should try out is blinking 2 or more LEDs at different frequencies. This can only be accomplished with a non-blocking state machine, so the usefulness and the purpose of a millis() based timer becomes self-evident.

Six or more LEDs with periods in the range of 200-500 ms, but with small differences of 1 or 2 ms, make interesting chasing patterns if you watch them go for a few minutes.

Hello
This task seems to be a scholl assigment.
Take some time and make a search inside the forum.
I guess you will find several solutions.
Have a nice day and enjoy coding in C++.

Hi guys. First of all, thanks for the all replies and tips. I managed to learn some basics of millis, but I don't know how to do this. I had an idea, but it's not working . LEDs are on when I press, but they're not turning on and off. When I release the button, they're off. That part is working. Here's the code:

#include <Bounce2.h>
int pin[4] = {7, 6, 5, 4};
int btn = 8;
int dt = 250;
int pt = 0;
int state = LOW;
Bounce b = Bounce();
void setup() {
  b.attach(btn, INPUT);
  b.interval(250);
  pinMode(pin[0], OUTPUT);
  pinMode(pin[1], OUTPUT);
  pinMode(pin[2], OUTPUT);
  pinMode(pin[3], OUTPUT);
}
void loop() {
  int g = digitalRead(btn);
  int ct = millis();
  if(g==0){
      digitalWrite(pin[0],HIGH);
      if(ct-pt>=dt){
      pt=ct;
      digitalWrite(pin[0],LOW);
      }
      digitalWrite(pin[1],HIGH);
      if(ct-pt>=dt){
      pt=ct;
      digitalWrite(pin[1],LOW);
      }    
      digitalWrite(pin[2],HIGH);
      if(ct-pt>=dt){
      pt=ct;
      digitalWrite(pin[2],LOW);
      }
      digitalWrite(pin[3],HIGH);
      if(ct-pt>=dt){
      pt=ct;
      digitalWrite(pin[3],LOW);
      }
      }
      if(g==1){
        digitalWrite(pin[0],LOW);
        digitalWrite(pin[1],LOW);
        digitalWrite(pin[2],LOW);
        digitalWrite(pin[3],LOW);
        }
  }

millis() returns an unsigned long, not an int

Why do you have stuff not depending on time in the if?

Sorry, I fixed that (unsigned long). What do you mean by that (sorry I'm really tired and stupid)? I tried to replace delay with millis()

Sad waste of an array.

but a nice try

Everyone's lives, including yours in a few months' time when you try to make sense of old code, will be a lot simpler if you use words like currentTime and so on for variable names.

You're not using the bounce library properly- in fact I don't think you're using it at all.

Have a look at the examples that come with the library... you need to do a bounce.update() each time through loop(), and also you shouldn't do a normal digitalRead() any more... the example has a line like this which replaces the normal digitalRead():

int deboucedInput = bounce.read();

Hello
All in all your sketch needs a time- and button handler for the led sequencer and debouncing.
C++ provides a lot smart instruction eg "struct" to built logical groups for the usage of User Defined Datatypes (UDT). The LED sequencer could be one of these contatining the timing and the ON/OFF sequence to be executed by a how ever contolled timer function.
Have nice day and enjoy coding in C++.

Tired possibly - stupid I would not say so as your attempt is a constructive step forward.

When you look at

I see requests to turn on leds that are independent of the timing comparison, so this will happen every time you cycle through the loop/if

Is that intended?

The logic could be

  • record start time upon initial button press (state change detection). Do that only once if the button stays pressed
  • if button is still pressed, use current time comparison with that start time to decide which leds should be on or off
  • if button is released, turn everything off
  • rinse and repeat

HI guys. Just wanted to say thank you for the all replies and tips. I did it! It's working now. Thanks a lot!

Well done that man.

You could post the final sketch to help the next person with similar issues.

Okay, here it is:

int pin[4] = {7, 6, 5, 4};
int btn = 8;
unsigned long dt = 250;
unsigned long pt = 0;
int state;
void setup() {
  pinMode(btn,INPUT);
  pinMode(pin[0], OUTPUT);
  pinMode(pin[1], OUTPUT);
  pinMode(pin[2], OUTPUT);
  pinMode(pin[3], OUTPUT);
}
void loop() {
  int g = digitalRead(btn);
  if (g == 0) {
    switch (state) {
      case (0): digitalWrite(pin[0], HIGH);
        break;
      case (1): digitalWrite(pin[0], LOW);
        break;
      case (2): digitalWrite(pin[1], HIGH);
        break;
      case (3): digitalWrite(pin[1], LOW);
        break;
      case (4): digitalWrite(pin[2], HIGH);
        break;
      case (5): digitalWrite(pin[2], LOW);
        break;
      case (6): digitalWrite(pin[3], HIGH);
        break;
      case (7): digitalWrite(pin[3], LOW);
        break;
    }
    if (millis() - pt > dt && state == 0) {
      state = 1;
      pt = millis();
    }
    if (millis() - pt > dt && state == 1) {
      state = 2;
      pt = millis();
    }
    if (millis() - pt > dt && state == 2) {
      state = 3;
      pt = millis();
    }
    if (millis() - pt > dt && state == 3) {
      state = 4;
      pt = millis();
    }
    if (millis() - pt > dt && state == 4) {
      state = 5;
      pt = millis();
    }
    if (millis() - pt > dt && state == 5) {
      state = 6;
      pt = millis();
    }
    if (millis() - pt > dt && state == 6) {
      state = 7;
      pt = millis();
    }
    if (millis() - pt > dt && state == 7) {
      state = 0;
      pt = millis();
    }
  }
  if (g == 1) {
    digitalWrite(pin[0], LOW);
    digitalWrite(pin[1], LOW);
    digitalWrite(pin[2], LOW);
    digitalWrite(pin[3], LOW);
  }
}

Does this approach suit your needs? It reacts in a timely manner as you need, and resets when the button is released. It is using delay not millis() though, so even though it reacts as if it's not-blocking, if you add more code it will be at the mercy of the two 250ms delays:

#define LED1_PIN 4
#define LED2_PIN 5
#define LED3_PIN 6
#define LED4_PIN 7
#define BTN_PIN 8
#define DELAY_TIME 250

int leds[] = {LED1_PIN, LED2_PIN, LED3_PIN, LED4_PIN};
const byte NUM_LEDS = sizeof(leds) / sizeof(leds[0]);

void setup() {
  Serial.begin(9600);
  pinMode(BTN_PIN, INPUT_PULLUP);
  for (byte i = 0; i<NUM_LEDS; i++) {
    pinMode(leds[i], OUTPUT);
  }
}
void loop() {
  static byte lastLED = 4;
  static byte nextLED = 0;

  bool buttonState = digitalRead(BTN_PIN);
  
  if (!buttonState){
    digitalWrite(leds[lastLED], LOW);
    delay(DELAY_TIME);
    digitalWrite(leds[nextLED], HIGH);
    delay(DELAY_TIME);
    lastLED = nextLED;
    ++nextLED %= 4;
  }
  else {
    for (byte i = 0; i < NUM_LEDS; i++) {
      digitalWrite(leds[i], LOW);
      lastLED = 4;
      nextLED = 0;
    }
  }
}

See it in action here: sketch.ino - Wokwi Arduino Simulator