I'm trying to send off multiple 'chase' effects based on serial input.

I’m trying to send off multiple ‘chase’ effects based on serial input.
I can’t seem to figure out how to trigger a new effect, while keeping the previous effects going until the end of the strip. Can anyone point me in the right direction? Here’s kind of an example of what I’m looking for: https://www.youtube.com/watch?v=JFEiGnH4QkY&t=7s

I don’t see the pattern ending before changing, but i do see a continuous fade out, so if the pattern does change, the old pattern stops, fades down and the new pattern starts.

This isn’t hard to code, and provides a quicker response to change

If it’s just “chase” effects you want then you could try shifting the entire array along by one pixel each time round the loop, discarding the last pixel and introducing new pixels at the beginning according to what colour you are currently injecting.
Also, each time round the loop, you should check for serial input ( by looking at the value of Serial.available() ) and then act on it if you have enough characters to make up a command.

@Zaphod_Beeblewurdle Thanks. How do you keep track of the pixels and introduce new pixels while the old ones are fading? I’ve tried keeping track of a dynamic array and shifting those values down as they new pixels are introduced, while incrementing the values themselves to reflect the position on the LED strip, but that did not seem to work. I feel like there should be an easier way. Any pseudo code would be much appreciated!!

Shifting pixels is straightforward:

for(int i =NUM_LEDS-1; i>1; i–)
{
leds[i] = leds[i-1];
}

Then you can fade all pixels towards a background colour like this (where amt is 0…255 where 0 means no fade, 255 means fade out in one step, adjust to suit your needs )

CRGB target=CRGB(targetColour);

for(int i=0;i<NUM_LEDS;i++) {
leds[i]=blend(leds[i],target,amt);
}

So that just leaves setting leds[0] to the colour of the stripe that you are currently generating. So the next step in the loop would be something like:

if( leds_done < stripe_size) {
leds[0] = stripe_colour;
leds_done = leds_done + 1;
}
else leds[0] = background_colour;

Then in your serial command monitor, whenever a new “send a stripe” command comes in, you would set leds_done to zero and stripe_size and stripe_colour to whatever the command specifies.

Hope that makes sense :slight_smile:

Actually, after watching the video again I see that there are multiple stripes moving at different speeds, so that would require an array of structures which describe a stripe (width, position, colour, speed ) then each time round the loop do something like:
for (int i=0;i<num_stripes;i++ ) {
stripes[i].position = stripes[i].position + stripes[i].speed;
if (stripes[i].position < NUM_LEDS) {
for(int j=0 ; j<stripes[i].width; j++) {
int L = stripes[i].position + j;
if(L < NUM_LEDS) leds[L] = stripes[i].colour;
}
} else stripes[i].speed = 0; // quick way of disabling a stripe
}

… sort of thing. Then when you want to add a new stripe in, simply find a member of stripes[] that has position > NUM_LEDS and set position to 0, and set the other properties to suit, rememebr , in this case, to initialise the stripes array with all position > NUM_LEDS toi start with in your setup() fuinction.

@Zaphod_Beeblewurdle I think i’ll stick to the first implementation for now haha. I’m trying it out now, but i have one question - what is leds_done? Don’t you need an ‘leds_done’ for each ‘chase’?

leds_done is a counter variable that keeps track of how many leds of the current stripe you have injected to the strip. That’s why it is incremented every time you set leds[0] to the stripe colour.

I seem to have done something wrong, as I can only get the 1st LED to light up now :confused:

#include <FastLED.h>

#define LED_PIN 6
#define COLOR_ORDER GRB
#define CHIPSET WS2811
#define NUM_LEDS 60

#define BRIGHTNESS 200
#define FRAMES_PER_SECOND 60

CRGB leds[NUM_LEDS];
int leds_done = 0;
char inValue = ‘x’;

void setup() {
Serial.begin(9600);
delay(1000); // sanity delay
FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
FastLED.setBrightness( BRIGHTNESS );
}

void loop() {
chase(); // run simulation frame

FastLED.show(); // display this frame
FastLED.delay(1000 / FRAMES_PER_SECOND);

if(Serial.available()) {
inValue = (char)Serial.read();
}

if(inValue == ‘a’) {
Serial.println(“Beat”);
inValue = ‘x’;
leds_done = 0;
}
}

void chase() {
//shift pixels
for(int i = NUM_LEDS - 1; i > 1; i–) {
//leds[i] = CRGB::Chartreuse;
leds[i] = leds[i-1];
}

//fade
for(int i=0; i < NUM_LEDS; i++) {
leds[i] = blend(leds[i], CRGB::Black, 150);
}

//reset?
if(leds_done < 5) {
leds[0] = CRGB::Amethyst;
leds_done = leds_done + 1;
} else {
leds[0] = CRGB::Chartreuse;
}
}

Try a much lower fade amount in the blend command, like 5 or 10, it’s pretty non linear. It might be fading too quickly.

In fact, just comment out the fade loop for testing purposes :slight_smile:

@Zaphod_Beeblewurdle Thanks for your help!!
missing/deleted image from Google+