Welcome, Jason! I’m not entirely sure I understand the effect you’re looking for, but I think I have the general idea. (The big question left open in my mind about what you described is this: should the stripes completely cover the LED strip like XXYYXXYYXXYY, or do you want some ‘black’ showing between them like XX__YY__XX__YY?) In any case, my overall recommendation is to start with the simple idea, get it working, play with it, and then add bells and whistles.
So for example: I’d first try to get it all up and running without the anti-aliasing or fading – just the stripes with controlled width. Then once you’ve got that working, add in features.
This code draws moving stripes of one color on a black background. The way it works is that it thinks of the LEDs along the strip as part of a repeating cycle: some stripe pixels, some background pixels, some stripe pixels, some background pixels, and so on. The length of the whole cycle is the stripe length plus the length of the gap between stripes. So to draw the stripes, we just loop down every pixel on the strip, figure out where in the cycle we are for that pixel, and draw the right color. The drawStripes function takes one argument telling it where in the cycle to begin, and by changing that in the loop() function, the stripes should move.
#include <FastLED.h>
#define NUM_LEDS 50
CRGB leds[NUM_LEDS];
uint8_t stripeWidth = 6;
uint8_t gapBetweenStripes = 10;
CRGB stripeColor = CRGB::Orange;
CRGB backgroundColor = CRGB::Black;
void setup() {
delay(3000);
FastLED.addLeds<WS2811,3,GRB>(leds, NUM_LEDS);
}
uint8_t gPhase = 0;
void loop() {
// advance overall starting phase
gPhase = gPhase + 1;
// keep it in bounds
gPhase = gPhase % (stripeWidth + gapBetweenStripes);
drawStripes( gPhase);
FastLED.show();
FastLED.delay(20);
}
void drawStripes( uint8_t startingPhase)
{
// calculate the length of the repeating cycle
uint8_t cycleLength = (stripeWidth + gapBetweenStripes);
uint8_t curPhase = startingPhase;
// loop over all the LEDS
for( uint16_t i = 0; i < NUM_LEDS; i++) {
// for each LED, figure out where in the cycle
// we are, and choose the right color
CRGB ledColor;
if( curPhase < stripeWidth) {
// inside a stripe
ledColor = stripeColor;
} else {
// in the gap between stripes
ledColor = backgroundColor;
}
leds[i] = ledColor;
}
// advance to next phase for next pixel
curPhase++;
// if we hit the end of the cycle, start at zero again
if( curPhase == cycleLength) {
curPhase = 0;
}
}
With a relatively small change, we can have the first and last pixel of the stripe be ‘dimmed’ down for a quick-and-dirty anti-aliased effect:
void drawStripes( uint8_t startingPhase)
{
// calculate the length of the repeating cycle
uint8_t cycleLength = (stripeWidth + gapBetweenStripes);
uint8_t curPhase = startingPhase;
// loop over all the LEDS
for( uint16_t i = 0; i < NUM_LEDS; i++) {
// for each LED, figure out where in the cycle
// we are, and choose the right color
CRGB ledColor;
if( curPhase < stripeWidth) {
// inside a stripe
ledColor = stripeColor;
// first and last pixel should be dimmer
if( curPhase == 0 || curPhase == (stripeWidth-1)) {
// dim first and last pixel to 1/4 brightness.
ledColor.nscale8_video( 64);
}
} else {
// in the gap between stripes
ledColor = backgroundColor;
}
leds[i] = ledColor;
}
// advance to next phase for next pixel
curPhase++;
// if we hit the end of the cycle, start at zero again
if( curPhase == cycleLength) {
curPhase = 0;
}
}
I hope this helps give you a start. For multiple stripes, you could expand this code to think of the ‘cycle’ as having four parts instead of just two: stripe1, gap1, stripe2, and gap2. There are other ways to do it, too, of course! Let us know what you come up with after some experimentation!