Q: Slow and smooth animation without stepping?

Q: Slow and smooth animation without stepping?

Hello! First off thanks for providing this amazing library. It’s sweet.

For the past few weeks I’ve been fruitlessly trying to achieve a nice smooth animation at very slow speeds. E.g. a rainbow fill that moves along a strip over a 10 minute or longer period.

Maybe someone could nudge me in the right direction?

My latest attempt goes something like this, using two arrays and blending them together depending on where we are in time:

static uint8_t deltaHue = 255 / NUM_LEDS;
static CRGB ledBuffer[NUM_LEDS];

uint16_t thisBeat = beat88(BPM88);
uint16_t nextBeat = beat88(BPM88, BPM_PERIOD_IN_MS);
uint8_t currentHue = map(thisBeat, 0, 0xFFFF, 0, 0xFF);
uint8_t nextHue = map(nextBeat, 0, 0xFFFF, 0, 0xFF);

fill_rainbow(LEDS, NUM_LEDS, currentHue, deltaHue);
if (currentHue != nextHue) {
    fill_rainbow(ledBuffer, NUM_LEDS, nextHue, deltaHue);
    fract8 fractionOfBpmElapsed = getFractionOfBpmElapsed();
    for( int i = 0; i < NUM_LEDS; i++) {
        nblend(LEDS[i], ledBuffer[i], fraction);
    }
}

The getFractionOfBpmElapsed function returns a fract8 that is 0 if we’re on the beat and increments to 255 as we get closer to the next beat.

This blends everything additively, resulting in all the colors being off, especially in the blue/purple zone which comes out white.

I’ve found over time that incrementally increasing the distance between display elements is just a bad thing overall and gets worse the further down the strip you go. As a result, I’ve kind of given up on things like your deltaHue above. Sorry, no answers here.

The smoothest thing I’ve found is the FastLED palette transitioning, which I just love.

When the smallest step is still noticeable you could try spatial and temporal dithering:
-constantly change the display one pixel at a time in a seemingly random pattern ~ that way there are no sudden steps, just a sense of some sparkling noise. If you can achieve a really high ‘frame rate’ in your display, then you could dither from one state to the next state masking the ‘step’ between them. My understanding is that FastLED does some of this dithering for us at low brightnesses and is why any delay should be a FastLED.delay(x) to allow that dithering to work.