FastLED - Creating a five color chasing effect

Hello there.

First time posting after reading the forums a fair bit.

New-ish coder here, a bit rusty after taking a couple decades off.

The goal of the code is to create a five color sequence of christmas colours, preferably using the BEAT8 function, so I can set the speed of the sequence. My brain likes wave functions. I'd also prefer to use the EVERY_N_MILLISECONDS function to set my timing between each colour. I tried inserting the EVERY_N_MILLISECOND function into the second band and it either duplicated the colour onto the same space as the first, or it had no effect.

The board I'm using is the Teensy 4.0 board and the LED strips are the 144 LED WS2812 strips, the NeoPixels.

The other stumbling block I ran into is when I set the code to run at 60 BPM or higher on the strips, I noticed an odd flickering before the leading color. I'd like it to look smoother. Possibly a framerate or timing issue?

Right! With that out of the way, here's the code.

#include <FastLED.h>
#define NUM_LEDS 60  //Supposed to be 144 LED's here, but 60 is in place to slow things down and to check spacing.
#define LED_PIN 1
#define FASTLED_ALLOW_INTERRUPTS 0
#define PULSE 15  //this sets how quick the LED's go from one end to the other in the strip.  15 is set so the sequence is easier to modify
CRGB leds[NUM_LEDS];



void setup() {
  FastLED.addLeds<WS2812, LED_PIN, GRB> (leds, NUM_LEDS).setCorrection(TypicalPixelString);
  FastLED.setBrightness(10);
  FastLED.setDither(0);
  FastLED.clear();
}

void loop() {
   uint8_t leader1 = map(beat8(PULSE,0), 0, 256, 0, NUM_LEDS +6);  //This is the first color in a sequence of five.  'Leader' is the keyword for the first band.  Second color band is block 1, third is block 2, and so on
   uint8_t leader2 = map(beat8(PULSE,0), 10, 256, 0, NUM_LEDS +3);
   uint8_t leader3 = map(beat8(PULSE,0), 20, 256, 0, NUM_LEDS);

   leds[leader1] = CRGB(23,117,28);
   leds[leader2] = CRGB(23,117,28);
   leds[leader3] = CRGB(23,117,28);

  fadeToBlackBy(leds, NUM_LEDS, 20);



  FastLED.show();
}

To sum up: How do I time it so that the other four colors show up in the sequence, and how do I negate any flickering?

Is your power supply adequate?

When you use 60 in the define on your 144 pixels, does the display stop at the 60th pixel?

Does beat8 make these color waves act like normal waves, and reflect off the "last" pixel, causing nodes , constructive and destructive interference?

So, the power supply is up to the task - it's programmable and it's outputting 5 volts as it should with it set to deliver a maximum of five amps.

The reason I set it at 60 LED's instead of the full 144 is because I wanted to see if there would be any issues when it was defined at a lower value. When it's set to that 60, it runs well. It stops at the 60th LED as defined. And the animation runs as expected - smooth and proper. However, when it's set to the full 144, and the BPM is 60 or lower, I get the flickering I mentioned.

It's possible it's a reflection issue like you mentioned. If so, what do I do to resolve it? Should I use a string like FastLED.delay(1000/60)? Or is there a better timing solution?

And because of the odd behaviour, I had to drop it down to a single color and single LED, just to see what's actually going on.

What I meant by this is, "Is the wave library making realistic waves" like tying a rope to a tree, shaking the rope, seeing the wave travel to the tree, reflect and return.

Flickering... if you move the signal pin from pixel zero to pixel 72 and send the code for the 60 pixel count toward 144, do you get 60 good pixels (with 72 being the zeroth pixel) or flicker? If flicker, then I would suspect an intermittent pixel. If good, I would try power injection (Vcc and GND placed farther "down" the string).

So, after testing it out using your suggestions, I can say that if I set it to LED 72, it works properly if I keep the defined length within 60 LED's. They all light up properly so I've ruled out errant LED's.

As for the reflection issue, I've narrowed it down to a highly likely cause - the LED's themselves don't really like being told what to do with a 3.3V signal. They'll behave fine for the most part if I have the saw wave BPM at 40 BPM or higher. However, they are showing what looks like bad data reflections if it's set lower - pixels further upstream lighting up for a millisecond or two, then turning back off until the command gets to them. It would be kind of a cool effect if I wanted that, but it's not what I want.

Is there a workaround to that available until I get a logic level shifter to bump up the 3.3v signal output to the 5V that the WS2812B's like?

I was assuming your WS2812 were 5vdc (or 12vdc), and you were using an external power supply to apply Vcc and GND to the WS2812.

Both your assumptions are correct.

Have you tried "power injection"... where you run VCC and GND to the pixel VCC and GND pads half-way down the strand, for this example, pixel 72?

I did one better. I grabbed a spare strip, 40 LED's long and hooked it up. If I have the BPM set to 20 or less, I get the same result. When I increase it higher than 20, the animation works as expected. That's giving more weight to my suspicion the LED's are having trouble registering data at 3.3v when it's at half or less BPM to LED strip length.

While I was figuring that out, I cleaned up the code a little bit.

#include <FastLED.h>

#define NUM_LEDS 40
#define LED_PIN 1
#define FASTLED_ALLOW_INTERRUPTS 0
CRGB leds [NUM_LEDS];

void setup()
{
 //Clears any residual colours away
  FastLED.clear();

   //FastLED strip setup with the proper color order
  FastLED.addLeds<WS2812B, LED_PIN, GRB> (leds, NUM_LEDS);
  
   //Colour correction for the strip, dither elimination, and light level
  FastLED.setCorrection(TypicalPixelString);
  FastLED.setDither(0);
  FastLED.setBrightness (25);
}

void loop() {

//Serial.begin (1800);
uint8_t waveform = map((beat8(25)), 0, 255, 0, NUM_LEDS);  //Note:  BPM is set to 25 and two lines removed for troubleshooting isolation.  Revise ASAP when the reflection issue is resolved, either through a workaround or a logic level shifter.
//Serial.println(waveform);

leds [waveform] = CRGB::Red;

fadeToBlackBy (leds, NUM_LEDS, 20);

FastLED.show();



}

Just a quick note, I also tried power injection on the 144LED strip at LED 72, like you suggested. No difference. As always, the help is appreciated. I wouldn't be able to do this without you guys.

At this point in time, it's looking like an issue that I'll have to resolve at a later time. I'm starting to run low on time here; I'm really hoping I can have this wrapped up by the weekend for a parade, so I need to prioritize the bigger issue. Adding more LED's to the single LED that moves up the strip. I've been looking into arrays the past few days and it looks like I have a string that works.

CRGBArray<NUM_LEDS> leds;


void setup() { 
  FastLED.clear();
  FastLED.addLeds<WS2812B, LED_PIN, GRB> (leds, NUM_LEDS);
  FastLED.setCorrection(TypicalPixelString);
  FastLED.setDither(1);
  FastLED.setBrightness (25);
  
}

void loop(){ 
  
   leds(0,12).fill_solid(CRGB::Orange);

  FastLED.show();
}

What I'd really like to get nailed down, in the next few days if possible, is a method to attach

uint8_t waveform = map((beat8(25)), 0, 255, 0, NUM_LEDS);

to

leds(0,12).fill_solid(CRGB::Orange);

and I'm stumped.

This is the "cylon" effect, where you have the main pixel light and (pixel - 1), (pixel -2), (pixel +1), (pixel + 2) at dimmer levels...

I know that. Had a look at the code beforehand, thinking it would help out. It wasn't really using an array, so I had to do a workaround

As for the odd flickering, I figured that out aswell. It was FASTLED_ALLOW_INTERRUPTS 0

I think I can consider this topic done because I'm out of time and I I'm using what I was able to hack together.

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