For those who are interested in dithering and smooth (long tail) fades.

For those who are interested in dithering and smooth (long tail) fades. I continued with my quest on getting the smooth fades like I can get with FadeCandy. FastLED dithering is brilliant but works on master brightness not on individual pixels.

In the HexaWS2811 code Richard applied a dithering method by walking through arrays. Due the inner working of FastLED pixel values of 1 are also 0 (so not visible). The dithering first didn’t work good (pixels started to light up at a value around 30). Now there is a flag in the script to render the table for FastLED (or use the table in my example below).

For the purists we actually don’t want a gamma correction curve but a luminance correction curve. Check: http://ledshield.wordpress.com/2012/11/13/led-brightness-to-your-eye-gamma-correction-no/

Peter pointed me to the right code. I’ve made a little script to render a lookup table with this curve: https://gist.github.com/kasperkamperman/3c3f72208366ed885f2f

Raplin implemented this curve now also in his Python script to render the dither tables: https://github.com/raplin/HexaWS2811/blob/master/gamma.py

This curve is a bit brighter at the lower and the higher end. In the end the name doesn’t matter of course. I think the luminance curve looks a bit better for my design, but in some situations the gamma curve could work better as well.

In order for the dithering to work without too much flickering you have to update fast. I’m updating now every 1724us (580Hz, same as APA102 PWM) with a 4 bit table (Teensy 3.0). If you work with slower speeds I think it’s better to render a 3 bit table (on ARM probably 1 or 2 bit).

Also make sure that your timing is fixed. Doing things that take longer messes up the dither frequency.

With the introduction of parallel processing (and octoWS2811 support) in FastLED 3.1 this dither method also becomes possible with the WS2812b (using short strings). If you design for that I think you could use the FadeCandy design principle of 64 leds on one output.

Arduino/FastLED code example:
https://gist.github.com/kasperkamperman/4461a70dd0841f80ddf4

Wow! Great write up, links, and code – thank you on all counts!

As a side note, I’d say that the main topic here is not ‘dithering’, but rather " gamma correction ", and in this case the gamma correction is being implemented using temporal dithering. The reason I make the distinction is just to keep the two separate ideas clear: temporal dithering is a just rendering technique, but gamma correction is adjusting for perceived brightnesses.

FastLED uses temporal dithering (at this point) only for smooth fading using the master brightness control. (It’s also worth noting that there’s zero added CPU cost and zero RAM cost to what the library is doing – it’s all done ‘between the pixels’.)

What you’ve implemented here is gamma correction using temporal dithering at the application layer.

I have hopes to eventually have something similar in the library (between the pixels), but that will only ever be on ARM, and so far we’ve (up to v3.0) wanted to keep parity ARM and AVR.

It’s also worth noting that what you’ve implemented here is VERY similar to how I first prototyped temporal dithering for the library! It makes me happy to see the technique evolve the way you’re doing it here!

Good to here that something like this will come to a future ARM version of the library. I’m fully aware that my code gets obsolete sooner or later because of the brilliant minds of Daniel and Mark. Thanks again for sharing your knowledge and hard work with us.

I suddenly became aware that when working with FastLED for a while now I’m starting to calculate and time my effects in microseconds instead of milliseconds :slight_smile:

Hi, probably a noob question…was trying the dithering example code above but didn’t find a place where the output pin is initialized. Can you please advise…thanks

//FastLED.addLeds<WS2812B, 2, GRB>(leds, NUM_LEDS);
//FastLED.addLeds<APA102, 11, 13, BGR, DATA_RATE_MHZ(12)>(leds, NUM_LEDS);

Over here (APA102 11,13, otherwise pin 2). You can change those numbers to fit your output pin or type of led string.