Go Down

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

sharonrlevy


PaulRB

No, it doesn't mean that, we still don't know what's causing it. I could not open the .doc files you attached before, my phone won't open them. I was hoping you would just copy & page the printed hsv values between code tags like David_2018 did before. If we can see the numbers behind the flickering, maybe we can understand the cause. If so, we may have to abandon the blend() function provided by FastLED and re-implement it ourselves.

PaulRB

I may have spotted something that could cause the flickering:
Code: [Select]

void loop()
{
  EVERY_N_MILLISECONDS(blendRate){
    static uint8_t k;
    ...
    ...
    ...
    k++;
  }

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

The call to .show() is not inside the EVERY_N_MILLISECONDS section. Its outside that, in loop() itself, so will get called every repetition of loop(), far more frequently than is needed (most of the times, the leds won't have changed, so it just repeats sending the same data).

Move the .show() line to inside the EVERY_N_MILLISECONDS section like this:
Code: [Select]

void loop()
{
  EVERY_N_MILLISECONDS(blendRate){
    static uint8_t k;
    ...
    ...
    ...
    k++;
    FastLED.show();  // update the display
  }

}

PaulRB

I also tried looking at the hsv values, using serial plotter:

There is a tiny bit of jitter in some of the numbers. I would not have thought it would be noticeable to the eye.

I made these changes to allow me to see the values in serial plotter:
Code: [Select]
    //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);
    Serial.print(colorCurrent.h); Serial.print(" "); Serial.print(colorCurrent.s); Serial.print(" "); Serial.println(colorCurrent.v);

david_2018

PaulRB, have a look at this sketch and see if the results look any better. There is still a bit of noticeable flicker when some of the colors change, but that may in part be the dimness of the LEDs, the RGB values are fairly small.

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  255
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);

const byte number_of_colors = 6;
int current_color_index = 0;

CHSV color_array[number_of_colors] = {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;

enum directions {increase, decrease, constant};
directions hueDirection, satDirection, valDirection;
bool hueZeroCross;
CHSV colorPrevious;


//---------------------------------------------------------------
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);
  adjustHSVinit();
  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);
      adjustHSVinit();

    }


    colorCurrent = blend(colorStart, colorTarget, k, SHORTEST_HUES);
    //adjustHSV();
    fill_solid( leds, NUM_LEDS, adjustHSV(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);
    char buf[60];
    sprintf_P(buf, PSTR("Original H:%3i S:%3i V:%3i    R:%3i G:%3i B:%3i    k:%3i"), colorCurrent.h, colorCurrent.s, colorCurrent.v, leds[1].r, leds[1].g, leds[1].b, k);
    Serial.println(buf);
    CHSV colorTemp = adjustHSV(colorCurrent);
    sprintf_P(buf, PSTR("Adjusted H:%3i S:%3i V:%3i    R:%3i G:%3i B:%3i    k:%3i"), colorTemp.h, colorTemp.s, colorTemp.v, leds[1].r, leds[1].g, leds[1].b, k);
    Serial.println(buf);
    k++;
  }
  FastLED.show();  // update the display
}

void adjustHSVinit() {
  //determine if Saturation will increase, decrease, or remail the same
  colorPrevious = colorCurrent;
  if (colorTarget.s > colorStart.s) {
    satDirection = increase;
  } else if (colorTarget.s < colorStart.s) {
    satDirection = decrease;
  } else {
    satDirection = constant;
  }
  //determine if Value will increase, decrease, or remain the same
  if (colorTarget.v > colorStart.v) {
    valDirection = increase;
  } else if (colorTarget.v < colorStart.v) {
    valDirection = decrease;
  } else {
    valDirection = constant;
  }
  //determine if Hue will increse, decrease, or remain the same
  //  this is a bit more difficult, because Hue will take the shortest path from Start to Target
  //  sometimes crossing from 0>255 or 255>0 to do so
  if (colorTarget.h > colorStart.h) {
    if ((colorTarget.h - colorStart.h) < 128) {
      hueDirection = increase;
      hueZeroCross = false;
    } else {
      hueDirection = decrease;
      hueZeroCross = true;
    }
  } else if (colorTarget.h < colorStart.h) {
    if ((colorStart.h - colorTarget.h) < 128) {
      hueDirection = decrease;
      hueZeroCross = false;
    } else {
      hueDirection = increase;
      hueZeroCross = true;
    }
  } else {
    hueDirection = constant;
  }
}

CHSV adjustHSV(CHSV colorOriginal) {
  CHSV colorCorrected = colorOriginal;

  //the following will only allow the HSV values to change in one direction
  //if the value of any of them temporarily reverts to a previous amount, it is ignored

  //correct value of Hue
  if ((hueDirection == increase) && (colorCorrected.hue < colorPrevious.hue)) {
    //check value to go from 255 to 0 if it is expected to cross 0
    if (!(hueZeroCross && (colorCorrected.hue == 0) && (colorPrevious.hue == 255))) {
      colorCorrected.hue = colorPrevious.hue;
    }
  }
  if ((hueDirection == decrease) && (colorCorrected.hue > colorPrevious.hue)) {
    //allow value to go from 0 to 255 of it is expected to cross 0
    if (!(hueZeroCross && (colorCorrected.hue == 255) && (colorPrevious.hue == 0))) {
      colorCorrected.hue = colorPrevious.hue;
    }
  }
  if ((hueDirection == constant) && (colorCorrected.hue != colorPrevious.hue)) {
    colorCorrected.hue = colorPrevious.hue;
  }
 
  //correct value of Saturation
  if ((satDirection == increase) && (colorCorrected.sat < colorPrevious.sat)) {
    colorCorrected.sat = colorPrevious.sat;
  }
  if ((satDirection == decrease) && (colorCorrected.sat > colorPrevious.sat)) {
    colorCorrected.sat = colorPrevious.sat;
  }
  if ((satDirection == constant) && (colorCorrected.sat != colorPrevious.sat)) {
    colorCorrected.sat = colorPrevious.sat;
  }
 
  //correct value of Value
  if ((valDirection == increase) && (colorCorrected.val < colorPrevious.val)) {
    colorCorrected.val = colorPrevious.val;
  }
  if ((valDirection == decrease) && (colorCorrected.val > colorPrevious.val)) {
    colorCorrected.val = colorPrevious.val;
  }
  if ((valDirection == constant) && (colorCorrected.val != colorPrevious.val)) {
    colorCorrected.val = colorPrevious.val;
  }
  colorPrevious.hue = colorCorrected.hue;
  colorPrevious.sat = colorCorrected.sat;
  colorPrevious.val = colorCorrected.val;
  return colorCorrected;
}

sharonrlevy

@PaulRB, I implemented your code update, and it didn't get rid of the flicker but it seemed to change it, mading it more recognizable as a pattern like - dim, bright, dim, dim, bright. I'm attaching the plotter data and serial data I got. Unfortunately, the lights kept getting stuck at red, unless I took it off the USB power, and then I can't plot the data. (I'm trying to post the serial data but I'm limited to 9000 characters so have to delete most of it)

Code: [Select]
Setup done.

128 90 50
colorCurrent: 128 colorTarget: 100 k: 0
colorCurrent: 128 colorTarget: 100 k: 1
colorCurrent: 128 colorTarget: 100 k: 2
colorCurrent: 128 colorTarget: 100 k: 3
colorCurrent: 128 colorTarget: 100 k: 4
colorCurrent: 128 colorTarget: 100 k: 5
colorCurrent: 128 colorTarget: 100 k: 6
colorCurrent: 128 colorTarget: 100 k: 7
colorCurrent: 128 colorTarget: 100 k: 8
colorCurrent: 127 colorTarget: 100 k: 9
colorCurrent: 127 colorTarget: 100 k: 10
colorCurrent: 127 colorTarget: 100 k: 11
colorCurrent: 127 colorTarget: 100 k: 12
colorCurrent: 127 colorTarget: 100 k: 13
colorCurrent: 127 colorTarget: 100 k: 14
colorCurrent: 127 colorTarget: 100 k: 15
colorCurrent: 127 colorTarget: 100 k: 16
colorCurrent: 127 colorTarget: 100 k: 17
colorCurrent: 126 colorTarget: 100 k: 18
colorCurrent: 126 colorTarget: 100 k: 19
colorCurrent: 126 colorTarget: 100 k: 20
colorCurrent: 126 colorTarget: 100 k: 21
colorCurrent: 126 colorTarget: 100 k: 22
colorCurrent: 126 colorTarget: 100 k: 23
colorCurrent: 126 colorTarget: 100 k: 24
colorCurrent: 126 colorTarget: 100 k: 25
colorCurrent: 126 colorTarget: 100 k: 26
colorCurrent: 125 colorTarget: 100 k: 27
colorCurrent: 125 colorTarget: 100 k: 28
colorCurrent: 125 colorTarget: 100 k: 29
colorCurrent: 125 colorTarget: 100 k: 30
colorCurrent: 125 colorTarget: 100 k: 31
colorCurrent: 125 colorTarget: 100 k: 32
colorCurrent: 125 colorTarget: 100 k: 33
colorCurrent: 125 colorTarget: 100 k: 34
colorCurrent: 125 colorTarget: 100 k: 35
colorCurrent: 124 colorTarget: 100 k: 36
colorCurrent: 124 colorTarget: 100 k: 37
colorCurrent: 124 colorTarget: 100 k: 38
colorCurrent: 124 colorTarget: 100 k: 39
colorCurrent: 124 colorTarget: 100 k: 40
colorCurrent: 124 colorTarget: 100 k: 41
colorCurrent: 124 colorTarget: 100 k: 42
colorCurrent: 124 colorTarget: 100 k: 43
colorCurrent: 124 colorTarget: 100 k: 44
colorCurrent: 123 colorTarget: 100 k: 45
colorCurrent: 123 colorTarget: 100 k: 46
colorCurrent: 123 colorTarget: 100 k: 47
colorCurrent: 123 colorTarget: 100 k: 48
colorCurrent: 123 colorTarget: 100 k: 49
colorCurrent: 123 colorTarget: 100 k: 50
colorCurrent: 123 colorTarget: 100 k: 51
colorCurrent: 123 colorTarget: 100 k: 52
colorCurrent: 123 colorTarget: 100 k: 53
colorCurrent: 122 colorTarget: 100 k: 54
colorCurrent: 122 colorTarget: 100 k: 55
colorCurrent: 122 colorTarget: 100 k: 56
colorCurrent: 122 colorTarget: 100 k: 57
colorCurrent: 122 colorTarget: 100 k: 58
colorCurrent: 122 colorTarget: 100 k: 59
colorCurrent: 122 colorTarget: 100 k: 60
colorCurrent: 122 colorTarget: 100 k: 61
colorCurrent: 122 colorTarget: 100 k: 62
colorCurrent: 121 colorTarget: 100 k: 63
colorCurrent: 121 colorTarget: 100 k: 64
colorCurrent: 121 colorTarget: 100 k: 65
colorCurrent: 121 colorTarget: 100 k: 66
colorCurrent: 121 colorTarget: 100 k: 67
colorCurrent: 121 colorTarget: 100 k: 68
colorCurrent: 121 colorTarget: 100 k: 69
colorCurrent: 121 colorTarget: 100 k: 70
colorCurrent: 121 colorTarget: 100 k: 71
colorCurrent: 121 colorTarget: 100 k: 72
colorCurrent: 120 colorTarget: 100 k: 73
colorCurrent: 120 colorTarget: 100 k: 74
colorCurrent: 120 colorTarget: 100 k: 75
colorCurrent: 120 colorTarget: 100 k: 76
colorCurrent: 120 colorTarget: 100 k: 77
colorCurrent: 120 colorTarget: 100 k: 78
colorCurrent: 120 colorTarget: 100 k: 79
colorCurrent: 120 colorTarget: 100 k: 80
colorCurrent: 120 colorTarget: 100 k: 81
colorCurrent: 119 colorTarget: 100 k: 82
colorCurrent: 119 colorTarget: 100 k: 83
colorCurrent: 119 colorTarget: 100 k: 84
colorCurrent: 119 colorTarget: 100 k: 85
colorCurrent: 119 colorTarget: 100 k: 86
colorCurrent: 119 colorTarget: 100 k: 87
colorCurrent: 119 colorTarget: 100 k: 88
colorCurrent: 119 colorTarget: 100 k: 89
colorCurrent: 119 colorTarget: 100 k: 90
colorCurrent: 118 colorTarget: 100 k: 91
colorCurrent: 118 colorTarget: 100 k: 92
colorCurrent: 118 colorTarget: 100 k: 93
colorCurrent: 118 colorTarget: 100 k: 94
colorCurrent: 118 colorTarget: 100 k: 95
colorCurrent: 118 colorTarget: 100 k: 96
colorCurrent: 118 colorTarget: 100 k: 97
colorCurrent: 118 colorTarget: 100 k: 98
colorCurrent: 118 colorTarget: 100 k: 99
colorCurrent: 117 colorTarget: 100 k: 100
colorCurrent: 117 colorTarget: 100 k: 101
colorCurrent: 117 colorTarget: 100 k: 102
colorCurrent: 117 colorTarget: 100 k: 103
colorCurrent: 117 colorTarget: 100 k: 104
colorCurrent: 117 colorTarget: 100 k: 105
colorCurrent: 117 colorTarget: 100 k: 106
colorCurrent: 117 colorTarget: 100 k: 107
colorCurrent: 117 colorTarget: 100 k: 108
colorCurrent: 116 colorTarget: 100 k: 109
colorCurrent: 116 colorTarget: 100 k: 110
colorCurrent: 116 colorTarget: 100 k: 111
colorCurrent: 116 colorTarget: 100 k: 112
colorCurrent: 116 colorTarget: 100 k: 113
colorCurrent: 116 colorTarget: 100 k: 114
colorCurrent: 116 colorTarget: 100 k: 115
colorCurrent: 116 colorTarget: 100 k: 116
colorCurrent: 116 colorTarget: 100 k: 117
colorCurrent: 115 colorTarget: 100 k: 118
colorCurrent: 115 colorTarget: 100 k: 119
colorCurrent: 115 colorTarget: 100 k: 120
colorCurrent: 115 colorTarget: 100 k: 121
colorCurrent: 115 colorTarget: 100 k: 122
colorCurrent: 115 colorTarget: 100 k: 123
colorCurrent: 115 colorTarget: 100 k: 124
colorCurrent: 115 colorTarget: 100 k: 125
colorCurrent: 115 colorTarget: 100 k: 126
colorCurrent: 114 colorTarget: 100 k: 127
colorCurrent: 114 colorTarget: 100 k: 128
colorCurrent: 114 colorTarget: 100 k: 129
colorCurrent: 114 colorTarget: 100 k: 130
colorCurrent: 114 colorTarget: 100 k: 131
colorCurrent: 114 colorTarget: 100 k: 132
colorCurrent: 114 colorTarget: 100 k: 133
colorCurrent: 114 colorTarget: 100 k: 134
colorCurrent: 114 colorTarget: 100 k: 135
colorCurrent: 114 colorTarget: 100 k: 136
colorCurrent: 113 colorTarget: 100 k: 137
colorCurrent: 113 colorTarget: 100 k: 138
colorCurrent: 113 colorTarget: 100 k: 139
colorCurrent: 113 colorTarget: 100 k: 140
colorCurrent: 113 colorTarget: 100 k: 141
colorCurrent: 113 colorTarget: 100 k: 142
colorCurrent: 113 colorTarget: 100 k: 143
colorCurrent: 113 colorTarget: 100 k: 144
colorCurrent: 113 colorTarget: 100 k: 145
colorCurrent: 112 colorTarget: 100 k: 146
colorCurrent: 112 colorTarget: 100 k: 147
colorCurrent: 112 colorTarget: 100 k: 148
colorCurrent: 112 colorTarget: 100 k: 149
colorCurrent: 112 colorTarget: 100 k: 150
colorCurrent: 112 colorTarget: 100 k: 151
colorCurrent: 112 colorTarget: 100 k: 152
colorCurrent: 112 colorTarget: 100 k: 153
colorCurrent: 112 colorTarget: 100 k: 154
colorCurrent: 111 colorTarget: 100 k: 155
colorCurrent: 111 colorTarget: 100 k: 156
colorCurrent: 111 colorTarget: 100 k: 157
colorCurrent: 111 colorTarget: 100 k: 158
colorCurrent: 111 colorTarget: 100 k: 159
colorCurrent: 111 colorTarget: 100 k: 160
colorCurrent: 111 colorTarget: 100 k: 161
colorCurrent: 111 colorTarget: 100 k: 162
colorCurrent: 111 colorTarget: 100 k: 163
colorCurrent: 110 colorTarget: 100 k: 164
colorCurrent: 110 colorTarget: 100 k: 165
colorCurrent: 110 colorTarget: 100 k: 166
colorCurrent: 110 colorTarget: 100 k: 167
colorCurrent: 110 colorTarget: 100 k: 168
colorCurrent: 110 colorTarget: 100 k: 169
colorCurrent: 110 colorTarget: 100 k: 170
colorCurrent: 110 colorTarget: 100 k: 171
colorCurrent: 110 colorTarget: 100 k: 172
colorCurrent: 109 colorTarget: 100 k: 173
colorCurrent: 109 colorTarget: 100 k: 174
colorCurrent: 109 colorTarget: 100 k: 175
colorCurrent: 109 colorTarget: 100 k: 176
colorCurrent: 109 colorTarget: 100 k: 177
colorCurrent: 109 colorTarget: 100 k: 178
colorCurrent: 109 colorTarget: 100 k: 179
colorCurrent: 109 colorTarget: 100 k: 180
colorCurrent: 109 colorTarget: 100 k: 181


sharonrlevy

@david_2018 that looks way better! It's still a bit halting between the value changes, like new color, new color new color, instead of a smooth flow, but it is no longer flickering. I'm attaching the plotter data. This is a big improvement! Any ideas of a way to continue smoothing the value changes? I tried slowing the blend rate, but that made it even more obvious.


Grumpy_Mike

Quote
Any ideas of a way to continue smoothing the value changes?
I would use floating point variables to do the calculations and only change them into integer values when addressing the hardware.

PaulRB

Quote
the lights kept getting stuck at red, unless I took it off the USB power
You can't really run 60 RGB leds on usb power alone, it's normally limited to 500mA. 60 leds could need as much as 3,600mA if they are all set at max brightness white. So if you are powering the strip by usb power alone, this could be why they all stick at red: the 500mA max is being exceeded and the voltage is dropping to a level where only the red LEDs light.

What you need to do is connect your 5V PSU to the strip only and power just the Arduino with usb. Only the ground wire and the data wire connecting the Arduino to the strip. Then you can monitor the Arduino and have the strip light correctly all through the sequence.

Of course, if you just want to monitor the Arduino, you can disconnect the strip. The Arduino has no way to tell if the strip is connected or not, and will output the same data regardless.

I could not understand the serial plotter screens you posted. What exactly were the different lines the plot? On the one I posted earlier, blue was hue, yellow was sat and red was Val.

Can you try something? Make all the colours in your sequence identical and let it run. Do you see any flickering?

david_2018

Some of the flickering seems to be caused by the conversion from HSV to RGB in FastLED.  Even when doing the calculations for the blend in the sketch to eliminate the jitter in the HSV numbers, the LEDs still produce a bit of flicker, particularly when more than one of the R G or B values change at the same time.

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  255
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);

const byte number_of_colors = 6;
int current_color_index = 0;

CHSV color_array[number_of_colors] = {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;




//---------------------------------------------------------------
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 == colorTarget ) && (k == 0)) {  // 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);
    byte deltaHue = (colorTarget.hue - colorStart.hue);
    byte newHue;
    if (colorTarget.hue > colorStart.hue) {
      if (deltaHue < 128) {
        newHue = (uint32_t)colorStart.hue + (((((uint32_t)colorTarget.hue - (uint32_t)colorStart.hue) * 10 * (uint32_t)k / 255u) + 5) / 10);
      } else {
        newHue = (uint32_t)colorStart.hue - ((((256u - (uint32_t)colorTarget.hue + (uint32_t)colorStart.hue) * 10 * (uint32_t)k / 255u) + 5) / 10);
        //Serial.println(256u -(uint32_t)colorTarget.hue + (uint32_t)colorStart.hue);
      }
    } else if (colorTarget.hue < colorStart.hue) {
      if (deltaHue >127) {
        newHue = (uint32_t)colorStart.hue - (((((uint32_t)colorStart.hue - (uint32_t)colorTarget.hue) * 10 * (uint32_t)k / 255u) + 5) / 10);
      } else {
        newHue = (uint32_t)colorStart.hue + ((((256u - (uint32_t)colorStart.hue + (uint32_t)colorTarget.hue) * 10 * (uint32_t)k / 255u) + 5) / 10);
      }
    } else { //colorStart.hue == colorTarget.hue
      newHue = colorStart.hue;
    }
    byte newSat;
    if (colorTarget.sat > colorStart.sat) {
      newSat = (uint32_t)colorStart.sat + (((((uint32_t)colorTarget.sat - (uint32_t)colorStart.sat) * 10 * (uint32_t)k / 255u) + 5) / 10);
    } else if (colorTarget.sat < colorStart.sat) {
      newSat = (uint32_t)colorStart.sat - (((((uint32_t)colorStart.sat - (uint32_t)colorTarget.sat) * 10 * (uint32_t)k / 255u) + 5) / 10);
    } else { //colorStart.sat == colorTarget.sat
      newSat = colorStart.sat;
    }
    byte newVal;
    if (colorTarget.val > colorStart.val) {
      newVal = (uint32_t)colorStart.val + (((((uint32_t)colorTarget.val - (uint32_t)colorStart.val) * 10 * (uint32_t)k / 255u) + 5) / 10);
    } else if (colorTarget.val < colorStart.val) {
      newVal = (uint32_t)colorStart.val - (((((uint32_t)colorStart.val - (uint32_t)colorTarget.val) * 10 * (uint32_t)k / 255u) + 5) / 10);
    } else { //colorStart.val == colorTarget.val
      newVal = colorStart.val;
    }
    //fill_solid( leds, NUM_LEDS, colorCurrent);
    fill_solid( leds, NUM_LEDS, CHSV(newHue, newSat, newVal));
    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);
    char buf[60];
    //sprintf_P(buf, PSTR("H:%3i S:%3i V:%3i    R:%3i G:%3i B:%3i    k:%3i"), colorCurrent.h, colorCurrent.s, colorCurrent.v, leds[1].r, leds[1].g, leds[1].b, k);
    //sprintf_P(buf, PSTR("H:%3i S:%3i V:%3i    R:%3i G:%3i B:%3i    k:%3i"), newHue, newSat, newVal, leds[1].r, leds[1].g, leds[1].b, k);
    //Serial.println(buf);
    sprintf_P(buf, PSTR("%3i %3i %3i"),newHue, newSat, newVal);
    Serial.println(buf);

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

}

sharonrlevy

@Grumpy_Mike - sorry I don't understand what you mean (I'm a real novice here).

@PaulRB - Oh yes, I normally have it powered by a 5V, but I didn't realize the lights didn't even need to be plugged in for the Plotter to plot. That being said, I have no idea what any of that plotting data is communicating

@david_2018 - I wanted to use HSV so that I could have more control over the Saturation and Value. But if this is creating all of the problems, could this code be converted to RGB mode, and still have a way to modulate brightness?  Also, is there anything new in the code you posted most recently?

And to all of you, I can't thank you enough for the help you are giving me.

sharonrlevy

In response to @PaulRB - if I make all of the H,S,V values the same, there is is no flickering, just a solid color.

If I make all of the values the same but change the color, I get a smooth blend from one color to the next. Well there's a tiny bit of flicker, but not that significant.

I tried the code from @david_2018's most recent post and no difference.

Grumpy_Mike

Quote
sorry I don't understand what you mean (I'm a real novice here)
The way you have it all the calculations are done with integers. This leads to rounding errors because all the incrementing can only be to the closest integer. To get fraction numbers you need to use floating point numbers. We tend to shy away from these with a micro controller because they take a lot longer to do and most of the time they are not what you want.

However here they are what you need.
https://www.arduino.cc/reference/en/language/variables/data-types/int/
 
https://www.arduino.cc/reference/en/language/variables/data-types/float/

PaulRB

I don't think switching to RGB is going to help. After all, that's what FastLED is doing behind the scenes anyway. The LEDs themselves work in RGB, you are working in HSV and FastLED is translating.

I'm still surprised you can even see the flickering at all, except perhaps when the LEDs are at very low brightness. The magnitude of the jitter in the data is one unit, the smallest possible. But that just is in the HSV space. Maybe in the RGB space it is much more significant. That's something to investigate.

PaulRB

Here is the first few seconds of the sequence as hue (blue line), sat (yellow line) and val (red line):



And now here is the same few seconds as red (blue line), green (yellow line) and blue (red line):



(Sorry about the confusing choice of colours, but I don't think serial plotter allows you to take control over them, you are stuck with the ones it has).

So its now clearer to me why you are seeing the flickering. It does look much worse in RGB colourspace.

I'm becoming convinced that Mike is right, the integer maths that FastLED is using to blend colours and to convert between colourspaces is the problem here. There is some jitter in the HSV values, so even if the conversion to RGB was perfect, there would still be some flicker. But it might be acceptably small, is hard to guess.

So there are a couple of options, I think.

1. Raise an issue against FastLED on github and wait/hope the author can fix it.
2. Switch to using RGB objects in FastLED and write or find some HSV-->RGB conversion and colour blending code so that you don't rely on FastLED's blend() and colourspace conversion.

Go Up