New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Higher colour-depth emulation through temporal dithering #671

Open
fish-face opened this Issue Oct 22, 2018 · 3 comments

Comments

Projects
None yet
2 participants
@fish-face

fish-face commented Oct 22, 2018

Certain kinds of animations can run into issues with a lack of colour-depth, especially with dimmer colours - switching an LED from (0, 0, 0) to (1, 1, 1) to (2, 2, 2) is very visible at each step if it's not done quickly. This could be addressed in some situations by extending the temporal dithering code and so this would be a cool enhancement.

@focalintent

This comment has been minimized.

Member

focalintent commented Oct 25, 2018

Each extra bit of dynamic range requires, roughly, doubling the update rate - given that WS2811 leds are capped at an update rate of 400hz, the existing dithering code is already pushing the limits of what we can get out of it. The current APA102's are only running at about a 2Khz refresh rate max (yes - early APA102 chips had a 19.2khz refresh rate, but I've heard that APA has changed their manufacturing to a lower refresh rate, plus a lot of places sell the SK9822 as APA102, and that refresh rate is capped at 2khz), so we might be able to get a couple extra bits out of it - but haven't put a lot of testing into that yet.

If you want to play with this yourself, you can edit lines 244/245 in controller.h -

FastLED/controller.h

Lines 244 to 245 in fdba485

#define MAX_LIKELY_UPDATE_RATE_HZ 400
#define MIN_ACCEPTABLE_DITHER_RATE_HZ 50

At some point we will expose those, but for now you're welcome to change them to the maximum update rate that you're likely to see and the minimum frame rate that you will be drawing at (note, there is, here, a difference between frame rate - which is how many times per second you are changing the contents of the leds array and update rate - which is how many times per second you are calling FastLED.show()).

I'd love to hear if you get noticeable improvements by playing with these values on something like the APA102s.

@fish-face

This comment has been minimized.

fish-face commented Oct 25, 2018

I'm currently stuck with WS2812s but not that many of them, so can probably squeeze at least 4 updates per frame out and plan to see what it looks like after getting everything else working (I've reverted to a different effect for my project which doesn't expose the issue). I might be able to get more out but I'm not sure exactly how long FastLED.show() is taking - micros() reports 1.8ms most of the time (the correct value for my 60 LEDs - this is on a Teensy so hopefully the clock is kept reasonable accurate?) but then sometimes 2.8ms. My own code runs pretty quickly so if the updates take 1.8ms consistently then I would be able to get an extra 8 updates/3 bits of colour depth which I imagine might work well. (Although I would guess flickering would be visible in some situations - 1.8ms on the minimum brightness then 12.6ms entirely off for example)

@focalintent

This comment has been minimized.

Member

focalintent commented Oct 25, 2018

The reason for the varying times is likely because you can’t update ws2812’s more than 400 times per second (if you do they start behaving oddly/badly) - so FastLED has a rate limiter for ws2812’s - to ensure that it has been 2.5ms since the last time show was called.

Also, the teensy allows interrupts to run while writing out led data - which may also account for some of the timing variability you are seeing.

Finally, the temporal dithering, as implemented is already giving you an extra 3 bits- the dithering algorithm is tuned for 400hz refresh rate on a 50hz frame rate (give or take). (Assuming you are calling FastLED.show() roughly 400 times per second, either by way of directly calling it or using FastLED.delay())

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment