Go Down

Topic: FastLED Modified Blend to Target Color - HSV - Flickering between Value changes (Read 1 time) previous topic - next topic

sharonrlevy

Hello,

I am a visual artist, and a total noob at coding. I have a WS2813 strip, with Arudino Uno for the prototype, though I may need a more powerful board for the final large piece.

I am working on a project in which I want to have a controlled fading between specific colors, and after trying out every code I could find from this board and github, and the internet at large, a nice coder helped me to modify this Fade to Color code by @marmilicious:

https://github.com/marmilicious/FastLED_examples/blob/master/blend_to_target_color.ino
(His code fades beautifully, but after the one specified color, it goes into random mode.)


My code is pasted below.
If I keep all of the values (V) consistent-like at 200-then the fading across colors looks great. But the problem is that I also want a change in Values-to go from a dim aqua, up through a series of brighter sunset colors, and then back down to a dim dark blue. But if I try and adjust the Value then I get tons of flickering as the values change. Adjusting the Blend Rate does not seem to effect the smoothness. Any ideas on how to fix this?

Thanks for your help!

Code: [Select]
#include "FastLED.h"
#define DATA_PIN    8
//#define CLK_PIN     13
#define LED_TYPE    WS2813
#define COLOR_ORDER GRB
#define NUM_LEDS    300
#define BRIGHTNESS  200
CRGB leds[NUM_LEDS];

uint8_t blendRate = 40;  // How fast to blend.  Higher is slower.  [milliseconds]


//fill in your Hue, Saturation, Value (HSV) colors below. You can add or subtract additional colors as needed
CHSV color1 = CHSV(128,255,100);
CHSV color2 = CHSV(32,255,200);
CHSV color3 = CHSV(23,255,225);
CHSV color4 = CHSV(224,255,225);
CHSV color5 = CHSV(192,250,200);
CHSV color6 = CHSV(160,255,100);  

//change number of colors below to reflect how many colors you have listed above
int number_of_colors = 6;
int current_color_index = 0;

//adjust he numbers below to reflect how many colors are listed above
CHSV color_array[6] = {color1, color2, color3, color4, color5, color6 };

//adjust color start CHSV and colorTarget CHSV to match colors above
CHSV colorStart = CHSV(128,255,100);  // starting color
CHSV colorTarget = CHSV(160,255,100);  // target color
CHSV colorCurrent = colorStart;


//---------------------------------------------------------------
void setup() {
  Serial.begin(115200);  // Allows serial monitor output (check baud rate)
  delay(3000); // 3 second delay for recovery
  //FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.setBrightness(BRIGHTNESS);
  Serial.println("Setup done. \n");
}


//---------------------------------------------------------------
void loop()
{
  EVERY_N_MILLISECONDS(blendRate){
    static uint8_t k;
    if ( colorCurrent.h == colorTarget.h ) {  // Check if target has been reached
      colorStart = colorCurrent;
      colorTarget = color_array[current_color_index];  // new target to transition toward
      current_color_index += 1;
   if (current_color_index == number_of_colors){
          current_color_index = 0;
      }
      k = 0;  // reset k value
      Serial.print("New colorTarget:\t\t\t"); Serial.println(colorTarget.h);
    }

     colorCurrent = blend(colorStart, colorTarget, k, SHORTEST_HUES);
    fill_solid( leds, NUM_LEDS, colorCurrent );
//    leds[0] = colorTarget;  // optional - set first pixel to always show target color
    Serial.print("colorCurrent:\t"); Serial.print(colorCurrent.h); Serial.print("\t");
    Serial.print("colorTarget:\t"); Serial.print(colorTarget.h);
    Serial.print("\tk: "); Serial.println(k);
    k++;
  }

  FastLED.show();  // update the display
}


david_2018

Have you seen this?
Looks like a similar problem, the HSV value is fluctuating, even when the start and end value are the same.  Start and end HSV both have a V of 100 in this case, but V is fluctuating in the calculations.

Code: [Select]
hue: 128 sat: 255 val: 100
hue: 128 sat: 255 val:  99
hue: 128 sat: 255 val: 100
hue: 128 sat: 255 val:  99
hue: 128 sat: 255 val:  99
hue: 128 sat: 255 val: 100
hue: 128 sat: 255 val:  99
hue: 129 sat: 255 val: 100
hue: 129 sat: 255 val:  99
hue: 129 sat: 255 val:  99
hue: 129 sat: 255 val: 100
hue: 129 sat: 255 val:  99
hue: 129 sat: 255 val: 100
hue: 129 sat: 255 val:  99
hue: 129 sat: 255 val:  99
hue: 130 sat: 255 val: 100
hue: 130 sat: 255 val:  99
hue: 130 sat: 255 val: 100
hue: 130 sat: 255 val:  99
hue: 130 sat: 255 val:  99
hue: 130 sat: 255 val: 100
hue: 130 sat: 255 val:  99
hue: 130 sat: 255 val:  99
hue: 131 sat: 255 val: 100
hue: 131 sat: 255 val:  99
hue: 131 sat: 255 val: 100
hue: 131 sat: 255 val:  99
hue: 131 sat: 255 val:  99
hue: 131 sat: 255 val: 100
hue: 131 sat: 255 val:  99
hue: 131 sat: 255 val: 100
hue: 132 sat: 255 val:  99
hue: 132 sat: 255 val:  99
hue: 132 sat: 255 val: 100
hue: 132 sat: 255 val:  99
hue: 132 sat: 255 val: 100
hue: 132 sat: 255 val:  99
hue: 132 sat: 255 val:  99
hue: 132 sat: 255 val: 100
hue: 133 sat: 255 val:  99
hue: 133 sat: 255 val: 100
hue: 133 sat: 255 val:  99
hue: 133 sat: 255 val:  99
hue: 133 sat: 255 val: 100
hue: 133 sat: 255 val:  99
hue: 133 sat: 255 val:  99
hue: 133 sat: 255 val: 100
hue: 134 sat: 255 val:  99
hue: 134 sat: 255 val: 100
hue: 134 sat: 255 val:  99
hue: 134 sat: 255 val:  99
hue: 134 sat: 255 val: 100
hue: 134 sat: 255 val:  99
hue: 134 sat: 255 val: 100
hue: 134 sat: 255 val:  99
hue: 135 sat: 255 val:  99
hue: 135 sat: 255 val: 100


You can attempt to correcting for the error manually (correction function is at the end of the code):

Code: [Select]

#include "FastLED.h"
#define DATA_PIN    8
//#define CLK_PIN     13
#define LED_TYPE    WS2813
#define COLOR_ORDER GRB
#define NUM_LEDS    300
#define BRIGHTNESS  200
CRGB leds[NUM_LEDS];

uint8_t blendRate = 40;  // How fast to blend.  Higher is slower.  [milliseconds]

//fill in your Hue, Saturation, Value (HSV) colors below. You can add or subtract additional colors as needed
CHSV color1 = CHSV(128, 255, 100);
CHSV color2 = CHSV(32, 255, 200);
CHSV color3 = CHSV(23, 255, 225);
CHSV color4 = CHSV(224, 255, 225);
CHSV color5 = CHSV(192, 250, 200);
CHSV color6 = CHSV(160, 255, 100);

//change number of colors below to reflect how many colors you have listed above
int number_of_colors = 6;
int current_color_index = 0;

//adjust he numbers below to reflect how many colors are listed above
CHSV color_array[6] = {color1, color2, color3, color4, color5, color6 };

//adjust color start CHSV and colorTarget CHSV to match colors above
CHSV colorStart = CHSV(128, 255, 100); // starting color
CHSV colorTarget = CHSV(160, 255, 100); // target color
CHSV colorCurrent = colorStart;

byte previous_val = colorCurrent.val; // previous V from HSV

//---------------------------------------------------------------
void setup() {
  Serial.begin(115200);  // Allows serial monitor output (check baud rate)
  delay(3000); // 3 second delay for recovery
  //FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.setBrightness(BRIGHTNESS);
  Serial.println("Setup done. \n");
}


//---------------------------------------------------------------
void loop() {
  EVERY_N_MILLISECONDS(blendRate) {
    static uint8_t k;
    if ( colorCurrent.h == colorTarget.h ) {  // Check if target has been reached
      colorStart = colorCurrent;
      colorTarget = color_array[current_color_index];  // new target to transition toward
      current_color_index += 1;
      if (current_color_index == number_of_colors) {
        current_color_index = 0;
      }
      k = 0;  // reset k value
      Serial.print("New colorTarget:\t\t\t"); Serial.println(colorTarget.h);
    }

    colorCurrent = blend(colorStart, colorTarget, k, SHORTEST_HUES);
    correctHSV();
    fill_solid( leds, NUM_LEDS, colorCurrent );
    //leds[0] = colorTarget;  // optional - set first pixel to always show target color
    Serial.print("colorCurrent:\t"); Serial.print(colorCurrent.h); Serial.print("\t");
    Serial.print("colorTarget:\t"); Serial.print(colorTarget.h);
    Serial.print("\tk: "); Serial.println(k);
    k++;
  }

  FastLED.show();  // update the display
}

void correctHSV() {
  if (colorStart.val < colorTarget.val) {  //if val is fading upward
    if (colorCurrent.val < previous_val) { //correct for any decrease in val
      colorCurrent.val = previous_val;
    }
  } else if (colorStart.val > colorTarget.val) { // if val is fading downward
    if (colorCurrent.val > previous_val) { // correct for any increase in val
      colorCurrent.val = previous_val;
    }
  } else { // val remains constant
    colorCurrent.val = colorTarget.val;
  }
  previous_val = colorCurrent.val;
}







PaulRB

The OP said:
Quote
But if I try and adjust the Value then I get tons of flickering as the values change.
So it's not a flicker that occurs on what should be a steady Value.

@sharonrlevy, can you post an example of the H, S & Values you see when the flicker occurs, before and after applying david_2018's fix?


sharonrlevy

@david_2018 - thanks, I will try that and report back

@PaulRB - I had seen that post, I wasn't exactly sure how to make use of it, I thought that meant the code itself was debugged so would make the proper adjustment? Can you please explain how I get that readout of the H, S & V?

Grumpy_Mike

Quote
how I get that readout of the H, S & V?
Use the Serial.print function call.

PaulRB

I had seen that post, I wasn't exactly sure how to make use of it, I thought that meant the code itself was debugged so would make the proper adjustment?
You mean the GitHub issue? It's not clear if the fix that was made (2 years ago) fixed all the blend() functions or just the RGB one. The issue was raised against the RGB blend function.

Can you please explain how I get that readout of the H, S & V?
I was hoping that david_2018's code included the lines to print the values, but checking again, it doesn't. Perhaps @david_2018 you could share those with the OP?

david_2018

Can you please explain how I get that readout of the H, S & V?
In you code, colorCurrent.hue, colorCurrent.sat, and colorCurrent.val will give you the values for hue, saturation,  and value.

PaulRB

Use the Serial.print function call.
I think the OP is asking how to access the h, s & v components. I think it's just colorCurrent.h, colorCurrent.s and colorCurrent.v so just use Serial.print() for each of them.

sharonrlevy

@david_2018
Quote
You can attempt to correcting for the error manually (correction function is at the end of the code):
On code below, I got an error code of:
 previous_val = colorCurrent.val;
   ^
exit status 1
'previous_val' was not declared in this scope

Code: [Select]
void correctHSV() {
  if (colorStart.val < colorTarget.val) {  //if val is fading upward
    if (colorCurrent.val < previous_val) { //correct for any decrease in val
      colorCurrent.val = previous_val;
    }
  } else if (colorStart.val > colorTarget.val) { // if val is fading downward
    if (colorCurrent.val > previous_val) { // correct for any increase in val
      colorCurrent.val = previous_val;
    }
  } else { // val remains constant
    colorCurrent.val = colorTarget.val;
  }
  previous_val = colorCurrent.val;
}

david_2018

@david_2018
On code below, I got an error code of:
 previous_val = colorCurrent.val;
   ^
exit status 1
'previous_val' was not declared in this scope


previous_val was declared immediately above void setup () in the code I posted.  Don't think I changed anything else.

sharonrlevy

Code: [Select]
@david_2018, with code posted as you wrote, I get the error report below, with 'previous_val was not declared in this scope' for each instance. I don't understand code enough to make any adjustments to this on my own  :smiley-confuse:




 ^
/Users/Sharon/Documents/Arduino/my sketches/Blend to target color/blendtotargetcolor_SL5/blendtotargetcolor_SL5.ino: In function 'void correctHSV()':
blendtotargetcolor_SL5:84:28: error: 'previous_val' was not declared in this scope
     if (colorCurrent.val < previous_val) { //correct for any decrease in val
                            ^
blendtotargetcolor_SL5:88:28: error: 'previous_val' was not declared in this scope
     if (colorCurrent.val > previous_val) { // correct for any increase in val
                            ^
blendtotargetcolor_SL5:94:3: error: 'previous_val' was not declared in this scope
   previous_val = colorCurrent.val;
   ^
Using library FastLED at version 3.2.5 in folder: /Users/sharon/Documents/Arduino/libraries/FastLED
exit status 1
'previous_val' was not declared in this scope

david_2018

@david_2018
On code below, I got an error code of:
 previous_val = colorCurrent.val;
   ^
exit status 1
'previous_val' was not declared in this scope

Code: [Select]

//adjust color start CHSV and colorTarget CHSV to match colors above
CHSV colorStart = CHSV(128, 255, 100); // starting color
CHSV colorTarget = CHSV(160, 255, 100); // target color
CHSV colorCurrent = colorStart;

byte previous_val = colorCurrent.val; // previous V from HSV  // <<<<<<<< insert this line into your code >>>>>>>>

//---------------------------------------------------------------
void setup() {
  Serial.begin(115200);  // Allows serial monitor output (check baud rate)
  delay(3000); // 3 second delay for recovery
  //FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.setBrightness(BRIGHTNESS);
  Serial.println("Setup done. \n");
}


sharonrlevy

#13
Jul 16, 2019, 01:35 am Last Edit: Jul 16, 2019, 01:40 am by sharonrlevy Reason: Adding correct code
Thanks @david_2018 that got rid of the error codes.
Unfortunately, that new bit of code didn't seem to change the results on how the LEDs look.

I'm attaching the serial print data from before I added that bit of code (blendtotarget 4) and after (that's the blendtotarget 5 version), if that helps...

Pasting in the code again in its entirety

Code: [Select]
#include "FastLED.h"
#define DATA_PIN    7
//#define CLK_PIN     13
#define LED_TYPE    WS2813
#define COLOR_ORDER GRB
#define NUM_LEDS    60
//#define BRIGHTNESS  100
CRGB leds[NUM_LEDS];

uint8_t blendRate = 50;  // How fast to blend.  Higher is slower.  [milliseconds]

CHSV color1 = CHSV(128,90,50);
CHSV color2 = CHSV(64,50,80);
CHSV color3 = CHSV(32,200,190);
CHSV color4 = CHSV(192,200,190);
CHSV color5 = CHSV(160,90,190);
CHSV color6 = CHSV(100,100,80);

int number_of_colors = 6;
int current_color_index = 0;

CHSV color_array[6] = {color1, color2, color3, color4, color5, color6};


//adjust color start CHSV and colorTarget CHSV to match colors above
CHSV colorStart = CHSV(128,90,50);  // starting color
CHSV colorTarget = CHSV(100,100,80);  // target color
CHSV colorCurrent = colorStart;

byte previous_val = colorCurrent.val; // previous V from HSV  // <<<<<<<< insert this line into your code >>>>>>>>

//---------------------------------------------------------------
void setup() {
  Serial.begin(115200);  // Allows serial monitor output (check baud rate)
  delay(3000); // 3 second delay for recovery
  //FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
//FastLED.setBrightness(BRIGHTNESS);
  Serial.println("Setup done. \n");
}


//---------------------------------------------------------------
void loop()
{
  EVERY_N_MILLISECONDS(blendRate){
    static uint8_t k;
    if ( colorCurrent.h == colorTarget.h ) {  // Check if target has been reached
      colorStart = colorCurrent;
      colorTarget = color_array[current_color_index];  // new target to transition toward
      current_color_index += 1;
   if (current_color_index == number_of_colors){
          current_color_index = 0;
      }
      k = 0;  // reset k value
      Serial.print("New colorTarget:\t\t\t"); Serial.println(colorTarget.h);
    }

     colorCurrent = blend(colorStart, colorTarget, k, SHORTEST_HUES);
    fill_solid( leds, NUM_LEDS, colorCurrent );
    leds[0] = colorTarget;  // set first pixel to always show target color
    Serial.print("colorCurrent:\t"); Serial.print(colorCurrent.h); Serial.print("\t");
    Serial.print("colorTarget:\t"); Serial.print(colorTarget.h);
    Serial.print("\tk: "); Serial.println(k);
    k++;
  }

  FastLED.show();  // update the display
}

void correctHSV() {
  if (colorStart.val < colorTarget.val) {  //if val is fading upward
    if (colorCurrent.val < previous_val) { //correct for any decrease in val
      colorCurrent.val = previous_val;
    }
  } else if (colorStart.val > colorTarget.val) { // if val is fading downward
    if (colorCurrent.val > previous_val) { // correct for any increase in val
      colorCurrent.val = previous_val;
    }
  } else { // val remains constant
    colorCurrent.val = colorTarget.val;
  }
  previous_val = colorCurrent.val;
}

david_2018

Just ignore my code, it was only trying to stabilize the value of the HSV, there are fluctuations in the hue and saturation causing a bit of blinking also. 

Go Up