Page 1 of 1
Forum

Welcome to the Tweaking4All community forums!
When participating, please keep the Forum Rules in mind!

Topics for particular software or systems: Start your topic link with the name of the application or system.
For example “MacOS X – Your question“, or “MS Word – Your Tip or Trick“.

Please note that switching to another language when reading a post will not bring you to the same post, in Dutch, as there is no translation for that post!




multiple ws2812b st...
 
Share:
Notifications
Clear all

[Solved] multiple ws2812b strands and effects

25 Posts
2 Users
0 Likes
10.3 K Views
(@supramp)
Active Member
Joined: 5 years ago
Posts: 16
Topic starter  

Help, lol.  

What am I trying to do?

I am trying to run 2 strips of WS2812B leds on pin 4, 72 leds each in parallel so they both run "meteor rain:. 1 WS2812B 60 led ring on pin 5 running "fade in/out" at the same time. I want 2 pull up momentary switches, 1 will trigger both pins to switch to "strobe" for 2 seconds, and the other to switch pin 5 to  "running lights"

I have been at this for a few days and am literally cross-eyed.  I am still learning and researching everyday and reading through the libraries, although I admit that much of it goes over my head, and this seems like no easy feet.  Here is my current attempt to run the sketch. it does compile with no errors, but I think I have changed so many settings attempting to trigger the events i mentioned that I am lost.  Please be gentle, and bestow upon me your infinite wisdom's.  Seriously, bestow away, lol.

#include "FastLED.h"
// How many leds in your strips?
#define NUM_LEDS_Strips 72
#define NUM_LEDS_Ring 60
// Switches
#define BUTTON_Vibrate 2 // vibration sensor for strobe effect
#define BUTTON_Lever 3 // lever reed switch for chase effect 
byte selectedEffect=0;
// Define the array of leds
CRGB ledsStrips[NUM_LEDS_Strips];
CRGB ledsRing[NUM_LEDS_Ring];

void setup() { 
      FastLED.addLeds<WS2812B, 4, RGB>(ledsStrips, NUM_LEDS_Strips); //LED strips on pin 4 with 72 LEDS
      FastLED.addLeds<WS2812B, 5, RGB>(ledsRing, NUM_LEDS_Ring); //LED strips on pin 5 with 60 LEDS
      pinMode(BUTTON_Vibrate, INPUT_PULLUP); //Activate internal 40k resistor to +5V;
      pinMode(BUTTON_Lever, INPUT_PULLUP); //Activate internal 40k resistor to +5V;
      attachInterrupt(digitalPinToInterrupt(BUTTON_Vibrate), Strobe, CHANGE); // pressed
      attachInterrupt(digitalPinToInterrupt(BUTTON_Lever), RunningLights, CHANGE); // pressed
      
}
void loop() { 
  switch(selectedEffect) {
    case 0 : {
         // Strobe - Color (red, green, blue), number of flashes, flash speed, end pause
         Strobe(0xff, 0xff, 0xff, 10, 50, 1000);
         delay (2000);
         break;
       }
    case 1 : {
         // Running Lights - Color (red, green, blue), wave dealy
         // RunningLights(0xff,0x00,0x00, 50); // red
         // RunningLights(0xff,0xff,0xff, 50); // white
         RunningLights(0x00,0x00,0xff, 50); // blue
         delay (2000);
         break;        
       }
            
    default : {
         // meteorRain - Color (red, green, blue), meteor size, trail decay, random trail decay (true/false), speed delay 
         meteorRain(0xff,0xff,0xff,10, 64, true, 30);  
       
         // FadeInOut - Color (red, green. blue)
         // FadeInOut(0xff, 0x00, 0x00); // red
         // FadeInOut(0xff, 0xff, 0xff); // white 
         FadeInOut(0x00, 0x00, 0xff); // blue
         break;
       }    
 }
}
// *************************
// ** LEDEffect Functions **
// *************************
void FadeInOut(byte red, byte green, byte blue){
  float r, g, b;
      
  for(int k = 0; k < 256; k=k+1) { 
    r = (k/256.0)*red;
    g = (k/256.0)*green;
    b = (k/256.0)*blue;
    setAll_Ring(r,g,b);
    showStrip_2();
  }
  for(int k = 255; k >= 0; k=k-2) {
    r = (k/256.0)*red;
    g = (k/256.0)*green;
    b = (k/256.0)*blue;
    setAll_Ring(r,g,b);
    showStrip_2();
  }
}
void Strobe(byte red, byte green, byte blue, int StrobeCount, int FlashDelay, int EndPause){
  for(int j = 0; j < StrobeCount; j++) {
    setAll_Ring(red,green,blue);
    showStrip_1();
    showStrip_2();
    delay(FlashDelay);
    setAll_Ring(0,0,0);
    showStrip_1();
    showStrip_2();
    delay(FlashDelay);
  }
 delay(EndPause);
}
void RunningLights(byte red, byte green, byte blue, int WaveDelay) {
  int Position=0;
  for(int i=0; i<NUM_LEDS_Ring*2; i++)
  {
      Position++; // = 0; //Position + Rate;
      for(int i=0; i<NUM_LEDS_Ring; i++) {
        // sine wave, 3 offset waves make a rainbow!
        //float level = sin(i+Position) * 127 + 128;
        //setPixel(i,level,0,0);
        //float level = sin(i+Position) * 127 + 128;
        setPixel(i,((sin(i+Position) * 127 + 128)/255)*red,
                   ((sin(i+Position) * 127 + 128)/255)*green,
                   ((sin(i+Position) * 127 + 128)/255)*blue);
      }
      
      showStrip_2();
      delay(WaveDelay);
  }
}
void theaterChase(byte red, byte green, byte blue, int SpeedDelay) {
  for (int j=0; j<10; j++) { //do 10 cycles of chasing
    for (int q=0; q < 3; q++) {
      for (int i=0; i < NUM_LEDS_Ring; i=i+3) {
        setPixel(i+q, red, green, blue); //turn every third pixel on
      }
      showStrip_2();
     
      delay(SpeedDelay);
     
      for (int i=0; i < NUM_LEDS_Ring; i=i+3) {
        setPixel(i+q, 0,0,0); //turn every third pixel off
      }
    }
  }
}
void meteorRain(byte red, byte green, byte blue, byte meteorSize, byte meteorTrailDecay, boolean meteorRandomDecay, int SpeedDelay) {  
  setAll_Strips(0,0,0);
  
  for(int i = 0; i < NUM_LEDS_Strips+NUM_LEDS_Strips; i++) {
    
    
    // fade brightness all LEDs one step
    for(int j=0; j<NUM_LEDS_Strips; j++) {
      if( (!meteorRandomDecay) || (random(10)>5) ) {
        fadeToBlack(j, meteorTrailDecay );        
      }
    }
    
    // draw meteor
    for(int j = 0; j < meteorSize; j++) {
      if( ( i-j <NUM_LEDS_Strips) && (i-j>=0) ) {
        setPixel(i-j, red, green, blue);
      } 
    }
   
    showStrip_1();
    delay(SpeedDelay);
  }
}
// used by meteorrain
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
   ledsStrips[ledNo].fadeToBlackBy( fadeValue );
 #endif  
}
// ***************************************
// ** FastLed/NeoPixel Common Functions **
// ***************************************
// Apply LED color changes to Strips
void showStrip_1() {
 #ifdef ADAFRUIT_NEOPIXEL_H 
   // NeoPixel
   strip.show();
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   FastLED[0].showLeds();
 #endif
}
// Apply LED color changes to Ring
void showStrip_2() {
 #ifdef ADAFRUIT_NEOPIXEL_H 
   // NeoPixel
   strip.show();
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   FastLED[1].showLeds();
 #endif
}
// Set a LED color (not yet visible)
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
   ledsStrips[Pixel].r = red;
   ledsStrips[Pixel].g = green;
   ledsStrips[Pixel].b = blue;
   ledsRing[Pixel].r = red;
   ledsRing[Pixel].g = green;
   ledsRing[Pixel].b = blue;
 #endif
}
// Set all LEDs to a given color and apply it (visible)
void setAll_Strips(byte red, byte green, byte blue) {
  for(int i = 0; i < NUM_LEDS_Strips; i++ ) {
    setPixel(i, red, green, blue); 
   }
  showStrip_1();
}
// Set all LEDs to a given color and apply it (visible)
void setAll_Ring(byte red, byte green, byte blue) {
    for(int i = 0; i < NUM_LEDS_Ring; i++ ) {
    setPixel(i, red, green, blue); 
  }
  showStrip_2();

   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2660
 

Hi Supramp,

well, my first advice would be to start from scratch, so the basics become much clearer.
this is what I typically do when I am getting lost in my own code hahah .

So we have 2 strands and one LED ring, and 2 switches. One switch triggers an effect on the strands and ring, and the other switch triggers another effect on both.

Since, even if it's just temporary, 2 effects have to run simultaneously (correct me if I misunderstood), I'd say that this would be the first challenge.
As the Arduino is not a multitasker (unlike a computer or a Raspberry Pi); we will need to merge effects.
Each effect requires a sequence of steps that have to run (almost) simultaneously

So if effect 1 requires steps A-B-C-D-E-F and effect 2 requires G-H-I-J then we need to glue those together.
Eg. A-G-B-H-C-I-D-J-E-G-F-H (you see how the steps run out of sync? another problem to address!)

I'd first try to make a sketch that runs the effects simultaneously (no switch involved yet).
This way you can make the function for button 1 and one for button 2.
Having played with effects, this can take some effort, especially when it comes to timing.

So in your case; make one sketch that does meteor rain on the 2 strips AND fade in/out on the ring.
Again; do not pay attention to the switches just yet and ignore the other effect.

After that, create a sketch that just does the 2 second strobe and the running lights at the same time.
Also without paying attention to the switches.

Once those work, you can extract the code and make them a function (eg. MyEffect1() and MyEffect2()) so you can then more easily call them when a button is pressed.

Unfortunately, I'm on vacation, and I have nothing with me to test anything with ... but feel free to ask.


   
ReplyQuote
(@supramp)
Active Member
Joined: 5 years ago
Posts: 16
Topic starter  

Sounds like a plan.  I too am a little busy at the moment.  I will work on the first part as you recommended and paste it here when I have an update.  Thanks


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2660
 

No worries - the forum isn't going anywhere.
This way though, things are less of spaghetti bundle (happens to me at times as well, and I then just start over).

Feel free to ask question! 


   
ReplyQuote
(@supramp)
Active Member
Joined: 5 years ago
Posts: 16
Topic starter  

I know you are on vacation, so no rush.  HAVE FUN!

OK, so I have started re-writing the sketch from scratch. first hurdle to overcome is that I have multiple strands with differing number of LEDS, so I would think the first step is establishing both strands:

// How many leds in your strands?
#define NUM_LEDS_Strips 72
#define NUM_LEDS_Ring 60

then setting them as CRGB and defining the number of strips as 2 so that I can use controllers to differentiate the  two different pins for separate effects.

// How many strands
#define NUM_STRIPS 2
//Establish that all Leds are CRGB
CRGB ledsStrips[NUM_LEDS_Strips];
CRGB ledsRing[NUM_LEDS_Ring];

Assuming this is correct thus far, the next step is to set the controller

//Establish controllers for each strand and brightness
CLEDController *controllers[NUM_STRIPS];
uint8_t gBrightness = 128;

and then the setup, which sets the LED type, pin, controller, etc;

void setup(){
      controllers[0] = &FastLED.addLeds<WS2812B, 4, RGB>(ledsStrips, NUM_LEDS_Strips);
      controllers[1] = &FastLED.addLeds<WS2812B, 5, RGB>(ledsRing, NUM_LEDS_Ring);

I am hoping you will know if any of this is wrong so far, but I will go on.  

What changes I have made so far;

Change all "NUM_LEDS" to "NUM_LEDS_Strips" or "NUM_LEDS_Ring" depending on what effect plays on what strand/pin.  Assuming it would otherwise error out due to a lack of defined "NUM_LEDS" in the scope.

Now, let me explain how I am understanding the effect functions, so my next question might make sense.

MeteorRain > runs the script for void MeteorRain> setAll> runs the void setALL function> showStrip> runs void showStrip function>FastLED.show

Question 1.  Does the FastLED.show function only show to the Led strips on pin 4 because it is sent to the corresponding controller placed in the MeteorRain call (see sketch below)  or is it being sent to all because of the setALL function,  if so, can I label setALL function as 2 different functions and have them called separately? IE setAll_1 and setAll_2

Question 2.  in the setAll function at the bottom, it calls to "NUM_LEDS" for calculations, will this matter for the ring? Do I need to add another line to run the calculations for :NUM_LEDS_Ring"?

I have highlighted the major changes to your original commands. Hopefully I did it correctly.

//******METEOR RAIN and FADE STRIP COMMAND*********
#include "FastLED.h"
// How many leds in your strands?
#define NUM_LEDS_Strips 72
#define NUM_LEDS_Ring 60
// How many strands
#define NUM_STRIPS 2
//Establish that all Leds are CRGB
CRGB ledsStrips[NUM_LEDS_Strips];
CRGB ledsRing[NUM_LEDS_Ring];

//Establish controllers for each strand and brightness
CLEDController *controllers[NUM_STRIPS];
uint8_t gBrightness = 128;

void setup(){
      controllers[0] = &FastLED.addLeds<WS2812B, 4, RGB>(ledsStrips, NUM_LEDS_Strips);
      controllers[1] = &FastLED.addLeds<WS2812B, 5, RGB>(ledsRing, NUM_LEDS_Ring);

}
// ********************************** REPLACE FROM HERE *********************************
void loop() {
//
*********************** ---> here we call the effect function <--- *****************
  meteorRain(0x00,0x00,0xff,10, 64, true, 30); // blue meteor rain
  controllers[0]->showLeds(gBrightness); // hoping this will draw the effect called to the Strips
  FadeInOut(0x00, 0x00, 0xff); // blue fade in-out
  controllers[1]->showLeds(gBrightness); // hoping this will draw the effect called to the Ring
}
//
********************* ---> here we define the effect function <--- *******************
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_Strips+NUM_LEDS_Strips; i++) {
       
    // fade brightness all LEDs one step
    for(int j=0; j<NUM_LEDS_Strips; j++) {
      if( (!meteorRandomDecay) || (random(10)>5) ) {
        fadeToBlack(j, meteorTrailDecay );        
      }
    }   
    // draw meteor
    for(int j = 0; j < meteorSize; j++) {
      if( ( i-j <NUM_LEDS_Strips) && (i-j>=0) ) {
        setPixel(i-j, red, green, blue);
      } 
    }
     showStrip();
    delay(SpeedDelay);
  }
}
void FadeInOut(byte red, byte green, byte blue){
  float r, g, b;
      
  for(int k = 0; k < 256; k=k+1) { 
    r = (k/256.0)*red;
    g = (k/256.0)*green;
    b = (k/256.0)*blue;
    setAll(r,g,b);
    showStrip();
  }
     
  for(int k = 255; k >= 0; k=k-2) {
    r = (k/256.0)*red;
    g = (k/256.0)*green;
    b = (k/256.0)*blue;
    setAll(r,g,b);
    showStrip();
  }
}
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  
}
// ************************************ REPLACE TO HERE **************************************
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_Strips; i++ ) {
    setPixel(i, red, green, blue); 
  }
  showStrip();
}

   
ReplyQuote


 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2660
 

I'll always try to answer when I can , but thanks for considering my vacation 

At first glance;

I recall you saying that the two strips are connected in parallel. This means that in essence you have only one strip (and the ring).

So I'd skip defining those as 2 individual strands and start something like this;

#include "FastLED.h"
// How many leds in your strands?
#define NUM_LEDS_Strips 72
#define NUM_LEDS_Ring 60
// Define the pins we use
#define PIN_Strips 4
#define PIN_Ring 5
//Establish that all Leds are CRGB
CRGB ledsStrips[NUM_LEDS_Strips];
CRGB ledsRing[NUM_LEDS_Ring];
// Brightness
uint8_t gBrightness = 128;
...
void setup()
{ // Add the strip and the ring
    FastLED.addLeds<WS2811, PIN_Strips, RGB>(ledsStrips, NUM_LEDS_Strips).setCorrection( TypicalLEDStrip );
    FastLED.addLeds<WS2811, PIN_Ring, RGB>(ledsRing, NUM_LEDS_Ring).setCorrection( TypicalLEDStrip );
    ...
}

Note: This example on how to use multiple LED strips - maybe you've already read it. Also remember: the 2 strips in parallel are seen as just one single strip. In that article the actually control each strip individually, but like I said: you can connect the two strips in parallel (both to pin 4) and they should both do the same thing.

Think of it this way; when setting the LED colors, little packets are send out from pin 4. Each LED (those tiny block are actually small controller chips and 3 LEDs combined - Red, Green and Blue, so we can make colors) will take the package intended for this LED, and will pass on the other packets to the next LED.
When sending all this data to PIN 4, with both strips in parallel, then both strips will receive exactly the same data. As of the first LED, the strips have no clue there is a strip running in parallel and the should not interfere and will produce the same effect in parallel.

Answer 1 & 2;

I think FastLED.Show will send the proper data to all LEDs, and all pins, at once so the values we've set for the individual LEDs will become visible.
If you want to go the controller route (not sure if it's needed), then I think there is a function ShowLeds which can be called from each controller (I've never used it). So you your code (I'm not using the controllers, but that's because I've needed or used it) something like this (see documentation);

controllers[0].ShowLeds();

Since I've never used Controllers, I'm not sure if the SetAll function will work properly. I'd have to test that.

If I've understood the documentation properly, then you could use the following instead of SetAll():

controllers[0].ShowColor(color,brightness);

This would then have to be done for the strip and the ring separately.
So in that aspect using 2 controllers may actually be better - I hope this helps and doesn't make things more confusing 


   
ReplyQuote
(@supramp)
Active Member
Joined: 5 years ago
Posts: 16
Topic starter  

Update.  I have the strands and the ring all wired up for testing. after a 10 minute panic session as to why just the basic meteor rain wasnt working (forgot to merge the grounds on my power pack to baord) I am at this point. The strands, and the ring perform meteor rain, and then fade in/out, rinse and repeat.  now to figure out how to seperate them.  saving the sketch amd renaming it to try some things with the controller [0].showLeds idea.

//******METEOR RAIN and FADE STRIP COMMAND*********
#include "FastLED.h"
// How many leds in your strands?
#define NUM_LEDS_Strips 72
#define NUM_LEDS_Ring 60
// How many strands
#define PIN_Strips 4
#define PIN_Ring 5
#define NUM_STRIPS 2
//Establish that all Leds are CRGB
CRGB ledsStrips[NUM_LEDS_Strips];
CRGB ledsRing[NUM_LEDS_Ring];
//Establish controllers for each strand and brightness
CLEDController *controllers[NUM_STRIPS];
uint8_t gBrightness = 128;
void setup(){
      controllers[0] = &FastLED.addLeds<WS2812B, PIN_Strips, RGB>(ledsStrips, NUM_LEDS_Strips);
      controllers[1] = &FastLED.addLeds<WS2812B, PIN_Ring, RGB>(ledsRing, NUM_LEDS_Ring);
}
// ********************************** REPLACE FROM HERE *********************************
void loop() {
//
*********************** ---> here we call the effect function <--- *****************
  meteorRain(0x00,0x00,0xff,10, 64, true, 15); // blue meteor rain
  controllers[0]->showLeds(gBrightness); // hoping this will draw the effect called to the Strips
  FadeInOut(0x00, 0x00, 0xff); // blue fade in-out
  controllers[1]->showLeds(gBrightness); // hoping this will draw the effect called to the Ring
}
//
********************* ---> here we define the effect function <--- *******************
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_Strips+NUM_LEDS_Strips; i++) {
       
    // fade brightness all LEDs one step
    for(int j=0; j<NUM_LEDS_Strips; j++) {
      if( (!meteorRandomDecay) || (random(10)>5) ) {
        fadeToBlack(j, meteorTrailDecay );        
      }
    }   
    // draw meteor
    for(int j = 0; j < meteorSize; j++) {
      if( ( i-j <NUM_LEDS_Strips) && (i-j>=0) ) {
        setPixel(i-j, red, green, blue);
      } 
    }
     showStrip();
    delay(SpeedDelay);
  }
}
void FadeInOut(byte red, byte green, byte blue){
  float r, g, b;
      
  for(int k = 0; k < 256; k=k+1) { 
    r = (k/256.0)*red;
    g = (k/256.0)*green;
    b = (k/256.0)*blue;
    setAll(r,g,b);
    showStrip();
  }
     
  for(int k = 255; k >= 0; k=k-2) {
    r = (k/256.0)*red;
    g = (k/256.0)*green;
    b = (k/256.0)*blue;
    setAll(r,g,b);
    showStrip();
  }
}
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
   ledsStrips[ledNo].fadeToBlackBy( fadeValue );
 #endif  
}
// ************************************ REPLACE TO HERE **************************************
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
   ledsStrips[Pixel].r = red;
   ledsStrips[Pixel].g = green;
   ledsStrips[Pixel].b = blue;
 #endif
}
void setAll(byte red, byte green, byte blue) {
  for(int i = 0; i < NUM_LEDS_Strips; i++ ) {
    setPixel(i, red, green, blue); 
  }
  showStrip();
}

   
ReplyQuote
(@supramp)
Active Member
Joined: 5 years ago
Posts: 16
Topic starter  

Side note.  I also removed the NUM_STRIPS, and all controller functions, but it still sent the data to both pins, but both effects like before. Cant seem to get the meteor rain to just the strips, and the fade to the ring alone. still working on it.


   
ReplyQuote
(@supramp)
Active Member
Joined: 5 years ago
Posts: 16
Topic starter  

i stand corrected. I had the ring on pin 4 with the strands of the breadboard. turns out, i was getting no signal to pin 5


   
ReplyQuote
(@supramp)
Active Member
Joined: 5 years ago
Posts: 16
Topic starter  

I GOT IT!  Well, mostly, lol.  I got it to where Pin 4 is showing MeteoRain and Pin 5 shows FadeInOut.  Problem now is that the meteor has to shoot and fade before the ring will start the fade sequence.  Is there a way that they can both run simultaneously?

//******METEOR RAIN and FADE STRIP COMMAND******
#include "FastLED.h"
// How many leds in your strands?
#define NUM_LEDS_Strips 72
#define NUM_LEDS_Ring 60
// How many strands
#define PIN_Strips 4
#define PIN_Ring 5
//Establish that all Leds are CRGB
CRGB ledsStrips[NUM_LEDS_Strips];
CRGB ledsRing[NUM_LEDS_Ring];

void setup(){
      FastLED.addLeds<WS2812B, PIN_Strips, RGB>(ledsStrips, NUM_LEDS_Strips);
      FastLED.addLeds<WS2812B, PIN_Ring, RGB>(ledsRing, NUM_LEDS_Ring);
}
//
******************************* REPLACE FROM HERE *********************************
void loop() {
//
*********************** ---> here we call the effect function <--- *****************
  meteorRain(0x00,0x00,0xff,10, 64, true, 15); // blue meteor rain
  
  FadeInOut(0x00, 0x00, 0xff); // blue fade in-out
 
}
//
********************* ---> here we define the effect function <--- *******************
void meteorRain(byte red, byte green, byte blue, byte meteorSize, byte meteorTrailDecay, boolean meteorRandomDecay, int SpeedDelay) {  
  setAll_0(0,0,0);
    for(int i = 0; i < NUM_LEDS_Strips+NUM_LEDS_Strips; i++) {
       
    // fade brightness all LEDs one step
    for(int j=0; j<NUM_LEDS_Strips; j++) {
      if( (!meteorRandomDecay) || (random(10)>5) ) {
        fadeToBlack(j, meteorTrailDecay );        
      }
    }   
    // draw meteor
    for(int j = 0; j < meteorSize; j++) {
      if( ( i-j <NUM_LEDS_Strips) && (i-j>=0) ) {
        setPixel_0(i-j, red, green, blue);
      } 
    }
     showStrip_0();
    delay(SpeedDelay);
  }
}
void FadeInOut(byte red, byte green, byte blue){
  float r, g, b;
      
  for(int k = 0; k < 256; k=k+1) { 
    r = (k/256.0)*red;
    g = (k/256.0)*green;
    b = (k/256.0)*blue;
    setAll_1(r,g,b);
    showStrip_1();
  }
     
  for(int k = 255; k >= 0; k=k-2) {
    r = (k/256.0)*red;
    g = (k/256.0)*green;
    b = (k/256.0)*blue;
    setAll_1(r,g,b);
    showStrip_1();
  }
}
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
   ledsStrips[ledNo].fadeToBlackBy( fadeValue );
 #endif  
}
// ************************************ REPLACE TO HERE **************************************
void showStrip_0() {
 #ifdef ADAFRUIT_NEOPIXEL_H 
   // NeoPixel
   strip.show();
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   FastLED[0].showLeds();
 #endif
}
void showStrip_1() {
 #ifdef ADAFRUIT_NEOPIXEL_H 
   // NeoPixel
   strip.show();
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   FastLED[1].showLeds();
 #endif
}
void setPixel_0(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
   ledsStrips[Pixel].r = red;
   ledsStrips[Pixel].g = green;
   ledsStrips[Pixel].b = blue;
 #endif
}
void setPixel_1(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
   ledsRing[Pixel].r = red;
   ledsRing[Pixel].g = green;
   ledsRing[Pixel].b = blue;
 #endif
}
void setAll_0(byte red, byte green, byte blue) {
  for(int i = 0; i < NUM_LEDS_Strips; i++ ) {
    setPixel_0(i, red, green, blue); 
  }
  showStrip_0();
}
void setAll_1(byte red, byte green, byte blue) {
  for(int i = 0; i < NUM_LEDS_Strips; i++ ) {
    setPixel_1(i, red, green, blue); 
  }
  showStrip_1();
}


   
ReplyQuote


(@supramp)
Active Member
Joined: 5 years ago
Posts: 16
Topic starter  

ok, now I have both buttons working almost how I want it, but still trying to figure out to get the fade and meteor simultaneous and not one after the other. heres where I am at.

//******METEOR RAIN and FADE STRIP COMMAND******
#include "FastLED.h"
// How many leds in your strands?
#define NUM_LEDS_Strips 72
#define NUM_LEDS_Ring 60
// How many strands
#define PIN_Strips 4
#define PIN_Ring 5
#define BUTTON_Vibrate 2 // vibration sensor for strobe effect
#define BUTTON_Lever 3 // lever reed switch for chase effect 

//Establish that all Leds are CRGB
CRGB ledsStrips[NUM_LEDS_Strips];
CRGB ledsRing[NUM_LEDS_Ring];
void setup(){
      FastLED.addLeds<WS2812B, PIN_Strips, RGB>(ledsStrips, NUM_LEDS_Strips);
      FastLED.addLeds<WS2812B, PIN_Ring, RGB>(ledsRing, NUM_LEDS_Ring);
      pinMode(BUTTON_Vibrate, INPUT_PULLUP); //Activate internal 40k resistor to +5V;
      pinMode(BUTTON_Lever, INPUT_PULLUP); //Activate internal 40k resistor to +5V;
      attachInterrupt(digitalPinToInterrupt(BUTTON_Vibrate), Strobe, CHANGE); // pressed
      attachInterrupt(digitalPinToInterrupt(BUTTON_Lever), RunningLights, CHANGE); // pressed
}
//
******************************* REPLACE FROM HERE *********************************
void loop() {
//
*********************** ---> here we call the effect function <--- *****************
  meteorRain(0xff,0xff,0xff,10, 64, true, 15); // blue meteor rain
  
  FadeInOut(0xff, 0xff, 0xff); // blue fade in-out
 
}
//
********************* ---> here we define the effect function <--- *******************
void meteorRain(byte red, byte green, byte blue, byte meteorSize, byte meteorTrailDecay, boolean meteorRandomDecay, int SpeedDelay) {  
  setAll_0(0,0,0);
    for(int i = 0; i < NUM_LEDS_Strips+NUM_LEDS_Strips; i++) {
       
    // fade brightness all LEDs one step
    for(int j=0; j<NUM_LEDS_Strips; j++) {
      if( (!meteorRandomDecay) || (random(10)>5) ) {
        fadeToBlack(j, meteorTrailDecay );        
      }
    }   
    // draw meteor
    for(int j = 0; j < meteorSize; j++) {
      if( ( i-j <NUM_LEDS_Strips) && (i-j>=0) ) {
        setPixel_0(i-j, red, green, blue);
      } 
    }
     showStrip_0();
    delay(SpeedDelay);
  }
}
void FadeInOut(byte red, byte green, byte blue){
  float r, g, b;
      
  for(int k = 0; k < 256; k=k+1) { 
    r = (k/256.0)*red;
    g = (k/256.0)*green;
    b = (k/256.0)*blue;
    setAll_1(r,g,b);
    showStrip_1();
  }
     
  for(int k = 255; k >= 0; k=k-2) {
    r = (k/256.0)*red;
    g = (k/256.0)*green;
    b = (k/256.0)*blue;
    setAll_1(r,g,b);
    showStrip_1();
  }
}
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
   ledsStrips[ledNo].fadeToBlackBy( fadeValue );
 #endif  
}
void Strobe(byte red, byte green, byte blue, int StrobeCount, int FlashDelay, int EndPause){
  for(int j = 0; j < 10; j++) {
    setAll_0(0xff,0xff,0xff);
    setAll_1(0xff,0xff,0xff);
    showStrip_0();
    showStrip_1();
    delay(50);
    setAll_0(0,0,0);
    setAll_1(0,0,0);
    showStrip_0();
    showStrip_1();
    delay(50);
  }
 delay(25);
}
void RunningLights(byte red, byte green, byte blue, int WaveDelay) {
  int Position=0;
  
  for(int j=0; j<NUM_LEDS_Ring*2; j++)
  {
      Position++; // = 0; //Position + Rate;
      for(int i=0; i<NUM_LEDS_Strips; i++) {
        // sine wave, 3 offset waves make a rainbow!
        //float level = sin(i+Position) * 127 + 128;
        //setPixel(i,level,0,0);
        //float level = sin(i+Position) * 127 + 128;
        setPixel_0(i,((sin(i+Position) * 127 + 128)/255)*0xff,
                   ((sin(i+Position) * 127 + 128)/255)*0xff,
                   ((sin(i+Position) * 127 + 128)/255)*0xff);
        setPixel_1(i,((sin(i+Position) * 127 + 128)/255)*0xff,
                   ((sin(i+Position) * 127 + 128)/255)*0xff,
                   ((sin(i+Position) * 127 + 128)/255)*0xff);
      }
      
      showStrip_0();
      showStrip_1();
      delay(10);
      setAll_0(0,0,0);
      setAll_1(0,0,0);
  }
}
// ************************************ REPLACE TO HERE **************************************
void showStrip_0() {
 #ifdef ADAFRUIT_NEOPIXEL_H 
   // NeoPixel
   strip.show();
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   FastLED[0].showLeds();
 #endif
}
void showStrip_1() {
 #ifdef ADAFRUIT_NEOPIXEL_H 
   // NeoPixel
   strip.show();
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   FastLED[1].showLeds();
 #endif
}
void setPixel_0(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
   ledsStrips[Pixel].r = red;
   ledsStrips[Pixel].g = green;
   ledsStrips[Pixel].b = blue;
 #endif
}
void setPixel_1(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
   ledsRing[Pixel].r = red;
   ledsRing[Pixel].g = green;
   ledsRing[Pixel].b = blue;
 #endif
}
void setAll_0(byte red, byte green, byte blue) {
  for(int i = 0; i < NUM_LEDS_Strips; i++ ) {
    setPixel_0(i, red, green, blue); 
  }
  showStrip_0();
}
void setAll_1(byte red, byte green, byte blue) {
  for(int i = 0; i < NUM_LEDS_Strips; i++ ) {
    setPixel_1(i, red, green, blue); 
  }
  showStrip_1();
}

Probably a better way to do this that would take up less memory, but Im doing the best I can, lol.  Its about 7.2kb att he moment, which is still well under the Nano's 32kb flash memory limit.


   
ReplyQuote
(@supramp)
Active Member
Joined: 5 years ago
Posts: 16
Topic starter  

So here is a short video of it working in it's current state. Granted, I only have about 8 amps available so it's not its peak color or brightness, but it will give you a better idea of where I'm at with the sketch i just posted. I also decided to make the strands run the running lights effect too. Wanted to see how it looked, lol


   
ReplyQuote
(@supramp)
Active Member
Joined: 5 years ago
Posts: 16
Topic starter  

I have been scouring the web looking for a solution. What I have found is that I can make meteor rain and fade run simultaneously by housing millis but I cant understand how it works or how to implement it into what I already have. Am I on the right track and do you know how?


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2660
 

The hurdle you're facing right now, is indeed a little bit of a challenge, as I mentioned earlier.
The Arduino is not made for multitasking, which is what you'd like to use for this issue.

The alternative is combining both functions into one, where each step of both effects is executed in sequence.
So do LED1 of the fade, do LED1 of meteor, do LED2 of fade, do LED2 of meteor, etc etc.

A few challenges with that will be that both will have one or the other loop in it doing all LEDs. Additionally the effect may become slower than desired.

This AdaFruit article will show this in more detail. But be warned that this may be more complex than desired. You'll see that timing becomes a challenge, code becomes extensive and sometimes a little harder to read, and the optional use of classes can be challenging as well.
This Instructable article shows a little more (even though it's a different kind of project) about timing issues and has some good pictures with it to make it more understandable.

There is a more advanced way of mimicking multitasking using interrupts (not recommended for beginners, but hey, you can take look for sure ).
And there are a few libraries out there supporting multitasking (kinda anyway), like this one for example.
This article may be helpful as well, which expands the Arduino framework (I have not tested any of these).


   
ReplyQuote
(@supramp)
Active Member
Joined: 5 years ago
Posts: 16
Topic starter  

Well, I am pretty happy with where I am at right now.  Pretty proud of myself, and I really appreciate the help. I was wondering one more thing.  Is there a way to shorten the run time for "runningLights".  The delay merely effects the speed that the sin wave moves, but the overall effect time doesn't seem to really change much.  I just want to shorten it to about 1000ms to 1500ms


   
ReplyQuote


Page 1 / 2

Like what you see and you'd like to help out? 

The best way to help is of course by assisting others with their questions here in the forum, but you can also help us out in other ways:

- Do your shopping at Amazon, it will not cost you anything extra but may generate a small commission for us,
- send a cup of coffee through PayPal ($5, $10, $20, or custom amount),
- become a Patreon,
- donate BitCoin (BTC), or BitCoinCash (BCH).

Share: