How to loop something until another button is registered

Hey guys, I'm a high school student making an LED sign for my schools studio team. This is my first project on the Arduino and programming in general. I'm using an led strip and the FastLED library. I want to make a "mode" in which the LEDs go back and forth until another button is pressed in which it stops and changes its color via the button pressed. I tried to first use a while statement, but that seemed to just loop the LED's back and forth forever and not acknowledging the other buttons being pressed. What would you guys recommend me to do or learn? I appreciate the help!

#include <FastLED.h>                                                                                                                         

#define NUM_LEDS 144
#define LED_PIN 10
#define BRIGHTNESS 10

CRGB myLeds[NUM_LEDS];

int switchState = 0;
int switchState1 = 0;
int switchState2 = 0;


void setup() {
 
pinMode(3, INPUT);
pinMode(4, INPUT);
pinMode(5, INPUT);


 FastLED.addLeds<WS2812B, LED_PIN, GRB>(myLeds, NUM_LEDS);
  FastLED.setMaxPowerInVoltsAndMilliamps(5, 500);
  FastLED.setBrightness(BRIGHTNESS);
  FastLED.clear();
  FastLED.show();
}

void loop() {

switchState = digitalRead(3);
switchState1 = digitalRead(4);
switchState2 = digitalRead(5);

if (switchState == 1) {
FastLED.clear();
    fill_solid(myLeds, NUM_LEDS, 0xFF0000);
    FastLED.show();
}


if (switchState1 == 1) {
FastLED.clear();
    fill_solid(myLeds, NUM_LEDS, 0x000066);
    FastLED.show();
}


//I want this to loop until another button is pressed
if (switchState2 == 1) {


  for (int i = 0; i < 36; i++) {
    myLeds[i] = 0xFFFFFF;
     FastLED.show();
       delay(15);
}
  for (int i = 36; i < 72; i++) {
    myLeds[i] = 0x0F64CD;
     FastLED.show();  
     delay(15);
}
  for (int i = 72; i < 108; i++) {
    myLeds[i] = 0xCD2E3A;
     FastLED.show();
      delay(15);
 }
  for (int i = 108; i < 144; i++) {
    myLeds[i] = 0xFFFFFF;
     FastLED.show();
     delay(15);
 }

 for (int i = 143; i >= 0; i--) {
   myLeds[i] = CRGB::Black;
     FastLED.show();
     delay(15);

   }
  }
}

Try this:

Dig into Finite State Machines, or FSM. Your project sounds like an fsm. There are many examples around this forum and elsewhere.

You will have to be more specific about how your circuit should work.

1 Like

Suppose that instead of a while-loop you use an If() instead and let loop() turn the crank?

1 Like

If the pin is set to INPUT_PULLUP, a switch to GND won't float the pin.

1 Like

Rather than using these "for" loops, try this:

  • start a counter ("i") at 0 and "i++" to 144.
  • "if" the counter is in a selected range, make the pixel a color

of course the buttons aren't checked while the code is stuck in the loops.

there need to be separate blocks of code in loop() that check for button presses and check if some timed event has expired. see Blink without delay

but in your case there's also different sequences of events, not that there are multiple different timed events, but that after one sequence completes another starts.

in your case, it looks like there's just one type of activity, setting a particular LED, your 'i', to a particular value during each sequence and it's the parameters that change, the value and direction that i changes

one approach is to capture the parameters in a data structure and a set of parameters. in your case the parameters are

  • LED value
  • index, you "i" value that the parameter takes effect at
  • direction the "i" changes +/- 1

arrays can be used. see The C Programming Language pg 23

Hi thanks for the reply, could you please explain what letting loop() turn the crank means?

1 Like

look this over
not a complete solution for you

#include <FastLED.h>

#define NUM_LEDS 144
#define LED_PIN 10
#define BRIGHTNESS 10

CRGB myLeds[NUM_LEDS];
int  ledIdx;

const byte Sw0 = 3;
const byte Sw1 = 4;
const byte Sw2 = 5;

#define On  HIGH

int switchState = 0;
int switchState1 = 0;
int switchState2 = 0;

bool run = true;

unsigned long msec0;

void loop ()
{
    unsigned long msec = millis ();

    if (run && msec - msec0 >= 15)  {
        msec0 = msec;
        Serial.println (ledIdx);

        myLeds [ledIdx++] = 0xFFFFFF;
        if (NUM_LEDS <= ledIdx)  {
            ledIdx = 0;
            run    = false;
            Serial.println ("done");
        }
        FastLED.show();
    }

    switchState  = digitalRead(Sw0);
    switchState1 = digitalRead(Sw1);
    switchState2 = digitalRead(Sw2);

    if (switchState == On) {
        FastLED.clear();
        fill_solid(myLeds, NUM_LEDS, 0xFF0000);
        FastLED.show();
    }

    if (switchState1 == On) {
        FastLED.clear();
        fill_solid(myLeds, NUM_LEDS, 0x000066);
        FastLED.show();
    }

    //I want this to loop until another button is pressed
    if (switchState2 == On)  {
        run   = true;
        msec0 = msec;
    }
}

void setup() {
    Serial.begin (9600);
    Serial.println (run);

    pinMode(Sw0, INPUT_PULLUP);
    pinMode(Sw0, INPUT_PULLUP);
    pinMode(Sw2, INPUT_PULLUP);

    FastLED.addLeds<WS2812B, LED_PIN, GRB>(myLeds, NUM_LEDS);
    FastLED.setMaxPowerInVoltsAndMilliamps(5, 500);
    FastLED.setBrightness(BRIGHTNESS);
    FastLED.clear();
    FastLED.show();
}
1 Like

Look into how this works:
https://www.arduino.cc/reference/en/language/structure/control-structure/switchcase/

// Define os pinos para o botão e o LED
const int buttonPin = 2;
const int ledPin = 13;

// Variável para armazenar o estado atual do botão
int buttonState = 0;

void setup() {
// Configura o pino do botão como entrada
pinMode(buttonPin, INPUT);

// Configura o pino do LED como saída
pinMode(ledPin, OUTPUT);
}

void loop() {
// Lê o estado do botão
buttonState = digitalRead(buttonPin);

// Se o botão for pressionado
if (buttonState == HIGH) {
// Loop para piscar o LED rapidamente
for (int i = 0; i < 10; i++) {
digitalWrite(ledPin, HIGH); // Liga o LED
delay(100); // Aguarda 100ms
digitalWrite(ledPin, LOW); // Desliga o LED
delay(100); // Aguarda 100ms
}

// Loop para piscar o LED lentamente
for (int i = 0; i < 10; i++) {
  digitalWrite(ledPin, HIGH); // Liga o LED
  delay(500); // Aguarda 500ms
  digitalWrite(ledPin, LOW); // Desliga o LED
  delay(500); // Aguarda 500ms
}

}
}

@nathan_kim - this post and the thread it is on might be worth the time

a7

the name of function "loop" does what the name says:

It loops. Always. For ever. Infinitely. (As long as power is switched on)

As long as the for-loop runs the only code that is inside the for-loop is executed.
This is called blocking code.

You need NON-blocking code.
And this means zero while-loops, zero for-loops.

The only loop that is looping is
void loop() itself

If the other explains did not serve,

In a for loop, the loop goes around until the middle, exit condition is met. Around and around, the for-loop turns the crank to go around.
This is an imagine.

With void loop() you have every code inside running over and over,

what part to run depends on conditions like the for-loop only void loop provides no index as for-loop has or exit or change like i++ when it does loop --- to use void loop() to replace inside loops, you have to add lines to check for exit/done and change the index that for-loop (aka for-next in Basic) but there are advantages that way especially when you ditch the delays for using "timers" which you are NOT ready for today but are walking up on.

Others have already posted details. Don't get confused, find the common parts and maybe draw a picture.. and keep asking good questions!

i am guessing, you are one of the smart ones?

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