Hi, Can someone explain why the following peace of code does NOT produce 60

Hi,
Can someone explain why the following peace of code does NOT produce 60 evenly lid led’s in terms of brightness?

#include “FastLED.h”
#define NUM_LEDS 60
#define DATA_PIN 10
CRGB leds[NUM_LEDS];

void setup(){
LEDS.addLeds<WS2812B, DATA_PIN, RGB>(leds, NUM_LEDS);
}

void loop (){

//set even led’s
for(int i=0; i<60; i=i+2) leds[i].setHSV(160, 255, 50); //minValue=16

//set odd led’s
for(int j=1; j<60; j=j+2) leds[j].setHue(160);
for(int j=1; j<60; j=j+2) leds[j] %=50; //minValue=2

FastLED.show(); //update ALL led’s
}

The most dim value for the EVEN led’s seems to be 16 and for the ODD led’s a value of 2. The upper limit for both is 255. The fadingcurve is not linear.

Because setHue probably makes the brightness 255 and not 50.

And also because the HSV to RGB conversion will attempt to (roughly) provide a non-linear curve to brightness, whereas the %= is just a straight scale8 of the rgb values. (Well, technically, scale8 video, but for the purposes here, they’re effectively the same thing).

if you changed the led[j] %= 50; to led[j] %= scale8_video(50,50); you’d probably get something that matches up a bit closer. Roughly.

Okay…
Here’s what I got. I came up with this RGB clock. It’s level is controlled by a LDR. It’s analog reading is mapped three times: first 50-200 being the hands(red green, blue), second 50-100 all “remaining” led’s and last 200-0 being an inverted saturation for the same “remaining” led’s. So, during the day the saturation for the remaining 57 led’s is close to zero: they go white. During the night their saturation fades to value 200 and turn blue AND dim as well. Needing to be able so set a saturation level, I have to use the CHSV object. There is no “set.Sat” like there is “set.Hue”.

@Kasper_Kamperman
If setHue controls brightness, what controls hue? This doesn’t make sense to me.
In the above code , hue stays the same throughout and the led’s behave accordingly. It’s the dimming (if I change the values simultaneously) that doesn’t run smooth. Is there a way to control both hue AND saturation in a mathematical way so I can assign a value to both separately? setHue and % do it in a nice way, but setHSV not.

I don’t understand why you can’t use setHSV? You can keep track of hue, saturation and brightness yourself in your Arduino code?

Or you can make a CHSV variable:
CHSV myHSVcolor;
myHSVcolor.hue = 0;
myHSVcolor.saturation = 255;
myHSVcolor.brightness = 255;

Check the wiki for good examples:

What doesn’t run smooth? Maybe you can make a little video to show what’s going on and describe what you expect.

I can use HSV but it doesn’t give the same output as setHue and % combined.
When using HSV, the level “kicks in” at level 16, whereas % does a better job starting at 2 (out of 255). I just made a video showing the difference. Let me see if I can upload it :slight_smile:

Video is shot with code below. I turn a pot from min to max.

#include “FastLED.h”
#define NUM_LEDS 60
#define DATA_PIN 10
CRGB leds[NUM_LEDS];
int brightness;

void setup() {
delay(1000); //safety first!
LEDS.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);}

void loop (){
// brightness through pot
brightness = map((analogRead(A6)), 0, 1023, 0, 255);

//all LED’s to black
for(int i=0; i<60; i=i++) leds[i].setHSV(0, 0, 0);

//all EVEN led’s
for(int i=0; i<60; i=i+2) leds[i].setHSV(161,255,(brightness));

//all ODD led’s
for(int i=1; i<60; i=i+2) leds[i].setHue(161);
for(int i=1; i<60; i=i+2) leds[i]%=(brightness);

FastLED.show(); //update ALL led’s
}

My point is, that if I want to control saturation for any led, I have to use HSV. But specifying hue and % gives much better control, but no saturation control!

%= uses video_scaling (sorry, I always read modulo when I see this, so I struggled a bit to understand this part.
But according to the documentation (https://github.com/FastLED/FastLED/wiki/Pixel-reference) you’ll do this:
leds[i].nscale8_video( 192);

In the HSV2RGB conversion there isn’t any non-lineair curve applied right now (at least in the 2.1 branch) I think. I thought that this would be the case, but it’s not.

Best thing to do is to apply the non-lineair scaling to your brightness by using the dim8_video function.

So:
for(int i=0; i<60; i=i+2) leds[i].setHSV(161,255,dim8_video(brightness));

Okay, I’ll give it a try. BUT this still leaves me with the saturation part. How do I control the sat for a given led while NOT using the setHSV command? I can set the level (%=) for a specific led, I can set the hue (setHue) but not it’s saturation. How so set the saturation for any given led using a single value?

With the setHSV function you can…

But if you want to desaturate RGB colors:
I adapted myself code to change saturation, it’s pretty simple:

red = qadd8(red, saturation);
green = qadd8(green, saturation);
blue = qadd8(blue, saturation);

So it would become:

saturation = dim8_raw(saturation); // this could work nicer, non-lineair curve

leds[i].r = qadd8(leds[i].r, saturation);
leds[i].g = qadd8(leds[i].g, saturation);
leds[i].b = qadd8(leds[i].b, saturation);

qadd8 limits automatically to 255. Check lib8tion.h.

You might want to invert saturation. Because saturation 255 becomes fully white.

Hsv2rgb does do a non-linear curve. (V = scale8(V,V); does a quick approximation of that) - this is why there’s a difference between the two sets of code used.

@Daniel_Garcia @Mark_Kriegsman Ok. I always assumed that scale8 was linear from this explanation in the lib8tion.h : scale8( i, sc) == (i * sc) / 256

If scale8 is indeed non-lineair than this could be the explanation of my problem? https://plus.google.com/100115767703084101160/posts/ceLmqbpxRUG

Right - read the line I posted again - hsv2rgb pre-scales brightness before using it - V=scale8(V,V);

So:

X = scale8(X,V); // linear curve
Y = scale8(Y,scale8(V,V)); // non-linear

The second is what hsv2rgb does.

Hi guys,
I took Kasper’s advice on desaturating colors and it works like charme! Now I have a nice looking curve, can control hue, sat and level in fine detail.
Thanks to Kasper and Daniel!

@Roger_M Glad I could help! Did you use dim8_raw as well?

Daniel, Mark I’m checking the hsv2rgb code. Is the non-lineair scaling only implemented in the default hsv2rgb_rainbow? Because I can’t find it in the hsv2rgb_raw (that was the one I was using and which had some strange behavior after applying a dim_curve to the rgb values).

dim8_raw it is! At least for my application. The clock runs smooth, dims well and all colors look very much alive and balanced. Color is all about math… :wink:

The non linear scaling is only done in rainbow for now.