Non-linear LED Response Workaround?

Question for the advanced blade style programmers out there:

I want to create an effect that has a pixel LED slowly going from black to orangered to mimic a component slowly getting red hot.

In theory it’s simple enough, but the results aren’t quite as realisic as I’d like.

The issue seems to be that brightness increases are non-linear, so rather than the brightness emerging really slowly, it’s nothing, nothing, nothing, on quite a bit, then on full.
My code is below and I’ve set the duration to 40,000 which is already quite long.

I guess my question is can we build a style that accounts for the non-linearity of the LED? For instance, can we set it to go from Rgb<0,0,0> to Rgb<20,2,0> over 40,000 milliseconds, then Rgb<20,2,0> to Rgb<125,15,0> over 10,000 ms? Is there way of going up in stages like that? And would it work?

Any thoughts welcome.
Here’s the code I’ve been using:

Try the “Metal Forge” Heat Up Ignition Effect in my library under Ignition Options on the Enhancements screen (there’s a corresponding Retraction Effect too).

The problem here isn’t that the LED is nonlinear, because it is. The problem is that it is linear, but human eyes are not. Human eyes have a response that is closer to response = \sqrt[3]{brightness} What this means is that if you increase a black led by a tiny amount, it looks like a big change. If you increase a white led by the same amount, it does not look like a big change.

Because neopixels are linear, and only have 8 bits of precision, the darkest we can make it without turning it off, is 1/255th of it’s maximum brightness. Unfortunately, this still looks fairly bright to the human eye. ProffieOS tries to work around this by doing dithering, which adds some additional levels by rapidly switching the LED between 0 and 1 values, but even that is not enough at very low levels.

There are a couple of ways to possibly get this to work.

  1. Cover up the led with some tape or something, then use higher values. By reducing the maximum brightness in this way, we’re also gaining more precision in absolute brightness.
  2. Use regular LEDs instead of neopixels. The ProffieOS PWM has 32768 levels, which should be enough.
  3. Use dotstar/Apa102 LEDs. These leds have more bits controlling the brightness, leading to much more accuracy in the lower levels. (Not entirely sure how much, because I haven’t tried it.)

To gain more control over the curve and colors, you probably want to use TrConcat<> to concatenate multiple transitions together.

1 Like

Thanks so much guys - legends as always! :+1: :clap: :grinning:
I see what you mean about the nature of LED light completely Prof - makes perfect sense. And for my purposes, as I’ve just learned from breaking down Fernando’s code, Trconcat<> was indeed the answer. I broke it down to four steps, with the first literally just going from zero to Rgb<3,0,0> over 4,000 milliseconds, which worked pretty well. The code is below. :grinning:

I’ll post up a video when I’ve had a chance to shoot one. The way I’ve used it is a really fun effect on this particular hilt.

Many thanks again. In both your debt as always. :grinning:


1 Like

Just been refining this and have gone to an ignition first step/retraction last step of Rgb<2,0,0> over 4000ms. The overall effect looks great and really natural, but when the LED fades out, it just flickers very slightly at the end, presumably because it’s struggling to illuminate with just 1/127th of its rated full power. I actually like how it looks, but it occurred to me to ask, could this cause damage to the LED, or indeed the Proffieboard, over time?

Short answer: no
The flickering probably comes from the dithering, and it’s nothing to worry about.

1 Like