Lost on how to control multiple led strips with MEGA

Hello-

Thanks in advance for any help. :slight_smile:

I'm working on a project that is using 12 individual led strips. I'm using the WS2815 12v versions. I have all the wiring and hardware figured out but am struggling a bit on the code. I'm using a MEGA so I can expand later if need be. I'm using the FastLED library example and it works great to make all 12 work at the same time. What I'm having an issue with is how to start and stop the code for each strip separately.

ie: Start PIN 1 code then Stop with delay
Start PIN 2 code then Stop with delay
.......and so on with all 12 strips

Want all PINs to use the same piece of code for the same effect on all 12 strips

The code below is what I have so far with all the strips working at the same time. Any assistance would be greatly appreciated. Thanks

   Greg

#include "FastLED.h"

#define NUM_LEDS 37

CRGB leds[NUM_LEDS];

#define PIN 1
#define PIN 2
#define PIN 3
#define PIN 4
#define PIN 5
#define PIN 6
#define PIN 7
#define PIN 8
#define PIN 9
#define PIN 10
#define PIN 11
#define PIN 12

void setup(){

delay(5500);

FastLED.addLeds<WS2811, 1, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );

FastLED.addLeds<WS2811, 2, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );

FastLED.addLeds<WS2811, 3, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );

FastLED.addLeds<WS2811, 4, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );

FastLED.addLeds<WS2811, 5, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );

FastLED.addLeds<WS2811, 6, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );

FastLED.addLeds<WS2811, 7, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );

FastLED.addLeds<WS2811, 8, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );

FastLED.addLeds<WS2811, 9, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );

FastLED.addLeds<WS2811, 10, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );

FastLED.addLeds<WS2811, 11, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );

FastLED.addLeds<WS2811, 12, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
}

void loop() {
meteorRain(0xff,0xff,0xff,10, 64, true, 30);
}

void meteorRain(byte red, byte green, byte blue, byte meteorSize, byte meteorTrailDecay, boolean meteorRandomDecay, int SpeedDelay) {
setAll(0,0,0);

for(int i = 0; i < NUM_LEDS+NUM_LEDS; i++) {

// fade brightness all LEDs one step
for(int j=0; j<NUM_LEDS; j++) {
  if( (!meteorRandomDecay) || (random(10)>5) ) {
    fadeToBlack(j, meteorTrailDecay );        
  }
}

// draw meteor
for(int j = 0; j < meteorSize; j++) {
  if( ( i-j <NUM_LEDS) && (i-j>=0) ) {
    setPixel(i-j, red, green, blue);
  }
}

showStrip();
delay(SpeedDelay);

}
}

void fadeToBlack(int ledNo, byte fadeValue) {
#ifdef ADAFRUIT_NEOPIXEL_H
// NeoPixel
uint32_t oldColor;
uint8_t r, g, b;
int value;

oldColor = strip.getPixelColor(ledNo);
r = (oldColor & 0x00ff0000UL) >> 16;
g = (oldColor & 0x0000ff00UL) >> 8;
b = (oldColor & 0x000000ffUL);

r=(r<=10)? 0 : (int) r-(r*fadeValue/256);
g=(g<=10)? 0 : (int) g-(g*fadeValue/256);
b=(b<=10)? 0 : (int) b-(b*fadeValue/256);

strip.setPixelColor(ledNo, r,g,b);

#endif
#ifndef ADAFRUIT_NEOPIXEL_H
// FastLED
leds[ledNo].fadeToBlackBy( fadeValue );
#endif
}
void showStrip() {
#ifdef ADAFRUIT_NEOPIXEL_H
// NeoPixel
strip.show();
#endif
#ifndef ADAFRUIT_NEOPIXEL_H
// FastLED
FastLED.show();
#endif
}

void setPixel(int Pixel, byte red, byte green, byte blue) {
#ifdef ADAFRUIT_NEOPIXEL_H
// NeoPixel
strip.setPixelColor(Pixel, strip.Color(red, green, blue));
#endif
#ifndef ADAFRUIT_NEOPIXEL_H
// FastLED
leds[Pixel].r = red;
leds[Pixel].g = green;
leds[Pixel].b = blue;
#endif
}

void setAll(byte red, byte green, byte blue) {
for(int i = 0; i < NUM_LEDS; i++ ) {
setPixel(i, red, green, blue);
}
showStrip();
}

Hello, do yourself a favour and please read How to get the best out of this forum and modify your post accordingly (including code tags and necessary documentation for your ask).


make up your mind instead of redefining PIN 12 times...

what value do you want PIN to be? (esp. as you use directly the pins number later on)

read this :Multiple Controller Examples · FastLED/FastLED Wiki · GitHub

Compiles, not tested.

#include "FastLED.h"

#define NUM_STRIPS          12
#define NUM_LEDS_PER_STRIP  37

const uint8_t pinStrip1 = 1;
const uint8_t pinStrip2 = 2;
const uint8_t pinStrip3 = 3;
const uint8_t pinStrip4 = 4;
const uint8_t pinStrip5 = 5;
const uint8_t pinStrip6 = 6;
const uint8_t pinStrip7 = 7;
const uint8_t pinStrip8 = 8;
const uint8_t pinStrip9 = 9;
const uint8_t pinStrip10 = 10;
const uint8_t pinStrip11 = 11;
const uint8_t pinStrip12 = 12;

CRGB grLeds[NUM_STRIPS][NUM_LEDS_PER_STRIP];

void setup()
{
    //delay(5500);  //?
    FastLED.addLeds<WS2811, pinStrip1, GRB>(grLeds[0], NUM_LEDS_PER_STRIP);
    FastLED.addLeds<WS2811, pinStrip2, GRB>(grLeds[1], NUM_LEDS_PER_STRIP);
    FastLED.addLeds<WS2811, pinStrip3, GRB>(grLeds[2], NUM_LEDS_PER_STRIP);
    FastLED.addLeds<WS2811, pinStrip4, GRB>(grLeds[3], NUM_LEDS_PER_STRIP);
    FastLED.addLeds<WS2811, pinStrip5, GRB>(grLeds[4], NUM_LEDS_PER_STRIP);
    FastLED.addLeds<WS2811, pinStrip6, GRB>(grLeds[5], NUM_LEDS_PER_STRIP);
    FastLED.addLeds<WS2811, pinStrip7, GRB>(grLeds[6], NUM_LEDS_PER_STRIP);
    FastLED.addLeds<WS2811, pinStrip8, GRB>(grLeds[7], NUM_LEDS_PER_STRIP);
    FastLED.addLeds<WS2811, pinStrip9, GRB>(grLeds[8], NUM_LEDS_PER_STRIP);
    FastLED.addLeds<WS2811, pinStrip10, GRB>(grLeds[9], NUM_LEDS_PER_STRIP);
    FastLED.addLeds<WS2811, pinStrip11, GRB>(grLeds[10], NUM_LEDS_PER_STRIP);
    FastLED.addLeds<WS2811, pinStrip12, GRB>(grLeds[11], NUM_LEDS_PER_STRIP);
            
}//setup

void loop() 
{    
    meteorRain( CRGB(0x00,0x00,0x00), CRGB(0xff,0xff,0xff), 10, 64, true, 30 );
    
}//loop

//
void meteorRain( CRGB ColorBackground, CRGB ColorMeteor, byte meteorSize, byte meteorTrailDecay, boolean meteorRandomDecay, int SpeedDelay ) 
{    
    // set background color
    for( uint8_t i=0; i<NUM_STRIPS; i++ )
        fill_solid( grLeds[i], NUM_LEDS_PER_STRIP, ColorBackground );

    for(uint8_t i=0; i<NUM_LEDS_PER_STRIP*2; i++ ) 
    {
        for( uint8_t strip=0; strip<NUM_STRIPS; strip++ )
        {
            // fade color to background color for all LEDs
            for(uint8_t led=0; led<NUM_LEDS_PER_STRIP; led++ ) 
            {
                if( (!meteorRandomDecay) || (random(10) > 5) ) 
                {
                    grLeds[strip][led] = fadeTowardColor( grLeds[strip][led], ColorBackground, meteorTrailDecay ); 
                    
                }//if
            
            }//for

            // draw meteor
            for( uint8_t j=0; j<meteorSize; j++ ) 
            {
                if( ( (i-j) < NUM_LEDS_PER_STRIP) && ((i-j) >= 0) ) 
                {
                    grLeds[strip][i-j] = ColorMeteor;
                
                }//if
            
            }//for
           
        }//for

        FastLED.show();
        delay( SpeedDelay );
        
    }//for
    
}//meteorRain

CRGB fadeTowardColor( CRGB &cur, const CRGB &target, uint8_t amount )
{
    nblendU8TowardU8( cur.red,   target.red,   amount);
    nblendU8TowardU8( cur.green, target.green, amount);
    nblendU8TowardU8( cur.blue,  target.blue,  amount);
    
    return cur;
    
}//fadeTowardColor

void nblendU8TowardU8( uint8_t &cur, const uint8_t target, uint8_t amount )
{
    if( cur == target) 
        return;
    
    if( cur < target ) 
    {
        uint8_t delta = target - cur;
        delta = scale8_video( delta, amount);
        cur += delta;
        
    }//if
    else 
    {
        uint8_t delta = cur - target;
        delta = scale8_video( delta, amount);
        cur -= delta;
        
    }//else
    
}//nblendU8TowardU8

Thank you both for all the help.

Blackfin- The code you assisted with worked but did the same as before. All 12 strips come on at once. Trying to get it to sequence from PIN 1 to 2 to 3 and so on.

Per J-M-L's advice I read :Multiple Controller Examples · FastLED/FastLED Wiki · GitHub. Playing around with that I did get the example array section to work the way I wanted. So I then tried to integrate the "Meteor" sketch to work the same but that's where my next problem lies.

Here is the sketch that works so far from the example stated. Being the novice I am (obviously) :slight_smile: I'm not grasping on how to add the meteor section from the first sketch.

Again thanks for any help provided.

#include "FastLED.h"
#define NUM_STRIPS 12
#define NUM_LEDS_PER_STRIP 4
CRGB leds[NUM_STRIPS][NUM_LEDS_PER_STRIP];

#define PIN 1
#define PIN 2
#define PIN 3
#define PIN 4
#define PIN 5
#define PIN 6
#define PIN 7
#define PIN 8
#define PIN 9
#define PIN 10
#define PIN 11
#define PIN 12


void setup() {

  delay(5000);

  FastLED.addLeds<NEOPIXEL, 1>(leds[0], NUM_LEDS_PER_STRIP);
  FastLED.addLeds<NEOPIXEL, 2>(leds[1], NUM_LEDS_PER_STRIP);
  FastLED.addLeds<NEOPIXEL, 3>(leds[2], NUM_LEDS_PER_STRIP);
  FastLED.addLeds<NEOPIXEL, 4>(leds[3], NUM_LEDS_PER_STRIP);
  FastLED.addLeds<NEOPIXEL, 5>(leds[4], NUM_LEDS_PER_STRIP);
  FastLED.addLeds<NEOPIXEL, 6>(leds[5], NUM_LEDS_PER_STRIP);
  FastLED.addLeds<NEOPIXEL, 7>(leds[6], NUM_LEDS_PER_STRIP);
  FastLED.addLeds<NEOPIXEL, 8>(leds[7], NUM_LEDS_PER_STRIP);
  FastLED.addLeds<NEOPIXEL, 9>(leds[8], NUM_LEDS_PER_STRIP);
  FastLED.addLeds<NEOPIXEL, 10>(leds[9], NUM_LEDS_PER_STRIP);
  FastLED.addLeds<NEOPIXEL, 11>(leds[10], NUM_LEDS_PER_STRIP);
  FastLED.addLeds<NEOPIXEL, 12>(leds[11], NUM_LEDS_PER_STRIP);


}

void loop() {
  // This outer loop will go over each strip, one at a time
  for (int x = 0; x < NUM_STRIPS; x++) {
    // This inner loop will go over each led in the current strip, one at a time
    for (int i = 0; i < NUM_LEDS_PER_STRIP; i++) {
      leds[x][i] = CRGB::Red;
      FastLED.show();
      leds[x][i] = CRGB::Black;
      delay(75);
    }
  }
}

If you replace the function MeteorRain with this does it make a difference?

It basically swaps the outer loops:

void meteorRain( CRGB ColorBackground, CRGB ColorMeteor, byte meteorSize, byte meteorTrailDecay, boolean meteorRandomDecay, int SpeedDelay ) 
{    
    // set background color
    for( uint8_t i=0; i<NUM_STRIPS; i++ )
        fill_solid( grLeds[i], NUM_LEDS_PER_STRIP, ColorBackground );

    for( uint8_t strip=0; strip<NUM_STRIPS; strip++ )
    {
        for(uint8_t i=0; i<NUM_LEDS_PER_STRIP*2; i++ ) 
        {
            // fade color to background color for all LEDs
            for(uint8_t led=0; led<NUM_LEDS_PER_STRIP; led++ ) 
            {
                if( (!meteorRandomDecay) || (random(10) > 5) ) 
                {
                    grLeds[strip][led] = fadeTowardColor( grLeds[strip][led], ColorBackground, meteorTrailDecay ); 
                    
                }//if
            
            }//for

            // draw meteor
            for( uint8_t j=0; j<meteorSize; j++ ) 
            {
                if( ( (i-j) < NUM_LEDS_PER_STRIP) && ((i-j) >= 0) ) 
                {
                    grLeds[strip][i-j] = ColorMeteor;
                
                }//if
            
            }//for
           
            FastLED.show();
            delay( SpeedDelay );
            
        }//for        
        
    }//for
    
}//meteorRain

Thank you so much! That did the trick. I do have a question though. :slight_smile: Is there a way in the code for me to speed up the process so it moves faster from one to the other? I'm trying really hard to absorb what you have done here. I'm just not familiar enough to see it. Thanks again!

I changed 30 above to 1 and it's pretty fast but would like faster. Is that possible? Thanks!

You could try, for example:

meteorRain( CRGB(0x00,0x00,0x00), CRGB(0xff,0xff,0xff), 10, 64, true, 250ul );

and change the delay in meteorRain to:

            delayMicroseconds( SpeedDelay );

Thanks again! Tried this but it's pretty much the same speed. I did adjust the values quite a bit with no change. Very strange. :slight_smile: I will play around and let you know

I characterized the execution time of meteorRain() and it appears that it's taking 1.34-seconds to complete the meteor effect for each string. That was with a delayMicroseconds(250) delay; with a delay(1) value the time was only marginally longer at 1.4-seconds, indicating that the time consumer is not the delays right now.

With the fade portion commented out the execution time drops to 1.08-seconds (with delayMicroseconds(250)).

The real time consumer is running FastLED.show() for every iteration. When that's commented out and the fade logic re-enabled the execution time drops to 278mS. (With the fade stuff commented out it drops to ~20mS).

As a sanity check: you have 12 strips and 37 LEDs per strip or 444 LEDs. Each LED requires 24 bits of data so 444 x 24 or 10656 bits of data must be sent every time .show() is called. At a nominal effective clock of 800kHz, 10656 bits is going to require 13.32mS each time show is called. This happens 37 x 2 or 74 times per strip giving a nominal per strip time of just about 1-second (0.986-sec), not counting any overhead in FastLED.

You might be able to make the things run faster if a more aggressive fade value is used or a smaller meteor size is used but you're not going to get around the basic, underlying gate of ~1-sec just to clock the data out for one strip.

It would be nice if the FastLED library gave the ability to .show( uint8_t pin ) -- so you only clock out the strip of interest -- but I don't think it does.

Wow! Amazed at the extent of the explanation. Very awesome. Thank you! I tried to squeeze out as much as I could. What is says though is I'm gonna live with the timing. It will have to do. :slight_smile: I will have to post a short video of this project once I finish. It's pretty cool. :slight_smile: Thanks again

Give this a try. After a bit of research I found you can control individual LED controllers within the FastLED class:

#include "FastLED.h"

#define NUM_LEDS_PER_STRIP  37
#define NUM_STRIPS          12

const uint8_t pinStrip1 = 1;
const uint8_t pinStrip2 = 2;
const uint8_t pinStrip3 = 3;
const uint8_t pinStrip4 = 4;
const uint8_t pinStrip5 = 5;
const uint8_t pinStrip6 = 6;
const uint8_t pinStrip7 = 7;
const uint8_t pinStrip8 = 8;
const uint8_t pinStrip9 = 9;
const uint8_t pinStrip10 = 10;
const uint8_t pinStrip11 = 11;
const uint8_t pinStrip12 = 12;

const uint8_t pinDebug = A0;

CRGB 
    grLeds[NUM_STRIPS][NUM_LEDS_PER_STRIP];
CLEDController 
    *stripControl[NUM_STRIPS];

uint8_t gBrightness = 128;

void setup() 
{ 
    stripControl[0] = &FastLED.addLeds<WS2812, pinStrip1, GRB>(grLeds[0], NUM_LEDS_PER_STRIP);
    stripControl[1] = &FastLED.addLeds<WS2812, pinStrip2, GRB>(grLeds[1], NUM_LEDS_PER_STRIP);
    stripControl[2] = &FastLED.addLeds<WS2812, pinStrip3, GRB>(grLeds[2], NUM_LEDS_PER_STRIP);
    stripControl[3] = &FastLED.addLeds<WS2812, pinStrip4, GRB>(grLeds[3], NUM_LEDS_PER_STRIP);
    stripControl[4] = &FastLED.addLeds<WS2812, pinStrip5, GRB>(grLeds[4], NUM_LEDS_PER_STRIP);
    stripControl[5] = &FastLED.addLeds<WS2812, pinStrip6, GRB>(grLeds[5], NUM_LEDS_PER_STRIP);
    stripControl[6] = &FastLED.addLeds<WS2812, pinStrip7, GRB>(grLeds[6], NUM_LEDS_PER_STRIP);
    stripControl[7] = &FastLED.addLeds<WS2812, pinStrip8, GRB>(grLeds[7], NUM_LEDS_PER_STRIP);
    stripControl[8] = &FastLED.addLeds<WS2812, pinStrip9, GRB>(grLeds[8], NUM_LEDS_PER_STRIP);
    stripControl[9] = &FastLED.addLeds<WS2812, pinStrip10, GRB>(grLeds[9], NUM_LEDS_PER_STRIP);
    stripControl[10] = &FastLED.addLeds<WS2812, pinStrip11, GRB>(grLeds[10], NUM_LEDS_PER_STRIP);
    stripControl[11] = &FastLED.addLeds<WS2812, pinStrip12, GRB>(grLeds[11], NUM_LEDS_PER_STRIP);

    pinMode( pinDebug, OUTPUT );
    
}//setup

void loop() 
{ 
    static uint8_t
        stripIdx = 0;

    digitalWrite( pinDebug, HIGH );
    meteorRain( stripIdx, CRGB(0x00,0x00,0x00), CRGB(0xff,0xff,0xff), 10, 64, true, 100 );
    digitalWrite( pinDebug, LOW );
    
    stripIdx++;
    if( stripIdx == NUM_STRIPS )
        stripIdx = 0;
    
}//loop

//
void meteorRain(    uint8_t stripNo, 
                    CRGB ColorBackground, 
                    CRGB ColorMeteor, 
                    byte meteorSize, 
                    byte meteorTrailDecay, 
                    boolean meteorRandomDecay, 
                    uint32_t SpeedDelay ) 
{    
    // set background color    
    fill_solid( grLeds[stripNo], NUM_LEDS_PER_STRIP, ColorBackground );

    for(uint8_t i=0; i<NUM_LEDS_PER_STRIP*2; i++ ) 
    {
        // fade color to background color for all LEDs
        for(uint8_t led=0; led<NUM_LEDS_PER_STRIP; led++ ) 
        {
            if( (!meteorRandomDecay) || (random(10) > 5) ) 
            {
                grLeds[stripNo][led] = fadeTowardColor( grLeds[stripNo][led], ColorBackground, meteorTrailDecay ); 
                
            }//if
        
        }//for

        // draw meteor
        for( uint8_t j=0; j<meteorSize; j++ ) 
        {
            if( ( (i-j) < NUM_LEDS_PER_STRIP) && ((i-j) >= 0) ) 
            {
                grLeds[stripNo][i-j] = ColorMeteor;
            
            }//if
        
        }//for
       
        stripControl[stripNo]->showLeds(gBrightness);
        delayMicroseconds( SpeedDelay );
        
    }//for        
        
}//meteorRain

CRGB fadeTowardColor( CRGB &cur, const CRGB &target, uint8_t amount )
{
    nblendU8TowardU8( cur.red,   target.red,   amount);
    nblendU8TowardU8( cur.green, target.green, amount);
    nblendU8TowardU8( cur.blue,  target.blue,  amount);
    
    return cur;
    
}//fadeTowardColor

void nblendU8TowardU8( uint8_t &cur, const uint8_t target, uint8_t amount )
{
    if( cur == target) 
        return;
    
    if( cur < target ) 
    {
        uint8_t delta = target - cur;
        delta = scale8_video( delta, amount);
        cur += delta;
        
    }//if
    else 
    {
        uint8_t delta = cur - target;
        delta = scale8_video( delta, amount);
        cur -= delta;
        
    }//else
    
}//nblendU8TowardU8

This worked awesome! Thanks! I did play around with the timing and got it dialed in perfect. I then attempted to take it out of loop function because I need it to run once after power up. Again I am confused. Tried so many ways. Honestly I need to add more effects for it to work exactly the way I need it to. :slight_smile:

So I was pondering on how to make this project a reality. I would like to continue with your help. It’s greatly appreciated. That being said can I offer compensation to get this finished on time. Not sure if this is possible on or off this forum?

~Happy Thanksgiving~

To make the effects run once/in sequence, perhaps something like:

#include "FastLED.h"

#define NUM_LEDS_PER_STRIP  37
#define NUM_STRIPS          12

const uint8_t pinStrip1 = 1;
const uint8_t pinStrip2 = 2;
const uint8_t pinStrip3 = 3;
const uint8_t pinStrip4 = 4;
const uint8_t pinStrip5 = 5;
const uint8_t pinStrip6 = 6;
const uint8_t pinStrip7 = 7;
const uint8_t pinStrip8 = 8;
const uint8_t pinStrip9 = 9;
const uint8_t pinStrip10 = 10;
const uint8_t pinStrip11 = 11;
const uint8_t pinStrip12 = 12;

//const uint8_t pinDebug = A0;

CRGB 
    grLeds[NUM_STRIPS][NUM_LEDS_PER_STRIP];
CLEDController 
    *stripControl[NUM_STRIPS];

uint8_t gBrightness = 255;

void setup() 
{ 
    stripControl[0] = &FastLED.addLeds<WS2812, pinStrip1, GRB>(grLeds[0], NUM_LEDS_PER_STRIP);
    stripControl[1] = &FastLED.addLeds<WS2812, pinStrip2, GRB>(grLeds[1], NUM_LEDS_PER_STRIP);
    stripControl[2] = &FastLED.addLeds<WS2812, pinStrip3, GRB>(grLeds[2], NUM_LEDS_PER_STRIP);
    stripControl[3] = &FastLED.addLeds<WS2812, pinStrip4, GRB>(grLeds[3], NUM_LEDS_PER_STRIP);
    stripControl[4] = &FastLED.addLeds<WS2812, pinStrip5, GRB>(grLeds[4], NUM_LEDS_PER_STRIP);
    stripControl[5] = &FastLED.addLeds<WS2812, pinStrip6, GRB>(grLeds[5], NUM_LEDS_PER_STRIP);
    stripControl[6] = &FastLED.addLeds<WS2812, pinStrip7, GRB>(grLeds[6], NUM_LEDS_PER_STRIP);
    stripControl[7] = &FastLED.addLeds<WS2812, pinStrip8, GRB>(grLeds[7], NUM_LEDS_PER_STRIP);
    stripControl[8] = &FastLED.addLeds<WS2812, pinStrip9, GRB>(grLeds[8], NUM_LEDS_PER_STRIP);
    stripControl[9] = &FastLED.addLeds<WS2812, pinStrip10, GRB>(grLeds[9], NUM_LEDS_PER_STRIP);
    stripControl[10] = &FastLED.addLeds<WS2812, pinStrip11, GRB>(grLeds[10], NUM_LEDS_PER_STRIP);
    stripControl[11] = &FastLED.addLeds<WS2812, pinStrip12, GRB>(grLeds[11], NUM_LEDS_PER_STRIP);

    //pinMode( pinDebug, OUTPUT );
    
}//setup

void loop() 
{ 
    doEffects();
    
}//loop

void doEffects( void )
{
    static uint8_t
        stripIdx = 0,
        stateEffects = 0;

    switch( stateEffects )
    {
        case    0:
            //stay in state 0 doing the meteor effect...
            meteorRain( stripIdx, CRGB(0x00,0x00,0x00), CRGB(0xff,0xff,0xff), 10, 64, true, 100 );
            stripIdx++;
            //until all strips are done...
            if( stripIdx == NUM_STRIPS )            
                stateEffects++;    //then bump to the next state
            
        break;

        case    1:
            //add another effect here and when done...
            for( stripIdx=0; stripIdx<NUM_STRIPS; stripIdx+=3 )
            {
                fill_solid( grLeds[stripIdx], NUM_LEDS_PER_STRIP, CRGB(0xff, 0x00, 0x00) );
                stripControl[stripIdx]->showLeds(gBrightness);
                fill_solid( grLeds[stripIdx+1], NUM_LEDS_PER_STRIP, CRGB(0x00, 0xff, 0x00) );
                stripControl[stripIdx+1]->showLeds(gBrightness);
                fill_solid( grLeds[stripIdx+2], NUM_LEDS_PER_STRIP, CRGB(0x00, 0x00, 0xff) );
                stripControl[stripIdx+2]->showLeds(gBrightness);
                
            }//for
            
            //move to the next effect
            stateEffects++;
            
        break;

        case    2:
            //add another effect and so on...
            //when done effects, just use an empty case like this
        break;
        
    }//switch
    
}//doEffects

void meteorRain(    uint8_t stripNo, 
                    CRGB ColorBackground, 
                    CRGB ColorMeteor, 
                    byte meteorSize, 
                    byte meteorTrailDecay, 
                    boolean meteorRandomDecay, 
                    uint32_t SpeedDelay ) 
{    
    // set background color    
    fill_solid( grLeds[stripNo], NUM_LEDS_PER_STRIP, ColorBackground );

    for(uint8_t i=0; i<NUM_LEDS_PER_STRIP*2; i++ ) 
    {
        // fade color to background color for all LEDs
        for(uint8_t led=0; led<NUM_LEDS_PER_STRIP; led++ ) 
        {
            if( (!meteorRandomDecay) || (random(10) > 5) ) 
            {
                grLeds[stripNo][led] = fadeTowardColor( grLeds[stripNo][led], ColorBackground, meteorTrailDecay ); 
                
            }//if
        
        }//for

        // draw meteor
        for( uint8_t j=0; j<meteorSize; j++ ) 
        {
            if( ( (i-j) < NUM_LEDS_PER_STRIP) && ((i-j) >= 0) ) 
            {
                grLeds[stripNo][i-j] = ColorMeteor;
            
            }//if
        
        }//for
       
        stripControl[stripNo]->showLeds(gBrightness);
        delayMicroseconds( SpeedDelay );
        
    }//for        
        
}//meteorRain

CRGB fadeTowardColor( CRGB &cur, const CRGB &target, uint8_t amount )
{
    nblendU8TowardU8( cur.red,   target.red,   amount);
    nblendU8TowardU8( cur.green, target.green, amount);
    nblendU8TowardU8( cur.blue,  target.blue,  amount);
    
    return cur;
    
}//fadeTowardColor

void nblendU8TowardU8( uint8_t &cur, const uint8_t target, uint8_t amount )
{
    if( cur == target) 
        return;
    
    if( cur < target ) 
    {
        uint8_t delta = target - cur;
        delta = scale8_video( delta, amount);
        cur += delta;
        
    }//if
    else 
    {
        uint8_t delta = cur - target;
        delta = scale8_video( delta, amount);
        cur -= delta;
        
    }//else
    
}//nblendU8TowardU8

Thank You! Works great now. Very much appreciated!

Ok I lied. I'm stuck again. :slight_smile: Thought I could figure it out but it's just not doing what I want. Like how this looks but can't see how to make Case 3 and 4 go the opposite way.

Case 1 and 2- Move from strip 1-12
Case 3 and 4- Move from strip 12-1 (reverse direction)

Here is the code. I tried all kinds of ways to change case 3 and 4 to work in the reverse direction with no luck. I'm probably way off on my thoughts anyways. Def harder than I expected this to be. Hopefully I'll understand any help given :slight_smile: Thank you

#include "FastLED.h"

#define NUM_LEDS_PER_STRIP  37
#define NUM_STRIPS          12

const uint8_t pinStrip1 = 1;
const uint8_t pinStrip2 = 2;
const uint8_t pinStrip3 = 3;
const uint8_t pinStrip4 = 4;
const uint8_t pinStrip5 = 5;
const uint8_t pinStrip6 = 6;
const uint8_t pinStrip7 = 7;
const uint8_t pinStrip8 = 8;
const uint8_t pinStrip9 = 9;
const uint8_t pinStrip10 = 10;
const uint8_t pinStrip11 = 11;
const uint8_t pinStrip12 = 12;

//const uint8_t pinDebug = A0;

CRGB
grLeds[NUM_STRIPS][NUM_LEDS_PER_STRIP];
CLEDController
*stripControl[NUM_STRIPS];

uint8_t gBrightness = 255;

void setup() {


  delay(100);


  stripControl[0] = &FastLED.addLeds<WS2812, pinStrip1, GRB>(grLeds[0], NUM_LEDS_PER_STRIP);
  stripControl[1] = &FastLED.addLeds<WS2812, pinStrip2, GRB>(grLeds[1], NUM_LEDS_PER_STRIP);
  stripControl[2] = &FastLED.addLeds<WS2812, pinStrip3, GRB>(grLeds[2], NUM_LEDS_PER_STRIP);
  stripControl[3] = &FastLED.addLeds<WS2812, pinStrip4, GRB>(grLeds[3], NUM_LEDS_PER_STRIP);
  stripControl[4] = &FastLED.addLeds<WS2812, pinStrip5, GRB>(grLeds[4], NUM_LEDS_PER_STRIP);
  stripControl[5] = &FastLED.addLeds<WS2812, pinStrip6, GRB>(grLeds[5], NUM_LEDS_PER_STRIP);
  stripControl[6] = &FastLED.addLeds<WS2812, pinStrip7, GRB>(grLeds[6], NUM_LEDS_PER_STRIP);
  stripControl[7] = &FastLED.addLeds<WS2812, pinStrip8, GRB>(grLeds[7], NUM_LEDS_PER_STRIP);
  stripControl[8] = &FastLED.addLeds<WS2812, pinStrip9, GRB>(grLeds[8], NUM_LEDS_PER_STRIP);
  stripControl[9] = &FastLED.addLeds<WS2812, pinStrip10, GRB>(grLeds[9], NUM_LEDS_PER_STRIP);
  stripControl[10] = &FastLED.addLeds<WS2812, pinStrip11, GRB>(grLeds[10], NUM_LEDS_PER_STRIP);
  stripControl[11] = &FastLED.addLeds<WS2812, pinStrip12, GRB>(grLeds[11], NUM_LEDS_PER_STRIP);

  //pinMode( pinDebug, OUTPUT );

}//setup

void loop()
{
  doEffects();

}//loop

void doEffects( void )
{
  static uint8_t
  stripIdx = 0,
  stateEffects = 0;

  switch ( stateEffects )
  {
    case    0:
      //stay in state 0 doing the meteor effect...
      meteorRain( stripIdx, CRGB(0x00, 0x00, 0x00), CRGB(0xff, 0xff, 0xff), 10, 175, true, 25 );
      stripIdx++;
      //until all strips are done...
      if ( stripIdx == NUM_STRIPS )

        stateEffects++;    //then bump to the next state

      break;

    case    1:
      //add another effect here and when done...
      for ( stripIdx = 0; stripIdx < NUM_STRIPS; stripIdx += 3 )
      {

        fill_solid( grLeds[stripIdx], NUM_LEDS_PER_STRIP, CRGB(0xff, 0x00, 0x00) );
        stripControl[stripIdx]->showLeds(gBrightness);
        delay(25);
        fill_solid( grLeds[stripIdx + 1], NUM_LEDS_PER_STRIP, CRGB(0xff, 0x00, 0x00) );
        stripControl[stripIdx + 1]->showLeds(gBrightness);
        delay(25);
        fill_solid( grLeds[stripIdx + 2], NUM_LEDS_PER_STRIP, CRGB(0xff, 0x00, 0x00) );
        stripControl[stripIdx + 2]->showLeds(gBrightness);
        delay(25);

      }//for

      //move to the next effect
      stateEffects++;

      break;

    case    2:
      //add another effect here and when done...
      for ( stripIdx = 0; stripIdx < NUM_STRIPS; stripIdx += 3 )
      {

        fill_solid( grLeds[stripIdx], NUM_LEDS_PER_STRIP, CRGB(0x00, 0x00, 0x00) );
        stripControl[stripIdx]->showLeds(gBrightness);
        delay(25);
        fill_solid( grLeds[stripIdx + 1], NUM_LEDS_PER_STRIP, CRGB(0x00, 0x00, 0x00) );
        stripControl[stripIdx + 1]->showLeds(gBrightness);
        delay(25);
        fill_solid( grLeds[stripIdx + 2], NUM_LEDS_PER_STRIP, CRGB(0x00, 0x00, 0x00) );
        stripControl[stripIdx + 2]->showLeds(gBrightness);
        delay(25);

      }//for

      //move to the next effect
      stateEffects++;

      break;


    case    3:
      //add another effect here and when done...
      for ( stripIdx = 0; stripIdx < NUM_STRIPS; stripIdx += 3 )
      {

        fill_solid( grLeds[stripIdx], NUM_LEDS_PER_STRIP, CRGB(0xff, 0x00, 0x00) );
        stripControl[stripIdx]->showLeds(gBrightness);
        delay(25);
        fill_solid( grLeds[stripIdx + 1], NUM_LEDS_PER_STRIP, CRGB(0xff, 0x00, 0x00) );
        stripControl[stripIdx + 1]->showLeds(gBrightness);
        delay(25);
        fill_solid( grLeds[stripIdx + 2], NUM_LEDS_PER_STRIP, CRGB(0xff, 0x00, 0x00) );
        stripControl[stripIdx + 2]->showLeds(gBrightness);
        delay(25);

      }//for

      //move to the next effect
      stateEffects++;

      break;


    case    4:
      //add another effect here and when done...
      for ( stripIdx = 0; stripIdx < NUM_STRIPS; stripIdx += 3 )
      {

        fill_solid( grLeds[stripIdx], NUM_LEDS_PER_STRIP, CRGB(0x00, 0x00, 0x00) );
        stripControl[stripIdx]->showLeds(gBrightness);
        delay(25);
        fill_solid( grLeds[stripIdx + 1], NUM_LEDS_PER_STRIP, CRGB(0x00, 0x00, 0x00) );
        stripControl[stripIdx + 1]->showLeds(gBrightness);
        delay(25);
        fill_solid( grLeds[stripIdx + 2], NUM_LEDS_PER_STRIP, CRGB(0x00, 0x00, 0x00) );
        stripControl[stripIdx + 2]->showLeds(gBrightness);
        delay(25);

      }//for

      //move to the next effect
      stateEffects++;

      break;


    case    5:
      //add another effect and so on...
      //when done effects, just use an empty case like this
      for ( stripIdx = 0; stripIdx < NUM_STRIPS; stripIdx += 3 )
      {

        fill_solid( grLeds[stripIdx], NUM_LEDS_PER_STRIP, CRGB(0xff, 0xff, 0xff) );
        stripControl[stripIdx]->showLeds(gBrightness);
        fill_solid( grLeds[stripIdx + 1], NUM_LEDS_PER_STRIP, CRGB(0xff, 0xff, 0xff) );
        stripControl[stripIdx + 1]->showLeds(gBrightness);
        fill_solid( grLeds[stripIdx + 2], NUM_LEDS_PER_STRIP, CRGB(0xff, 0xff, 0xff) );
        stripControl[stripIdx + 2]->showLeds(gBrightness);

      }//for

      //move to the next effect
      stateEffects++;

      break;



  }//switch

}//doEffects

void meteorRain(    uint8_t stripNo,
                    CRGB ColorBackground,
                    CRGB ColorMeteor,
                    byte meteorSize,
                    byte meteorTrailDecay,
                    boolean meteorRandomDecay,
                    uint32_t SpeedDelay )
{
  // set background color
  fill_solid( grLeds[stripNo], NUM_LEDS_PER_STRIP, ColorBackground );

  for (uint8_t i = 0; i < NUM_LEDS_PER_STRIP * 2; i++ )
  {
    // fade color to background color for all LEDs
    for (uint8_t led = 0; led < NUM_LEDS_PER_STRIP; led++ )
    {
      if ( (!meteorRandomDecay) || (random(10) > 5) )
      {
        grLeds[stripNo][led] = fadeTowardColor( grLeds[stripNo][led], ColorBackground, meteorTrailDecay );

      }//if

    }//for

    // draw meteor
    for ( uint8_t j = 0; j < meteorSize; j++ )
    {
      if ( ( (i - j) < NUM_LEDS_PER_STRIP) && ((i - j) >= 0) )
      {
        grLeds[stripNo][i - j] = ColorMeteor;

      }//if

    }//for

    stripControl[stripNo]->showLeds(gBrightness);
    delayMicroseconds( SpeedDelay );

  }//for

}//meteorRain

CRGB fadeTowardColor( CRGB &cur, const CRGB &target, uint8_t amount )
{
  nblendU8TowardU8( cur.red,   target.red,   amount);
  nblendU8TowardU8( cur.green, target.green, amount);
  nblendU8TowardU8( cur.blue,  target.blue,  amount);

  return cur;

}//fadeTowardColor

void nblendU8TowardU8( uint8_t &cur, const uint8_t target, uint8_t amount )
{
  if ( cur == target)
    return;

  if ( cur < target )
  {
    uint8_t delta = target - cur;
    delta = scale8_video( delta, amount);
    cur += delta;

  }//if
  else
  {
    uint8_t delta = cur - target;
    delta = scale8_video( delta, amount);
    cur -= delta;

  }//else

}//nblendU8TowardU8

Try this:

void doEffects( void )
{
    static uint8_t
        stripIdx = 0,
        stateEffects = 0;

    switch ( stateEffects )
    {
        case    0:
            //stay in state 0 doing the meteor effect...
            meteorRain( stripIdx, CRGB::Black, CRGB::White, 10, 175, true, 25 );
            stripIdx++;
            
            //until all strips are done...
            if ( stripIdx == NUM_STRIPS )
            {
                stripIdx = 0;           
                stateEffects++;    //then bump to the next state
                
            }//if
        
        break;

        case    1:
            stripFillEffect( stripIdx, CRGB::Green, 25ul );
            stripFillEffect( stripIdx+1, CRGB::Green, 25ul );
            stripFillEffect( stripIdx+2, CRGB::Green, 25ul );

            stripIdx += 3;            
            if( stripIdx == NUM_STRIPS )
            {
                stripIdx = 0;            
                stateEffects++;
                
            }//if
        
        break;

        case    2:
            stripFillEffect( stripIdx, CRGB::Black, 25ul );
            stripFillEffect( stripIdx+1, CRGB::Black, 25ul );
            stripFillEffect( stripIdx+2, CRGB::Black, 25ul );

            stripIdx += 3;
            if( stripIdx == NUM_STRIPS )
                stateEffects++;
                
      break;

        case    3:
            stripFillEffect( stripIdx-1, CRGB::Green, 25ul );
            stripFillEffect( stripIdx-2, CRGB::Green, 25ul );
            stripFillEffect( stripIdx-3, CRGB::Green, 25ul );

            stripIdx -= 3;
            if( stripIdx == 0 )
            {
                stripIdx = NUM_STRIPS;            
                stateEffects++;
                
            }//if
        
        break;


        case    4:
            stripFillEffect( stripIdx-1, CRGB::Black, 25ul );
            stripFillEffect( stripIdx-2, CRGB::Black, 25ul );
            stripFillEffect( stripIdx-3, CRGB::Black, 25ul );

            stripIdx -= 3;
            if( stripIdx == 0 )
                stateEffects++;

        break;


        case    5:
            for ( stripIdx = 0; stripIdx < NUM_STRIPS; stripIdx += 3 )
            {        
                fill_solid( grLeds[stripIdx], NUM_LEDS_PER_STRIP, CRGB::White );
                stripControl[stripIdx]->showLeds(gBrightness);
                fill_solid( grLeds[stripIdx + 1], NUM_LEDS_PER_STRIP, CRGB::White );
                stripControl[stripIdx + 1]->showLeds(gBrightness);
                fill_solid( grLeds[stripIdx + 2], NUM_LEDS_PER_STRIP, CRGB::White );
                stripControl[stripIdx + 2]->showLeds(gBrightness);
            
            }//for
            
            //move to the next effect or done
            stateEffects++;
        
        break;

        default:
            //done effects; do nothing
        break;

    }//switch

}//doEffects

void stripFillEffect( uint8_t stripNo, CRGB color, uint32_t timeDelay )
{
    fill_solid( grLeds[stripNo], NUM_LEDS_PER_STRIP, color );
    stripControl[stripNo]->showLeds(gBrightness);
    delay( timeDelay );
    
}//stripFillEffect

As you settle on whatever effects you want you might think about the patterns and statements that are common to all and see if there's a way to approach them differently; instead of having discrete states for each effect that are very close to one another, maybe have a function that does that and pass the start and end color, the direction of movement etc.

Thanks again! Very much appreciated. Here’s a short clip of them in action. Turned out sick! :slight_smile:

1 Like

Video is private :pleading_face:

1 Like

Oops. Lol. Fixed

Still can't view it for some reason. I just get a blank window on the YT page.