FastLED Color Correction The green LEDs in your LED pixels shine much more brightly

FastLED Color Correction
The green LEDs in your LED pixels shine much more brightly than the red or blue LEDs; this means that any color you try to mix is inherently ‘too green’ unless you correct for that somehow. Well, FastLED v2.1 now has new features that let you control the overall color balance and temperature of your projects, so that you get exactly the colors you wanted.

As sometimes happens around here, documentation and examples are trailing behind the library code itself, but we wanted to get a basic overview of the new features out there to start letting people know what we’ve done with the library and why. We’ll post some examples this week.

You don’t have to use any of the color management functions in FastLED v2.1, but I find that at least setting the color correction to something approximately like the right values for a given LED strip (I just eyeball it and try different settings!) really makes a difference in the overall quality and appearance of the project.

And, as a final note here, all of these color transformations are performed totally inside the library; your ‘leds[]’ array is never modified, and (astonishingly!) there is no slowdown or CPU penalty for using (or not using) these features. Even on an 8Mhz ATtiny85 MUL-less “Trinket”. And yes, we’re bragging here.

fantastic work

Bragging is okay. I think it’s deserved! This sounds like a great feature. I can’t wait to play with it. :slight_smile:

Silly answer: We’ve licensed “Elven Magic!” from the Keebler people.

Real answer: we’re doing it in the same general way that we’ve been doing the master brightness control for a year: we know exactly how fast we can send data to the LED strips, and exactly how many (or actually ‘how few’) CPU clock cycles we have between transmitting each individual bit from the CPU to the LED strip. And while we’re transmitting one pixel’s data out the data pin to the LED strip, we’ve interleaved among those operations, bit by bit, all the mathematical transforms and data wrangling needed to fully prepare the NEXT pixel of data. And we’ve got it worked out exactly right so that the next pixel’s data is fully transformed and prepared at pretty much the exact moment that we’ve finished transmitting the first pixel, and it’s time to start transmitting the second pixel (and starting to transform and prepare the data for the third).

We’ve interleaved and pipelined the ‘transform a pixel’ operations and the ‘transmit a pixel’ operations, quite literally at the single-bit level.

Because the CPU can’t transmit the data any faster than the LED strip can accept it, the CPU would ‘normally’ be sitting around doing nothing for a few cycles here and a few cycles there, until the time came to transmit the next bit. We’re already transmitting at the maximum speeds that the (WS2811/WS2812) LED strips can receive; we just figured out how to use the meager and scattered intermediate CPU cycles to do this additional useful work.

The practical upshot is that when you call “show()” it comes back to you as fast as it did before, and it transmits the pixel data to the LED strip as fast as before, but now instead of merely dumping the leds[] buffer out the data pin at the designated data rate, FastLED is now also performing a pretty large number of useful transforms on the pixel data on-the-fly: temporal dithering, color correction, temperature adjustment, and master brightness control. On ARM platforms (Teensy, Arduino Due), FastLED is actually able to perform these pixel stream transforms so fast that the library can drive data into 16 LED strips in parallel, all in the same amount of time that it used to be able to drive just one.

And I have to say here that @Daniel_Garcia 's implementation is nothing short of breathtaking. The fact that we came up with these ideas, and prototyped them, and got them up and running at all is a little mind-bending. But Dan’s made this code, which by all rights should be a trainwreck, into something modular, maintainable, and beautiful.

That is VERY impressive!! So then I take it that Daniel worked for Keebler at some point in his career? :wink:

It’s possible that if we had to name one particular ‘brand’ that’s helped propel FastLED development, it might be not be a brand of cookies.

So I can add a preferred/new setting by simply adding this to the library? And, my RGB led’s order is actually RBG, this can be a bit confusing. I should assume the library is written around the RGB standard? Thanks!
//SMD5050=0xFFA0F0 /* 255, 160, 240 */,
MYSMD5050=0xFFA0FF,

You don’t even need to do that.

Just .setCorrection( CRGB( 255, 160, 240) ), or similar. No need to edit the library, just plug in your adjustment values directly.

Ahh, that’s too easy Mark!

.setCorrection() is simply an e"eyeball" type setting, right? I wonder if I can use the mcd/lumens values that some vendors so graciously provide to do some percentage calculations … Things that make you go ‘Hmmmmm’.

We have code that does exactly that coming in the full v2.1 release. MCDs in, adjustment values out. I’m finding that I often want to tweak the values a bit by hand, but it’s a useful starting point.

I also built a handheld LED color meter that reads out RGB values so that I could just put the probe up against an LED strip and actually measure the color. http://imgur.com/3NRJAH8 But that’s another story for another day…

Yeah, I’ve been known to bring an LED to work and drop it on one of our light meters. The guys don’t appreciate it when I do that. :slight_smile:

Wait, there’s a master brightness control? :slight_smile:

FastLED.setBrightness( 0…255 )

:slight_smile:

Lol, I have *brightness in about a hundred places in my code. Slaps forehead. Of course had I but looked at your excellent documentation…

The library is full of ‘easter eggs’ like this :slight_smile:

Mark what is the link to the new code?

I wonder if there’s a best practice way of scaling brightness where it’s done multiple times due to different input variables?

I’ve been using a float and then multiplying that by 255 at the last stage.

You can setBrightness at any time and it dynamically adjusts the whole led output. It doesn’t modify the leds[] array-- just what’s sent to the led strip.

I gather that. And it’s supremely useful as a simple brightness control. In my code I’ll just call that with a mapped value from a brightness pot. I’m talking about coming up with raw levels in the first place.