Help understanding color blending

Hi all,

I've got a working sketch running 8 one meter strips of DotStars with the FastLED library. The sketch largely does what I want in shifting colors through the strips. What I'm hoping to accomplish is a more gradual gradient in the color change. Right now the color blend from pixel to pixel is rather stark. The green shifts gradually to yellow, but then it sharply turns off in favor of red. I would like to find a way to change that so that it is a slow process that is stretched out over a greater number of pixels.

This line controls the length of each color segment, but not the blend. Ideally I would also be able to make the segment much, much larger. Currently the segment might be around 160 pixels or more. It's a little hard to count with the way I have it laid out. But If I could make the sketch give me one gradient from the first pixel to the last, that would be great.

colorIndex += 1;

I know that the multiplier I'm using in declaring each strip is also affecting the way the color is dispersed. Right now I am moderately happy with what I have, but I assume that would have to change if I could lengthen the color segment.

At the moment I am more concerned with increasing the blend to a more subtle pattern. After searching about on FastLED references, I've not seen a way to edit the blend function. Is it even possible?

Thanks again in advance!

#include "FastLED.h"

#define NUM_STRIPS 8
#define NUM_LEDS_PER_STRIP 60
#define NUM_LEDS NUM_LEDS_PER_STRIP * NUM_STRIPS
#define BRIGHTNESS 64
#define LED_TYPE    APA102 // DotStar chipset
// #define COLOR_ORDER GRB
#define COLOR_ORDER BGR // DotStar color order

CRGB leds[NUM_STRIPS * NUM_LEDS_PER_STRIP];

CRGBPalette32 currentPalette;
TBlendType    currentBlending;

#define UPDATES_PER_SECOND 100

void setup() {

  FastLED.addLeds<DOTSTAR, 30, 40>(leds, 0 * NUM_LEDS_PER_STRIP, NUM_LEDS_PER_STRIP);

  FastLED.addLeds<DOTSTAR, 31, 41>(leds, .25 * NUM_LEDS_PER_STRIP, NUM_LEDS_PER_STRIP);

  FastLED.addLeds<DOTSTAR, 32, 42>(leds, .5 * NUM_LEDS_PER_STRIP, NUM_LEDS_PER_STRIP);
  
  FastLED.addLeds<DOTSTAR, 33, 43>(leds, .75 * NUM_LEDS_PER_STRIP, NUM_LEDS_PER_STRIP); 
  
  FastLED.addLeds<DOTSTAR, 34, 44>(leds, 1 * NUM_LEDS_PER_STRIP, NUM_LEDS_PER_STRIP); 

  FastLED.addLeds<DOTSTAR, 35, 45>(leds, 1.25 * NUM_LEDS_PER_STRIP, NUM_LEDS_PER_STRIP); 
  
  FastLED.addLeds<DOTSTAR, 36, 46>(leds, 1.5 * NUM_LEDS_PER_STRIP, NUM_LEDS_PER_STRIP); 

  FastLED.addLeds<DOTSTAR, 37, 47>(leds, 1.75 * NUM_LEDS_PER_STRIP, NUM_LEDS_PER_STRIP); 


  delay( 3000 ); // power-up safety delay
  FastLED.addLeds<LED_TYPE, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  FastLED.setBrightness(  BRIGHTNESS );
  
  currentPalette = RainbowColors_p;

}

void loop() {


  static uint8_t startIndex = 0;
  startIndex = startIndex + 1; /* motion speed */

  FillLEDsFromPaletteColors( startIndex);

  FastLED.show();
  FastLED.delay(5000 / UPDATES_PER_SECOND);  // Scroll speed in milliseconds
}

void FillLEDsFromPaletteColors( uint8_t colorIndex)
{
  uint8_t brightness = 10;  //preference is 4 but lower than 50 causes noticeable fragmentation
   

  for(int i = 0; i < NUM_LEDS; i++) {  
   leds[i] = ColorFromPalette( currentPalette, colorIndex, brightness, currentBlending);
    colorIndex += 1;  // Color segment size 
  }
}

I see you use brightness of just 10. That's probably your problem. Every led color just has an 8-bit (256 steps) control. By setting the overall brightness to just 10 you effectively limit the sum of all colors to ever go over 10. Which just doesn't leave you with a lot of possible colors/values. Try setting it to 255 and see if it's smoother.

To improve the appearance of colours you can use gamma correction on the numbers to compensate for the log responce to light of the eye.

Going from one colour to another is just like drawing a straight line at any angle on a screen of pixels. That is you have an X increment the amount X will change each step of the way from start to finish. Likewise a Y increment. Depending on the angle one of these increments will be one and the other some fraction less than one. At each step increment the next pixel to draw, or colour to use.

For a colour do this in thee dimensions XYZ only these are your colour components RGB.

Apply gamma correction as the last step after you have calculated the colour number above.

@Grumpy_Mike, that's not an issue if you use FastLed with HSV or pallets :slight_smile:

Alright, I kicked the brightness up to 255. It does seem a bit smoother. The reds still stand out in their transition. I'm beginning to suspect that that is just the nature of the FastLED color blending function.

While reading about gamma correction was interesting, I did not try to implement it due to @septillion's statement.

So if that is the case, is there a way to make the segment size much larger? As the line controlling segment size is inversely related to the size of the integer listed, I'm not sure how to make it larger when it starts with 1.

colorIndex += 1;

Again, thank you both for your input!

septillion:
@Grumpy_Mike, that's not an issue if you use FastLed with HSV or pallets :slight_smile:

What's not an issue, gamma correction or charting a way through three dimensional colour space?

I would beg to differ, both are relevant.

Last, pallets and HSV take care of that in FastLed.

Gamma correction is another topic. Colors in HSV with fastled are pretty fine, brightness control is indeed very linear. But having good brightness control and good color blending is just not possible with 8-bit. Once you start dimming the resolution is a nightmare.

Last, pallets and HSV take care of that in FastLed.

No they don't.
HSV is only one colour space defined here as implemented by the FastLED libiary:-

Blending between two colours produces a different set of colours depending on what colour space you are in.

However you still have three colour components which are interpolated in exactly the way I said in reply #2.

By ignoring one or two colour parameters you are only blending between two colours of the same fixed unchanging parameters. For example with HSV space changing only the H component only produces a set of fully saturated, full brightness colours.
When it comes to fading the colour the FastLED libiary makes no claim to do any gamma correction. Are you saying it does?

Once you start dimming the resolution is a nightmare.

Agreed, but it is possible to get intermediate colours by colour dithering, although this possible to a greater extent using Dot Star type LEDs than Neopixels.

Alright, the documentation for the pallets is horrible :confused: But that does all the color fading between colors of the pallet. Although, now looking at the code, it does so in RGB unfortunately ;/

Grumpy_Mike:
Are you saying it does?

Absolutely not. :slight_smile: I only say the color blend is pretty good across Value (up to the point it craps out because of resolution). But Value itself clearly is linear so no gamma correction whatsoever.