Is there a linear fade (by appearance) function within FastLED? Doing a PWM fade,

Is there a linear fade (by appearance) function within FastLED? Doing a PWM fade, our eyes just don’t perceive the higher values as well as the lower ones, so you end up with somewhat of a curve with a fast ramp up and slow towards the higher values. I have a client right now that’s complaining that the fade in his product (which is simply going from 0 to 255 on each channel), that it isn’t a linear one. Well yeah, mathematically it is, but our eyes don’t see it.

Yes!

dim8_video is a good very fast approximation.

(And the “V” in HSV is automatically corrected this way. )

So I would have to use HSV with that then?

And I have a better approximation coming, too… that still doesn’t require a big lookup table.

No need to use HSV, but if you do use HSV you get this for free.

Try
FastLED.setBrightness( dim8_video( level ) );

I was about to try incorporating this: http://teaching.ericforman.com/how-to-make-led-brightness-linear/

This client is literally just cycling through a red fade, green fade, blue fade, and repeat ad nauseam. But doing a regular ramp up (+5 to the current value) isn’t perceived as that.

Don’t set to the level itself.
Set to dim8_video( level );

Start with RGB(0, 0, 0) and fade each channel up then down, in sequence. I also have to remind myself that this is the client from hell …

Or you can use a big lookup table.
I just don’t like that :slight_smile:

Neither do I. But for what this does, and to get this guy out of my hair, that was the quickest solution I came up with. But, now knowing that there’s a function that takes care of the translation, I’ll use that.

// example red ramp up
for( int level=0; level<256; level++) {
byte red = dim8_video( level );
FastLED.showColor( CRGB( red, 0,0));
delay( 10 );
}

You still might want the table. But it’s worth knowing about the function too.

I’ll see what works best when I get to the office later. I’m in class teaching 6th grade science, and the unit’s at my office. This is another argument for packing some hardware, something small to test with.

Woohoo teaching! Go you!

Solar cars … problem is this state with its afternoon clouds. They’re the bane of my existence!

So I ended up not using dim8_video() - for some reason when I did that, the first couple of steps are very noticeable. Like the first three to four steps. Probably because I’m also delaying by 50ms to slow the whole thing down. So, going back to just incrementing by +5 and passing that to CRGB() worked out to be smoother and by shortening the delay a bit more it didn’t hang around on the upper values for too long. Client’s happy … for now.

How many pixels are we talking here? And what kind?

12 pixels, driven by the old WS2801 chip.

And all 12 pixels the same color at once the whole time?

Ayup. This is what I ended up running:

void loop() {
if (millis() - lastRun > pause) {
val = val + increment; // increment = 5
if (val <= 0) {
val = 0;
col++;
if (col > 2) col = 0;
// pause longer between colors
pause = 250;
} else {
pause = 50;
}
if ((val > 240) || (val <= 0)) {
increment = -increment;
}
switch(col) {
case 0:
LEDS.showColor(CRGB(0, 0, val));
break;
case 1:
LEDS.showColor(CRGB(0, val, 0));
break;
case 2:
LEDS.showColor(CRGB(val, 0, 0));
break;
}
lastRun = millis();
}
}

When I ran that with showCOlor(CRGB(0, 0, dim8_video(val)) instead, the first three-four steps are noticeable.

Now, it’s also possible that it was happening because I was bitbanging pins as opposed to using SPI. I couldn’t test that in the limited amount of time I had to reprogram the units.