I just installed my new fastLED based controller (replacing the previous non-wifi feather m0).
I noticed something that is a bit odd. I’m displaying an HSV rainbow - nothing odd there, brightness is steady at about 33% for all the Hues. If I reduce saturation, so tending towards white, the brightness goes up, until at 0 saturation, the LEDs are all full on (255,255,255), and the strip is three times brighter than at 255 saturation.
Is this expected behavior? I thought the brightness would stay constant with varying hue (which it does) and saturation (which it doesn’t).
I can finagle it by varying brightness (level/value) with saturation, but isn’t the HSV model supposed to avoid the need for dealing with these kind of issues? Or am I missing something?
Thanks,
Someone asked for my code- Here it is:
#include “helper_functions.h”
void parse_rainbowCycle() {
//Function to parse global variables for rainbow mode
display_message(“Rainbow Cycle Mode”);
previous_display_mode = display_mode;
display_mode = RAINBOWCYCLE_MODE;
display_blank = false;
mode_from_mqtt = false;
}
void do_rainbowCycle() {
if(mode_from_mqtt) parse_rainbowCycle();
static CEveryNMillis UpdateTime(timing/fps);
static uint8_t hue;
if(UpdateTime) {
uint8_t beat = beatsin8(fps*60, min_brightness,saturation,0,0);
//progression can be SHORTEST_HUES, LONGEST_HUES, FORWARD_HUES, BACKWARD_HUES
fill_gradient(&leds[0], min_led, CHSV(hue,beat,max_brightness), max_led, CHSV(hue+255,beat,max_brightness), FORWARD_HUES);
hue+=hue_increment;
show_leds();
UpdateTime.setPeriod(timing/fps);
}
}
Hmmm… anyone know what code markers work here (if any?)
OK, update: here is my constant brightness with varying hue and saturation code. It is UGLY.
I tried to find a mathematical solution, the closest I can get is this:
uint8_t calc_bri = qadd8((((uint16_t)beat*5)/8),148);
(where beat is saturation). saturation vs brightness seems to be linear, for a fixed hue, but hue vs saturation vs brightness is not. (I did resort to graphing the response by the way).
This works for a fixed hue (in this case 0), but goes out the window as soon as you start varying the hue. The brightness seems to depend on the amount of green in the pixel, so you have to calculate the amount of green for the specific hue, saturation, brightness - and then it’s not particularity linear on the rainbow setting. I couldn’t find a mathematical fit, so I had to go with the brute force method instead - ugh!
void do_rainbowCycle() {
if(mode_from_mqtt) parse_rainbowCycle();
static CEveryNMillis UpdateTime(timing/fps);
static uint8_t hue;
if(UpdateTime) {
uint8_t beat = beatsin8(fps*60, min_brightness,saturation,0,0);
//progression can be SHORTEST_HUES, LONGEST_HUES, FORWARD_HUES, BACKWARD_HUES
uint8_t chv1_brightness = max_brightness;
uint8_t chv2_brightness = max_brightness;
uint8_t target_brightness = max_brightness/3;
CRGB rgb_colour1 = CHSV(hue,beat,chv1_brightness);
CRGB rgb_colour2 = CHSV(hue+255,beat,chv2_brightness);
uint8_t colour1_brightness = qsub8(rgb_colour1.getAverageLight(), target_brightness);
uint8_t colour2_brightness = qsub8(rgb_colour2.getAverageLight(), target_brightness);
while(colour1_brightness > 0) {
chv1_brightness--;
rgb_colour1 = CHSV(hue,beat,chv1_brightness);
colour1_brightness = qsub8(rgb_colour1.getAverageLight(), target_brightness);
}
while(colour2_brightness > 0) {
chv2_brightness--;
rgb_colour2 = CHSV(hue+255,beat,chv2_brightness);
colour2_brightness = qsub8(rgb_colour2.getAverageLight(), target_brightness);
}
fill_gradient(&leds[0], min_led, CHSV(hue,beat,chv1_brightness), max_led, CHSV(hue+255,beat,chv2_brightness), FORWARD_HUES);
hue+=hue_increment;
show_leds();
UpdateTime.setPeriod(timing/fps);
}
}
If anyone can come up with a better method than this please post!