Want to get rid of delay() function, FastLED, PLEASE HELP

Hi there!

I am making a project with 3 layers of leds, one on top of the other, 8 leds per strip. Im trying to figure out how to replace the delay() function so that i can add a momentary pushbutton in the future, already knowing that a delay() in the for loop will prevent other actions of my pushbutton.
This simple code below has one led go up each strip, one strip at a time, to make it look like its spiralling up the project ive created. I want to keep that effect.

I dont have the pushbutton written into the code yet. Also, i know about using millis(), but ive tried every combination.
Is there something in the FastLED library that could help me?
My end goal will be to switch through various lighting functions, about 12 different ones, without getting stuck at any delays.

Here is the basic code i have:

#include <FastLED.h>

#define NUM_STRIPS    3
#define NUM_LEDS      8
#define COLOR_ORDER   GRB
#define LED_TYPE      WS2812B

CRGB leds[NUM_STRIPS][NUM_LEDS];

//Pin locations for LED strips
const int lowerLEDs = 5;
const int middleLEDs = 6;
const int upperLEDs = 7;



void setup() {
  delay(3000);      //For recovery

 //Add led strip arrays 
  FastLED.addLeds<LED_TYPE, lowerLEDs, COLOR_ORDER>(leds[0], NUM_LEDS);
  FastLED.addLeds<LED_TYPE, middleLEDs, COLOR_ORDER>(leds[1], NUM_LEDS);
  FastLED.addLeds<LED_TYPE, upperLEDs, COLOR_ORDER>(leds[2], NUM_LEDS);

  currentTime = millis();
  
}




void loop() {
  for(int x = 0; x < NUM_STRIPS; x++) {
    for(int i = 0; i < NUM_LEDS; i++) {
      leds[x][i] = CRGB::Red;
      FastLED.show();
      leds[x][i] = CRGB::Black;
      delay(100);                                          //THIS IS WHAT I WANT TO GET RID OF. 
    }
  }
 
}

THANKS SO MUCH FOR ANY FEEDBACK <3

You can't use for loops, so you need to pick what your for loops do for you, and implement the equivalent using the technique in the blink without delay example in the IDE.

This hack may be useful. Read the thread and see.

a7

What? I use them in most of my FastLED projects.
For example:

// Function to light up all LEDs as gray, but with every 
// tenth LED green and every hundredth is yellow.
void lightEmUp() {
  fill_solid(leds, NUM_LEDS, CRGB::DimGrey);
  for (int i = 0; i < NUM_LEDS; i++) {
    int j = i % 10;                     //j==0 every ten steps
    if (j == 0)  leds[i] = CRGB::Green;
    j = i % 100;                        //j==0 every hundred steps
    if (j == 0)  leds[i] = CRGB::Yellow;
  }
  FastLED.show();
}

Show us what you have tried.

…like these with a honking delay in the body:

    for(int i = 0; i < NUM_LEDS; i++) {
      leds[x][i] = CRGB::Red;
      FastLED.show();
      leds[x][i] = CRGB::Black;
      delay(100);                                          //THIS IS WHAT I WANT TO GET RID OF. 
    }

HTH

a7

Compare that code with the 'for' loop posted by OP. Note the big, fat 100 ms delay in the latter. Not to mention 'FastLED.show()' getting called on every iteration.

You could just replace the delay, with a timed loop where you check the button. If pressed then jump out and go onto the next pattern. It's effectively the same approach as per the solution in #3.

#include <FastLED.h>

#define NUM_STRIPS    3
#define NUM_LEDS      8
#define COLOR_ORDER   GRB
#define LED_TYPE      WS2812B


#define DELAY 100


CRGB leds[NUM_STRIPS][NUM_LEDS];

//Pin locations for LED strips
const int lowerLEDs = 5;
const int middleLEDs = 6;
const int upperLEDs = 7;

const int myButton = 8;

void setup() {
  delay(3000);      //For recovery

 //Add led strip arrays 
  FastLED.addLeds<LED_TYPE, lowerLEDs, COLOR_ORDER>(leds[0], NUM_LEDS);
  FastLED.addLeds<LED_TYPE, middleLEDs, COLOR_ORDER>(leds[1], NUM_LEDS);
  FastLED.addLeds<LED_TYPE, upperLEDs, COLOR_ORDER>(leds[2], NUM_LEDS);

//  currentTime = millis();

  pinMode (myButton, INPUT_PULLUP);
  
}

void loop() 
{

  pattern_1(); 
//pattern_2();
//pattern_3();  

}

void pattern_1()
{
   for(int x = 0; x < NUM_STRIPS; x++) 
   {
    for(int i = 0; i < NUM_LEDS; i++) 
    {
      leds[x][i] = CRGB::Red;
      FastLED.show();
      leds[x][i] = CRGB::Black;

      unsigned long onTime = millis();
      while (millis() - onTime < DELAY)
      {
        if (digitalRead(myButton) == LOW)
          return;
      }
    }
  }
}

Another possible approach:

#include <FastLED.h>

#define NUM_STRIPS    3
#define NUM_LEDS      8
#define COLOR_ORDER   GRB
#define LED_TYPE      WS2812B

CRGB leds[NUM_STRIPS][NUM_LEDS];

//Pin locations for LED strips
const int lowerLEDs = 5;
const int middleLEDs = 6;
const int upperLEDs = 7;

#define NUM_PATTERNS    3
void Pattern1( void );      //pattern prototypes
void Pattern2( void );
void Pattern3( void );

typedef void(*pPatternFunc_t)(void);

//array of pointers to the pattern functions
pPatternFunc_t
    pPatterns[NUM_PATTERNS] = 
    {
        &Pattern1,
        &Pattern2,
        &Pattern3
    };
    
const uint8_t 
    pinSwitch = 2,          //pattern change switch input
    pinLED = LED_BUILTIN;   //for demo purposes

uint8_t 
    idxPattern = 0,
    lastSw;
uint32_t 
    tNow,
    tSwitch = 0ul;

void setup() 
{
    delay(3000);      //For recovery
    
    //Add led strip arrays 
    FastLED.addLeds<LED_TYPE, lowerLEDs, COLOR_ORDER>(leds[0], NUM_LEDS);
    FastLED.addLeds<LED_TYPE, middleLEDs, COLOR_ORDER>(leds[1], NUM_LEDS);
    FastLED.addLeds<LED_TYPE, upperLEDs, COLOR_ORDER>(leds[2], NUM_LEDS);

    pinMode( pinSwitch, INPUT_PULLUP );
    lastSw = digitalRead( pinSwitch );
    pinMode( pinLED, OUTPUT );
    
}//setup

void loop() 
{
    if( ReadSw() )
    {        
        //clean up existing pattern
        FastLED.clear();
        FastLED.show();
        digitalWrite( pinLED, LOW );

        //bump pattern being shown on button press
        idxPattern++;
        if( idxPattern == NUM_PATTERNS )
            idxPattern = 0;
            
    }//if

    //process current pattern every pass of loop()
    pPatterns[idxPattern]();

}//loop

bool ReadSw( void )
{
    //update the switch every 50mS
    tNow = millis();
    if( (tNow - tSwitch) < 50ul )
        return false;
        
    tSwitch = tNow;
    
    //return true if switch input seen to go from not-pressed to pressed
    uint8_t nowSw = digitalRead( pinSwitch );
    if( nowSw != lastSw )
    {
        lastSw = nowSw;
        if( nowSw == LOW )
            return true;
    }//if

    return false;
    
}//ReadSw

void Pattern1( void )
{
    static uint32_t
        tPattern = 0ul;
    static uint8_t
        strip=0,
        led=0;

    //patterns need to be non-blocking
    tNow = millis();
    
    //update this pattern every 100mS
    if( (tNow - tPattern) >= 100ul )
    {
        tPattern = tNow;
        
        leds[strip][led] = CRGB::Red;
        FastLED.show();
        leds[strip][led] = CRGB::Black;

        //this part replaces the for-loops of the original code
        led++;
        if( led == NUM_LEDS )
        {
            led = 0;
            strip++;
            if( strip == NUM_STRIPS )
                strip = 0;
        }//if
            
    }//if
    
}//Pattern1

void Pattern2( void )
{
    static uint32_t
        tBlink;
        
    //filler code to demonstrate change of patterns
    //toggle LED every 500mS
    tNow = millis();
    if( (tNow - tBlink) >= 500ul )
    {
        tBlink = tNow;
        digitalWrite( pinLED, digitalRead( pinLED ) ^ HIGH  );
        
    }//if
    
}//Pattern2

void Pattern3( void )
{   
    static uint32_t
        tBlink;
    //filler code to demonstrate change of patterns
    //toggle LED every 150mS
    tNow = millis();
    if( (tNow - tBlink) >= 150ul )
    {
        tBlink = tNow;
        digitalWrite( pinLED, digitalRead( pinLED ) ^ HIGH  );
        
    }//if
    
}//Pattern3

You implied that a for loop was bad while it is the delay that is bad.

Where did I do that?

Here:

In response to

So, why did you say:

In response to MY post? Take note of the author.

Aw, what the Hell?

Use a goto to break out

goto xit

Thanks everybody for all the feedback and possible solutions!!
I'll go through and try each different option thats been presented, i cant thank you enough. Im pretty new to programming so i'm excited to learn some things.

Love you all!

Just different combinations of using millis() within the for loops, but now that i see some other peoples ideas, i was approaching the concept wrong.

Is there any reason you are using three separate strips, therefor three output pins?

A bit of logic would work for one strip, one output pin.

Just curious.

a7

I just thought it would work best to separate the three levels of the project, one strip per level.
It's like a tower with three floors.
Do you think I could get easier results making one long strip 24 LEDs long?
I'm new to Fast LED and everything so I wasn't sure if I could seperate the levels as one strip for different patterns