Using a pushbutton as a switch and looping a LED sequence accordingly

Hi guys!

So I figured out how to use a push button as a switch using code I found online. The if function tests for the buttonState and then activates one of the LED sequences.

Inside this if function is another if function, which contains the 2 sequences. Inside the else the LED´s are constantly on, which is fine and works well. If I press the button the blinking sequence is executed, which also works fine. But I want the blinking to loop until I press the button again.

I tried using a while function for the blinking sequence but at the end the state is set back to LOW, so that doesnt work.. Does anybody have an idea how to do this? So I can use the button to change between static light and my blinking sequence?

Thanks in advance!
Tim

// the setup function runs once when you press reset or power the board
  int ledpinhintenrot4 = 13;
  int ledpinhintenblau1 = 12;
  int ledpinhintenblau2 = 11;
  int ledpinhintenblau3 = 10;
  int ledpinhintenblau4 = 9;
  int ledpinhintenrot1 =8;
  int ledpinhintenrot2 =7;
  int ledhintenrot=4;
  int ledpinvorneweis=5;
  int ledpinhintenrot=6;
  int buttonPower = A5;
  int buttonInput = A3;
  int state =0;
  long time=0;
  
  long i= 1;
  
  long debounce = 200;
  
  int buttonState =0;
  int previous = LOW;

void setup() {
  // initialize digital pin LED_BUILTIN as an output.int 
  
  pinMode(ledpinhintenblau1, OUTPUT);
  pinMode(ledpinhintenblau2,OUTPUT);
  pinMode(ledpinhintenblau3,OUTPUT);
  pinMode(ledpinhintenblau4, OUTPUT);
  pinMode(ledpinhintenrot1,OUTPUT);
  pinMode(ledpinhintenrot2,OUTPUT);
  pinMode(ledpinhintenrot4,OUTPUT);
  pinMode(ledpinvorneweis,OUTPUT);
  pinMode(ledpinhintenrot,OUTPUT); 
  pinMode(ledhintenrot,OUTPUT);
  pinMode(buttonPower,OUTPUT);
  pinMode(buttonInput,INPUT);
  
}


void loop() {
  
  buttonState = digitalRead(buttonInput);
    digitalWrite(buttonPower,HIGH);

  
   if (buttonState == HIGH && previous == LOW && millis() - time > debounce) {
    if (state == HIGH)  {
           
    digitalWrite(ledpinhintenblau1, HIGH);
    digitalWrite(ledpinhintenblau2,HIGH);
    digitalWrite(ledpinhintenblau3,HIGH);
    digitalWrite(ledpinhintenblau4,HIGH);
    digitalWrite(ledpinhintenrot1, HIGH);
    digitalWrite(ledpinhintenrot2,HIGH);
    digitalWrite(ledpinhintenrot4,HIGH);
    digitalWrite(ledpinvorneweis,HIGH);
    digitalWrite(ledpinhintenrot,HIGH);
    digitalWrite(ledhintenrot,HIGH);
  
  
    delay(200);
 
    digitalWrite(ledpinhintenblau1, LOW);
    digitalWrite(ledpinhintenblau2,LOW);
    digitalWrite(ledpinhintenblau3,LOW);
    digitalWrite(ledpinhintenblau4,HIGH);
  
    digitalWrite(ledpinhintenrot1, HIGH);
    digitalWrite(ledpinhintenrot2,HIGH);
    digitalWrite(ledpinhintenrot4,HIGH);
    digitalWrite(ledpinvorneweis,HIGH);
    digitalWrite(ledpinhintenrot,HIGH);
    digitalWrite(ledhintenrot,HIGH);
  
  
    delay(100);
  
    digitalWrite(ledpinhintenblau1, HIGH);
    digitalWrite(ledpinhintenblau2,HIGH);
    digitalWrite(ledpinhintenblau3,HIGH);
    digitalWrite(ledpinhintenblau4,HIGH);
    digitalWrite(ledpinhintenrot1, HIGH);
    digitalWrite(ledpinhintenrot2,HIGH);
    digitalWrite(ledpinhintenrot4,HIGH);
    digitalWrite(ledpinvorneweis,HIGH);
    digitalWrite(ledpinhintenrot,HIGH);
    digitalWrite(ledhintenrot,HIGH);
    
    delay(200);
  
    digitalWrite(ledpinhintenblau1, LOW);
    digitalWrite(ledpinhintenblau2,LOW);
    digitalWrite(ledpinhintenblau3,LOW);
    digitalWrite(ledpinhintenblau4,HIGH);
    digitalWrite(ledpinhintenrot1, HIGH);
    digitalWrite(ledpinhintenrot2,HIGH);
    digitalWrite(ledpinhintenrot4,HIGH);
    digitalWrite(ledpinvorneweis,HIGH);
    digitalWrite(ledpinhintenrot,HIGH);
    digitalWrite(ledhintenrot,HIGH);
  
    delay(1300);
  
      
      
  state = LOW;
      
   }
      
    else {
      
      
      
      
      digitalWrite(ledpinhintenblau1, HIGH);
      digitalWrite(ledpinhintenblau2,HIGH);
      digitalWrite(ledpinhintenblau3,HIGH);
      digitalWrite(ledpinhintenblau4,HIGH);
      digitalWrite(ledpinhintenrot1, HIGH);
      digitalWrite(ledpinhintenrot2,HIGH);
      digitalWrite(ledpinhintenrot4,HIGH);
      digitalWrite(ledpinvorneweis,HIGH);
      digitalWrite(ledpinhintenrot,HIGH);
      digitalWrite(ledhintenrot,HIGH);
  
      state = HIGH;
      
      
        
    }
    
    time = millis();    
  }

  digitalWrite(buttonInput, state);
  
  previous = buttonState;
    
    
  
  
}

Speaking as a total newbie here.

It looks like both sets of LED activation live inside the IF that is checking to see if the button is pressed. If I am reading that right, then the only time that either LED routine could happen is when the button is pressed and would only happen once per button press.

I would probably move the LED activation outside of the IF. I would then create an overall "mode" variable to determine if you are in "sequence" mode or "constant" mode. I would then poll the switch on each loop to see if it needs to toggle the mode variable to the other mode. Putting the LED activations into functions and using function calls might make it easier to read.

The other difficulty is that you can't really poll the switch during all of those sequences with delays, so you would have to hold the button down until it finishes what it is doing. So, if you wanted faster button press recognition you would either need to replace the delays with more modes and timers or I supposed you could have the button run an interrupt that just toggles the mode.

What is the purpose of this line of code?

  digitalWrite(buttonInput, state);

I don't think it does whatever you intend. From the Arduino reference:

"If the pin is configured as an INPUT, digitalWrite() will enable (HIGH) or disable (LOW) the internal pullup on the input pin. It is recommended to set the pinMode() to INPUT_PULLUP to enable the internal pull-up resistor."

You can solve your problem by using millis() and making your LED sequence a state machine. That way you can monitor the button input while executing your LED sequence.

How is your button wired?

For a start this makes no sense to me

digitalWrite(buttonInput, state);

If the variable name was buttonPin the problem might be more obvious. If an I/O pin is set at INPUT then writing a HIGH to it turns on the internall pullup resistor and writing a LOW turns it off. I'm pretty sure that is not what you want to do.

It would be better to read the button and check if it has just been pressed with code like this rather than mix it up with other IF tests

previousButtonState = buttonState;
buttonJustPressed = false;
if (millis() - millis() - time > debounce) {
     time = millis();
     buttonState = digitalRead(buttonPin);
     if (buttonState == LOW and previousButtonState == HIGH) {
         buttonJustPressed = true;
     }
}

Then, in place of this

if (buttonState == HIGH && previous == LOW && millis() - time > debounce) {

you have

if (buttonJustPressed == true) {

This code seems to appear almost unchanged several times

           digitalWrite(ledpinhintenblau1, HIGH);
            digitalWrite(ledpinhintenblau2,HIGH);
            digitalWrite(ledpinhintenblau3,HIGH);
            digitalWrite(ledpinhintenblau4,HIGH);
            digitalWrite(ledpinhintenrot1, HIGH);
            digitalWrite(ledpinhintenrot2,HIGH);
            digitalWrite(ledpinhintenrot4,HIGH);
            digitalWrite(ledpinvorneweis,HIGH);
            digitalWrite(ledpinhintenrot,HIGH);
            digitalWrite(ledhintenrot,HIGH);

If you put it in a function you don't need to type all the repeats with the risk of errors. Actually I think all but the first three rows are always the same so they could actually go in setup().

If you want a responsive button then you must get rid of all the delay()s. Have a look at how millis() is used to manage timing without blocking in Several Things at a Time.

And see Using millis() for timing. A beginners guide if you need more explanation.

...R

...R

Just for fun I coded this up. It can switch between the two LED modes continuously using the button. The nice thing is you can modify or add to the LED sequence just by updating the ledSeq array.

It compiles but I could not test it. Perhaps it will make sense to you.

const int ledpinhintenrot4 = 13;
const int ledpinhintenblau1 = 12;
const int ledpinhintenblau2 = 11;
const int ledpinhintenblau3 = 10;
const int ledpinhintenblau4 = 9;
const int ledpinhintenrot1 = 8;
const int ledpinhintenrot2 = 7;
const int ledhintenrot = 4;
const int ledpinvorneweis = 5;
const int ledpinhintenrot = 6;
const int buttonPower = A5;
const int buttonInput = A3;
int state = 0;
long time = 0;
long debounce = 200;
int buttonState;
int previous = LOW;

const int ledPins[] = 
{  
  ledpinhintenrot4,  
  ledpinhintenblau1,  
  ledpinhintenblau2,  
  ledpinhintenblau3,  
  ledpinhintenblau4,  
  ledpinhintenrot1,  
  ledpinhintenrot2,  
  ledhintenrot,  
  ledpinvorneweis,  
  ledpinhintenrot
};

const int numLeds = sizeof(ledPins)/sizeof(ledPins[0]);

enum ledMode_enum
{
  LEDS_ON,
  LEDS_SEQ
};

struct ledSeq_struct
{
  byte ledState[numLeds];
  unsigned long ledDelayMS;
};

ledMode_enum ledMode = LEDS_ON;
ledSeq_struct ledSeq[] =
{
  {{HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH}, 200},
  {{LOW,  LOW,  LOW,  HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH}, 100},
  {{HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH}, 200},
  {{LOW,  LOW,  LOW,  HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH}, 1300}
};

const int ledSeqLength = sizeof(ledSeq)/sizeof(ledSeq_struct);

void setup() 
{
  // initialize digital pin LED_BUILTIN as an output.int
  pinMode(ledpinhintenblau1, OUTPUT);
  pinMode(ledpinhintenblau2, OUTPUT);
  pinMode(ledpinhintenblau3, OUTPUT);
  pinMode(ledpinhintenblau4, OUTPUT);
  pinMode(ledpinhintenrot1, OUTPUT);
  pinMode(ledpinhintenrot2, OUTPUT);
  pinMode(ledpinhintenrot4, OUTPUT);
  pinMode(ledpinvorneweis, OUTPUT);
  pinMode(ledpinhintenrot, OUTPUT);
  pinMode(ledhintenrot, OUTPUT);
  pinMode(buttonPower, OUTPUT);
  pinMode(buttonInput, INPUT);
}


void loop() 
{
  static int ledSeqNum = 0;
  static bool ledDelay = false;
  static unsigned long previousDelayTime = millis();
  
  buttonState = digitalRead(buttonInput);
  digitalWrite(buttonPower, HIGH);
  if (buttonState == HIGH && previous == LOW && millis() - time > debounce) 
  {
    // Switch LED modes
    if (ledMode == LEDS_ON) 
    {
      ledMode = LEDS_SEQ;
      previousDelayTime = millis();
      // Start with sequence 0
      ledSeqNum = 0;
      for (int ledNum = 0; ledNum < numLeds; ledNum++)
      {
        digitalWrite(ledPins[ledNum], ledSeq[0].ledState[ledNum]);
      }
    }
    else if (ledMode == LEDS_SEQ)
    {
      ledMode = LEDS_ON;
      for (int ledNum = 0; ledNum < numLeds; ledNum++)
      {
        digitalWrite(ledPins[ledNum], HIGH);
      }
    }
    time = millis();
  }
  previous = buttonState;

  if (ledMode == LEDS_SEQ)
  {
    if (millis() - previousDelayTime >= ledSeq[ledSeqNum].ledDelayMS)
    {
      previousDelayTime = millis();
      ledSeqNum++;
      ledSeqNum%=ledSeqLength;
      for (int ledNum = 0; ledNum < numLeds; ledNum++)
      {
        digitalWrite(ledPins[ledNum], ledSeq[ledSeqNum].ledState[ledNum]);
      }
    }
  }
}

@ToddL1962 Thank you! It works!
And also thank you to @Robin2 and all others! I now have a lot more inside into how to do this and why it didnt work!

Have a great week!