Flickering with low light levels on WS2812 LEDs
I’m having flickering issues that seem to have something to do with dithering. There seems to be a timing issue involved because different WS2812 strings flicker a bit differently. Even changing NUM_LEDS from 15 to 16 make a huge difference in the flicker.
When I replace the WS2812s with WS2801s, the flickering does not appear. I wonder whether this have something to do with aliasing, the update frequency of FastLED interacting with the WS2812 PWM rate of 400 hz. The WS2801s have a PWM rate of 2.5 kHz.
Note that dithering seems to be happening even though I have setBrightness(255). The dither pattern is visible, it freezes when I hit the reset button.
Here is the code:
// DitherTest.ino
#include “FastLED.h”
#define NUM_LEDS 15
#define DATA_PIN 13
#define CLOCK_PIN 12
CRGB leds[NUM_LEDS];
void setup()
{
FastLED.addLeds<WS2811, DATA_PIN, GRB>(leds, NUM_LEDS);
// FastLED.addLeds<WS2801, DATA_PIN, CLOCK_PIN>(leds, NUM_LEDS);
// FastLED.addLeds(leds, NUM_LEDS);
FastLED.setBrightness(255);
FastLED.setDither(1);
// add rainbow background
for (int i = 0; i < NUM_LEDS; i++)
leds[i] = CHSV( i * 256 / NUM_LEDS, 255, 16);;
}
void loop()
// Display pattern for three seconds dither on, three seconds dither off…
{
FastLED.setDither(1);
FastLED.delay (3000);
FastLED.setDither(0);
FastLED.delay (3000);
}
Oh, and thank you to @Mark_Kriegsman and +Daniel Garcia. I take a break for six weeks and you come up with all this amazing new work, dithering and color correction and all.
I can confirm that I get the same effect with my 8x8 Neopixel Matrix from Adafruit. When I change it to WS2812B, the flicker is still there, but not as bad.
With NUM_LEDS 15 the flickering is more like flashing lights. With NUM_LEDS 16 the flickering is just flickering.
NUM_LEDS at 35 is bad too. 15 is worse off however. Interesting…
You don’t want to be updating WS2812B’s more than 400 times a second - because then you start messing with their PWM rates. At 15 leds, that’s 0.45ms/frame, or, to put another way, you could easily see update getting called a few thousand times a second.
I haven’t yet put code in to throttle things like the WS2812’s down to no more than 400Hz, you’ll have to do that by hand for now.
This isn’t a problem with the WS2801 because the WS2801’s data rate is so slow (and their pwm rate is 6 times higher) that it’s unlikely you’d be pushing led data quickly enough 
(Though, it turns out that worldsemi may have changed things with the WS2801’s at some point to allow driving them at up to 25Mhz - but I haven’t had a chance to test that yet).
Should I just temporarily put in some code to throttle the updates? A delay(10) in the loop should do it?
You’d have to put it inside of FastLED.delay itself (or not use FastLED.delay).
Also - what hardware are you using? (If there’s something I would stamp into the forehead of every library user reporting a bug - it’s tell me what platform you’re building on! The differences between due, teensy, atmega328, attiny, etc… I usually want or need to know what platform something’s being built for).
Also - note that WS2811 and WS2812B and WS2812 are all aliases for each other - there’s no difference in the library between them (the one exception being NEOPIXEL which defaults the RGB ordering to GRB).
I also tried to set NUM_LEDS 400 and the flicker is still there, although it’s not extreme.
At 400 leds you’re going to be seeing a different flicker, namely that things are capped out at 80fps, and the current dithering code shows off some flicker at lower frame rates.
Also, finally, what hardware are you running on - if the flickering is instead being caused by a timing issue, those are going to be very hardware dependent.
The hardware I tried were both a LeoStick, a Leonardo clone, and a Boardino, a Decimelia clone. There are similar results, but I can test if you need to know if the results are exactly the same.
To be thorough, I tried NUM_LEDS at between 8 and 400 with similar results. It’s just that some numbers were worse than others. 15 seems to be the worst. 16 is not bad.
Note that I’m using setBrightness(255) throughout the code.
(N.B. I’m about to take off for 3 days, so anything that needs code changes, either @Mark_Kriegsman will need to poke at, or i’ll look into on monday).
Thanks Daniel. You deserve the break. I think that we are all amazed that the two of you do so much so quickly. You make our jobs a lot easier.
I’ll try to take a look this evening!
I’ve tried to narrow this problem down. Maybe this is better code to show the flickering. The flicker happens only on LEDs number 2 and 3, maybe 4.
Results were identical on both a Leonardo clone and a Diecimila clone.
The flicker only happens on WS2812 strips. I tried two different kinds.The flicker doesn’t happen on WS2801 strips.
Change NUM_LEDS to 15 and see it really flicker, but @Mark_Kriegsman indicated that since the LED refresh is not throttled, a setting of 15 makes the LEDs update too fast.
// DitherTestLEDsGrey.ino
#include “FastLED.h”
#define NUM_LEDS 60
#define DATA_PIN 13
#define CLOCK_PIN 12
CRGB leds[NUM_LEDS];
void setup()
{
FastLED.addLeds<WS2811, DATA_PIN, GRB>(leds, NUM_LEDS);
// FastLED.addLeds<WS2801, DATA_PIN, CLOCK_PIN>(leds, NUM_LEDS);
// FastLED.addLeds(leds, NUM_LEDS);
FastLED.setBrightness(255);
FastLED.setDither(1);
// greyscale background
for (int i = 0; i < NUM_LEDS; i++)
leds[i].r = i;
}
void loop()
{
FastLED.setDither(1);
FastLED.delay (3000);
FastLED.setDither(0);
FastLED.delay (3000);
}
60 LEDs gives you a 555hz update rate(it’s 30us per led). Still over 400.