FastLED: The basics from scratch

Hi all,

I really would like to understand and use the fastled library. I love led's, colors and effects.

However, I have basic programming skills, at this point I lack the skills to really get into this. I've been at this for a week or two and progress is slow. I fee llike I'm constantly trying to re-invent the wheel. All the tutorials and code I find assume a certain level which I haven't reached yet.

I do have a basic understanding of the concept though and managed to program: first project: fading colors with colorsets

However, the first reply mentions the use of the CHSV instead of CRGB. And yes, CHSV seems to be much more useful than CRGB when fading from>to colors and adjusting brightness.

So.... I would like to start this thread and make it sort of an archive with beginner questions that I or any other beginners might encounter. Each question/challenge I face will be a topic that I will link to in this opening post.

FastLED: The basics for beginners Topics: 1. CRGB vs CHSV colors

1. CRGB vs CHSV colors

[u]Challenge: Set my leds to white using CHSV.[/u]

In my first project fading colors with colorsets I used CRGB colors. CHSV is however much more suitable so I'm curious how to use it properly.

Basics CRGB: Red, Green, Bleu, make a color. Nice but not convenient because R, G and B will all have to be changed when changing color (three variables need to be changed). Fading one single color from zero to max brightness, forget it.

Basics CHSV: Ok, this is nice ! Heu, saturation, value :)

|500x302

Hue: the color (0-255) Saturation: from pale(0) to max intensity/full color (255) Value: brightness, very useful to fade in/out [u]one[/u] single color (0=off/black, 255=max)

I started out with a test sketch using potmeters and CHSV but I could not get a nice white. Then i looked into color correction in fastled and found this : Color correction-temperature

I wrote a test sketch with potmeters (see below). Setting LEDColorCorrection in fastled didn't do anything significant. So I tested all predefined color temperatures.

  • Only Candle 0xFF9329 got me close to white, but still a bit to greenish
  • So I tried to reduce green 0x.. GG .. ( in FastLED.setTemperature(); )
  • By trail and error the value 0x FF 70 29 in FastLED.setTemperature(0xFF7029); got me a nice white

Using this color correction and playing around with the potmeters for H/S/V was a valuable trail :)

Conclusion: Using the CHSV is much more intuitive and code-friendly than using the CRGB color space.

#include 
#include 

#define LED_PIN     2
//#define CLOCK_PIN 4 
#define NUM_LEDS    1
#define LED_TYPE    WS2812
#define COLOR_ORDER GRB
#define BRIGHTNESS  255

#define pinHue A0
#define pinSat A1
#define pinVal A2


CRGB leds[NUM_LEDS];



void setup() {
    Serial.begin(9600);
    
    delay(3000);
    LEDS.addLeds(leds, NUM_LEDS);
    //FastLED.setTemperature(Candle);
    FastLED.setTemperature(0xFF7029);
    //Candle 0xFF9329 seems OK
    //Tungsten40W 0xFFC58F way to blue
    //Tungsten100W 0xFFD6AA way to blue
    //Halogen 0xFFF1E0 way to blue
    //CarbonArc 0xFFFAF4 way to blue
    //HighNoonSun 0xFFFFFB way to blue
    //DirectSunlight 0xFFFFFF way to blue
    // OvercastSky 0xC9E2FF way to blue
    //ClearBlueSky 0x409CFF way to blue
    // WarmFluorescent 0xFFF4E5 way to blue
    // StandardFluorescent 0xF4FFFA way to blue
    // MercuryVapor 0xD8F7FF way to blue
    //SodiumVapor 0xFFD1B2 way to blue
    // MetalHalide 0xF2FCFF way to blue
    // HighPressureSodium 0xFFB74C better but a a bit greenish blue 
    // UncorrectedTemperature 0xFFFFFF  way to blue
    // Custom 0xFF8029 getting there but still a bit greenish > reduced green(?) in Candle 0xFF9329 : Candle 0x FF 93 29 > Candle 0x FF 80 29
    // Custom 0xFF6029 nice white with a very slight pink touch
    // Custom 0xFF5029 getting more pink, no good
    // Custom 0xFF7029 Yup, looks like a nice white for my leds !
    FastLED.setBrightness(BRIGHTNESS);

    pinMode(pinHue, INPUT);
    pinMode(pinSat, INPUT);
    pinMode(pinVal, INPUT);
}

void loop()
{
  byte byteHue = map(analogRead(pinHue), 0, 1023, 0, 255);
  byte byteSat = map(analogRead(pinSat), 0, 1023, 0, 255);
  byte byteVal = map(analogRead(pinVal), 0, 1023, 0, 255);

  Serial << byteHue << "  " <<  byteSat << "  " << byteVal << endl;
  
  CHSV color = CHSV(byteHue, byteSat, byteVal);

  fill_solid(leds, NUM_LEDS, color);
  
  FastLED.show();
   
}

Ok, so I'm working on my first project, fading.

Instead of fading from color to color I'm trying to: - fade a led to black - change the color - fade it up to full brightness again

Fading to black, ok, I use: leds*.fadeToBlackBy( 15 );* But fading back to full brightness ? Can it be done by changing the value ? I have been looking for a way to adjust only the V in Hue/Sat/Val, is there a way ? something like leds*.value-- ?*

Using FastLED often times takes some digging as the “documentation” is disjointed at best. Look in the folder where the library is installed for file “pixeltypes.h”. In there you will find the definition of the CHSV structure. Note the union at the beginning:

/// Representation of an HSV pixel (hue, saturation, value (aka brightness)).
struct CHSV {
    union {
 struct {
    union {
        uint8_t hue;
        uint8_t h; };
    union {
        uint8_t saturation;
        uint8_t sat;
        uint8_t s; };
    union {
        uint8_t value;
        uint8_t val;
        uint8_t v; };
 };
 uint8_t raw[3];
 };

    /// default values are UNITIALIZED
    inline CHSV() __attribute__((always_inline))
    {
    }

    /// allow construction from H, S, V
    inline CHSV( uint8_t ih, uint8_t is, uint8_t iv) __attribute__((always_inline))
        : h(ih), s(is), v(iv)
    {
    }

    /// allow copy construction
    inline CHSV(const CHSV& rhs) __attribute__((always_inline))
    {
        h = rhs.h;
        s = rhs.s;
        v = rhs.v;
    }

    inline CHSV& operator= (const CHSV& rhs) __attribute__((always_inline))
    {
        h = rhs.h;
        s = rhs.s;
        v = rhs.v;
        return *this;
    }

    inline CHSV& setHSV(uint8_t ih, uint8_t is, uint8_t iv) __attribute__((always_inline))
    {
        h = ih;
        s = is;
        v = iv;
        return *this;
    }
};

Also, have you looked here: https://github.com/FastLED/FastLED/wiki/Pixel-reference ?

EDIT: sorry I only saw your second reply when I wrote this post.
But what you quote from “pixeltypes.h”, that’s way beyond my skills to make something of :frowning:

Yes I did look there but just went over it again.

So if I understand correctly after reading this:

Automatic Color Conversion

The library provides fast, efficient methods for converting a CHSV color into a CRGB color. Many of these are automatic and require no explicit code.

For example, to set an led to a color specified in HSV, you can simply assign a CHSV color to a CRGB color:

  // Set color from Hue, Saturation, and Value.  
  // Conversion to RGB is automatic.
  leds[i] = CHSV( 160, 255, 255);

  // alternate syntax
  leds[i].setHSV( 160, 255, 255);

  // set color to a pure, bright, fully saturated, hue
  leds[i].setHue( 160);

There is no conversion back from CRGB to CHSV provided with the library at this point.

When you use for example leds*.setHue(160);*
- fastled translates that to a CRGB assuming 255 for S and V
- fastled writes that CRGB to leds[]
- once it is in CRGB it cannot be converted back to CHSV
The thing is I only want to increment or decrement V of a led.
Reading the above it seems not possible ? Because it is impossible to get the current V from an CRGB ?
What I can think of now is :
- an array of CHSV objects, one for each led
- write the CHSV objects to leds[] each time the main loop runs
```
*CRGB leds[NUM_LEDS];
CHSV arrCHSV[NUM_LEDS];

in setup:

// Fill arrCHSV  with a single color
 for(int i = 0; i < NUM_LEDS; i++){
   arrCHSV[i]= CHSV( 160, 255, 255);
 }

in the loop:

for(int i = 0; i < NUM_LEDS; i++){
   leds[i] = arrCHSV[i];
 }*
```
This way I can access and modify for example arrCHSV[ i].val
I did some quick tests and this seems to work. However I have this feeling I’m trying to re-invent the wheel here. Fastled does have some interesting color utility functions and my guess is that one or a combination of those might do what I want.
The function documentation is really limited, only an explanation for void fill_gradient :frowning:
Where can I find more info on all of those color utility functions ?
Thanks !

Yes, that's what I would do -- keep a "shadow array" of CHSV objects that you'd then copy to the main CRGB array when you need to update the physical LEDs. But, you don't necessarily need to do this copy every time though the loop() function. Only when you're about to call FastLED.show().

If you control the timing of your program with delay() statements, it will probably be every time though loop. But, I'd highly recommend you learn now how to use millis() based timing instead. Otherwise, your code will be blocking and as soon as you try to do something more advanced you're going to be stuck.

See: Arduino IDE -- File --> Examples --> 02.Digital --> BlickWithoutDelay Using millis() for timing. A beginners guide Demonstration code for several things at the same time

BTW, the FastLED library does have an hsv2rgb() conversion function, but I understand its approximate and expensive in terms of processor cycles. So, I'd avoid it.

One could also define their custom colors for later use:

#define ORANGE_1 CHSV(30,156,185)
#define ORANGE_2 0xFFA500
#define ORANGE_3 CRGB(255,165,0)
//etc ...

void setup(){
}


void loop(){
}

Yes, I am aware of the disadvantages of using delay(); I started programming for PIC micros back in 2003 in assembly, to use RGB leds ;)

The only delay I intend to use is FastLED.delay() in the main loop to control the framerate.

As for the arrays, I'm introducing a third array arrTargetCHSV[NUM_LEDS]

So :

CRGB leds[NUM_LEDS];
// Will be the array that is written to the leds when calling FastLED.show();

arrCurrentCHSV[NUM_LEDS];
// Holds all CHSV that are to be written to the leds each time the loop runs
for(int i = 0; i < NUM_LEDS; i++){
    leds[i] = arrCurrentCHSV[i];
}

CHSV arrTargetCHSV[NUM_LEDS];
// Holds all the target CHSV 
// Different functions/voids will change the target values

mrExplore: The only delay I intend to use is FastLED.delay() in the main loop to control the framerate.

FastLED.delay() is still blocking. So, any other resources in your project (buttons/switches, sensors, etc) will not be serviced during the delay. If you try to switch patterns or displays on the fly, your controls will be non-responsive. The source code of FastLED.delay() is in FastLED.cpp:

void CFastLED::delay(unsigned long ms) {
 unsigned long start = millis();
        do {
#ifndef FASTLED_ACCURATE_CLOCK
 // make sure to allow at least one ms to pass to ensure the clock moves
 // forward
 ::delay(1);
#endif
 show();
 yield();
 }
 while((millis()-start) < ms);
}

Here's the Doxygen entry: http://fastled.io/docs/3.1/class_c_fast_l_e_d.html#a6819ff831058a710d4582dfc09817202

Well, it looks like I won't be using any delays, because my code seems to be to slow :confused:

So I have :

// Array of leds
CRGB leds[NUM_LEDS];

// Array of CHSV objects that can be manipulated
// The CHSV values are written to the leds each loop
CHSV arrCurrentCHSV[NUM_LEDS];

// Array of target values
// This is used to fade colors and brightness
CHSV arrTargetCHSV[NUM_LEDS];

The main loop:

void loop(){
  
  // Place all CHSV object into the led array
  for(int i = 0; i < NUM_LEDS; i++){
    leds[i] = arrCurrentCHSV[i];
  }
  
  FastLED.show();


  EVERY_N_SECONDS(6){
      vChangeColorset();
  }

  vFade(); 

}

Now: vChangeColorset(); will place new target CHSV's into arrTargetCHSV vFade(); adjusts every CHSV in arrCurrentCHSV toward the corresponding target value in arrTargetCHSV

void vFade(){

  //Serial << "val: " << arrCurrentCHSV[0].val << endl;
  //Serial << "start: " << millis() << endl;
  // Every time vFade is called arrCurrentCHSV values wil be in-/decremented towards the CHSV values in arrTargetCHSV
  CHSV cur;
  CHSV tar;
  for(int i = 0; i < NUM_LEDS; i++){

    cur = arrCurrentCHSV[i];
    tar = arrTargetCHSV[i];

    // Hue
    if(cur.hue < tar.hue && cur.hue < 255){       // if the hue is smaller than the target AND is not 255: increment the hue
      arrCurrentCHSV[i].hue++;
    }
    if(cur.hue > tar.hue && cur.hue > 0){       //
      arrCurrentCHSV[i].hue--;      
    }

    // Saturartion
    if(cur.sat < tar.sat && cur.sat < 255){
      arrCurrentCHSV[i].sat++;
    }
    if(cur.sat > tar.sat && cur.sat > 0){
      arrCurrentCHSV[i].sat--;      
    }

    // Value
    if(cur.val < tar.val && cur.val < 255){
      arrCurrentCHSV[i].val++;
    }
    if(cur.val > tar.val && cur.val > 0){
      arrCurrentCHSV[i].val--;      
    }
    
  } //end for
  //Serial << "end: " << millis() << endl;
  
} //end vFade

This code is actually to slow...

You could say, make the in-/decrements larger by using: arrCurrentCHSV*.hue += 10;* But the problem would be overflow I think ? hue/sat/val are uint_8t so say: > arrCurrentCHSV*.hue is currently 250* > arrCurrentCHSV*.hue += 10;* > the uint8_t would overflow to a value of 5: 250+10 would be 260 but overflow to 260-255 > there would be no way to tell if overflow occurred and vFade() would happily start incrementing hue from 5 I'm thinking of using upper and lower limits, so instead of 0 and 255 I'd use 15 and 240. Then I could use in-/decrements of up to 15 But I have a feeling I'm making it more complex than it could be. So id anyone has a better suggestion, please :) Thanks

First, is your code all contained within a single .ino file? If so, please post it that way. A COMPLETE sketch (including global variable definitions and setup() / loop() functions) is much easier to copy into the Arduino IDE to compile and modify. I don’t have time to stitch together the disparate snippets that you’ve posted and then try to figure out what else is needed to make it compile.

Second, you can take advantage of the uint8_t overflow and transition seamlessly from a hue value of (say) 250 to a hue value of 5. The HSV color space is continuous across that transition (i.e. hue=255 and hue=0 are pretty much the same color of Red). To do this, just figure out how many steps you need to take to go from current hue to the target hue. Then increment (or decrement) the hue that many times without worrying about its absolute value.

Thanks for your input and help gfvalvo, much appreciated.

To your last post:

  • I'll post the complete (working) code I have below ...in my next reply because of the bloody 9000 character limit.

  • I understand the advantage in overflow when using the hue. But when adjusting the value (brightness), overflowing from 255 to 10 would mean "turning the led off". I used a safe offset from 0 and 255 with upper and lower limits in the sketch below. Keeping the in-/decrement amount within the offset works.

However:

  • I still feel like I'm re-inventing the wheel. the FastLED library probably has some functions that could make achieving my goals much more easier and efficient than writing 200+ lines of code. But it's not well documented/explained and in tutorials there seems to be a gap between the bloody obvious and the way too advanced :(

For example: my fade from red to green has a very visible blue/purple in between. What I would like to find out is if there might be a funtions like these: Fade(led*, from current color, to target color, fadetime)* or: Fade(all leds, from current color, to black, fadetime) or: Fade(all leds, from black, to target colors, fadetime) - I just received a pretty urgent work assignment I have to focus on. I will have to put my efforts on fastled on hold :( But now, without further ado, here is my (not perfect) working code: See next reply...

///////////////////////////////////////////////////////////////////////////////////////////////////
//
//  This sketch is a test in fading between colors and fading brightness
//  It uses the CHSV colorspace.
//
//  - To be able to manipulate CHSV values an array is of CHSV objects is used.
//  - The array has a CHSV object for each led
//  - Every time the loop runs each led is set to the CHSV in the array of CHSV objects
//    CRGB leds[NUM_LEDS] is a CRGB arrray
//    The CHSV's from the CHSV array are "translated" to CRGB by the library when using leds[i] = arrCurrentCHSV[i];

//  A seperate CHSV array is used because, once a CHSV value is written to a led, the CHSV is converted to CRGB
//  After that, it is not possible to get the separate H/S/V value from a led and that makes adjusting the 
//  color and brightness just pretty plain impossible.
 

#include <FastLED.h>
#include <Streaming.h>
#include <Math.h>

// SETTINGS FOR LEDS
#define DATA_PIN    2
#define LED_TYPE    WS2812
#define COLOR_ORDER GRB
#define NUM_LEDS    26
#define BRIGHTNESS  255


// ARRAYS ==========================================================================

// Array of leds
CRGB leds[NUM_LEDS];

// Array of CHSV objects that can be manipulated
// The CHSV values are written to the leds each loop
CHSV arrCurrentCHSV[NUM_LEDS];

// Array of target values
// This is used to fade colors and brightness
CHSV arrTargetCHSV[NUM_LEDS];

// An array of hue values that produce colors that can be used in effects
// saturation and value are always at 255 when showing a color
CHSV arrColors[8]=
{
  CHSV( 255, 0, 255),     //0 White - white is a special case, saturation has to be set to 0
  CHSV( 255, 255, 255),   //1 Red
  CHSV( 100, 255, 255),   //2 Green
  CHSV( 160, 255, 255),   //3 Blue
  CHSV( 50, 255, 255),    //4 Yellow
  CHSV( 175, 255, 255),   //5 Purple
  CHSV( 200, 255, 255),   //6 Pink
  CHSV( 30, 255, 255)     //7 Orange
};
// Determine the number of colors in the array
int intLengtharrColors = sizeof(arrColors) / sizeof(arrColors[0]);

// An array in which each row is a colorset
// eacht row must have the same number of entries
// 12 is chosen so that color sets of 2, 3, 4 and 6 can be used
// while keeping the chance of random selection even
int arrColorsets[7][12] = {
  {0,3,1,0,3,1,0,3,1,0,3,1},    //0 red white blue
  {3,1,2,3,1,2,3,1,2,3,1,2},    //1 red green blue
  {0,1,0,1,0,1,0,1,0,1,0,1},    //2 red white
  {2,1,2,1,2,1,2,1,2,1,2,1},    //3 red green
  {2,1,4,2,1,4,2,1,4,2,1,4},    //4 red yellow green
  {2,4,2,4,2,4,2,4,2,4,2,4},    //5 yellow green
  {3,5,3,5,3,5,3,5,3,5,3,5}     //6 blue purple
};

// Determine the number of elements/colorsets
int intNumberOfColorsets = sizeof(arrColorsets) / sizeof(arrColorsets[0]);

int intCurrentColorset = 0;

// Parameters for fading value (brightness)
uint8_t intValUpperLimit = 250;
uint8_t intValLowerLimit = 40;
uint8_t intValAdjustment = 2;       // This should not be greater than the offset of <intValUpperLimit to 255>  or offset <intValLowerLimit to 0?


void setup() {

  Serial.begin(9600);
  
  delay(3000); // 3 second delay for recovery
  
  // tell FastLED about the LED strip configuration
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS);
  FastLED.setTemperature(0xFF7029);
  
  // set master brightness control
  FastLED.setBrightness(BRIGHTNESS);

  // Fill arrCurrentCHSV and arrTargetCHSV with a single color
  for(int i = 0; i < NUM_LEDS; i++){
    arrCurrentCHSV[i]= CHSV( 160, 255, 255);
    arrTargetCHSV[i]= CHSV( 160, 255, 255);
  }
  
} // end setup

void loop(){

  // vFade in-/decrements all values in arrCurrentCHSV towards arrTargetCHSV
  vFade();
  
  // Place all CHSV objects from arrCurrentCHSV into the led array
  // NOTE: memcpy is faster but cannot be used because arrCurrentCHSV elements have to be converted to CRGB 
  for(int i = 0; i < NUM_LEDS; i++){
    leds[i] = arrCurrentCHSV[i];
  }
  
  FastLED.show();

  // Change the target color for a few leds
  // Option 1: since there are only 2-3 colors in a color set, the chance that the new target is the current color is high, therefor all leds will get a new target
  // Option 2: change a smaller number of leds and make the change interval smaller or random between for example 500-1000 milliseconds

 int intNumberOfLedsToChange = NUM_LEDS;
 int intChangeInterval = random(1000,4000);
     
  EVERY_N_MILLISECONDS(intChangeInterval){
       
     for(int led = 0; led <= intNumberOfLedsToChange; led++){
      
        int intTargetLed = random(0, NUM_LEDS);
 
        // generate a random int to select a color from one row in array arrColorsets
        int intGetRandomColorFromSet = random(0,12);

        int intGetColor = arrColorsets[intCurrentColorset][intGetRandomColorFromSet];

        // Place the CHSV color into arrTargetCHSV[i]
        arrTargetCHSV[intTargetLed] = arrColors[intGetColor];
     }  //end for
  } //end every

  EVERY_N_SECONDS(30){
      vChangeColorset();
  }

} //end loop


void vFade(){

  //Serial << "val: " << arrCurrentCHSV[0].val << endl;
  //Serial << "start: " << millis() << endl;
  // Every time vFade is called arrCurrentCHSV values wil be in-/decremented towards the CHSV values in arrTargetCHSV
  CHSV cur;
  CHSV tar;
  for(int i = 0; i < NUM_LEDS; i++){

    cur = arrCurrentCHSV[i];
    tar = arrTargetCHSV[i];

    // Hue
    if(cur.hue < tar.hue && cur.hue < 255){       // if the hue is smaller than the target AND is not 255: increment the hue
      arrCurrentCHSV[i].hue++;
    }
    if(cur.hue > tar.hue && cur.hue > 0){       
      arrCurrentCHSV[i].hue--;      
    }

    // Saturartion
    if(cur.sat < tar.sat && cur.sat < 255){
      arrCurrentCHSV[i].sat++;
    }
    if(cur.sat > tar.sat && cur.sat > 0){
      arrCurrentCHSV[i].sat--;      
    }

    // Value
    if(cur.val < tar.val && cur.val < intValUpperLimit){
      arrCurrentCHSV[i].val += intValAdjustment;
    }
    if(cur.val > tar.val && cur.val > intValLowerLimit){
      arrCurrentCHSV[i].val -= intValAdjustment;      
    }
    
  } //end for
  //Serial << "end: " << millis() << endl;
  
} //end vFade


void vChangeColorset(){

  // When the colorset is to be changed:
  // - ALL leds will fade to black
  // - When all leds are black: 
  //   New colors for the leds are set in arrCurrentCHSV AND arrTargetCHSV
  //   Setting a new target includes setting V (brightness) to 255, fading from black to the new target is handled by vFade

  // Fading to black ==============================================================================

  //a boolean that indicates wether all leds are black
  bool bAllBlack = false;
  //as long as not all leds are black yet:
  while(bAllBlack == false){

    //first set bAllBlack to true
    bAllBlack = true;
    
    //check all leds, if there is only one led that is NOT black, bAllBlack is set to false
    for(int i = 0; i < NUM_LEDS; i++){
      if(arrCurrentCHSV[i].val > intValLowerLimit){
        bAllBlack = false;
      }
    }
  
    for(int i = 0; i < NUM_LEDS; i++){
      if(arrCurrentCHSV[i].val > intValLowerLimit){
        //decrease the brightness
        arrCurrentCHSV[i].val-= intValAdjustment;
        // place CHSV into leds[] for display
        leds[i] = arrCurrentCHSV[i];
      }
    }
    
    FastLED.show();

  } //end while

  // Selecting new colors from a colorset ========================================================

  // To ensure the random selection of a colorset different from the current:
  int intPreviousColorset = intCurrentColorset;
  // as long as the randomly chosen set is the same as the previous, pick a new one
  while(intCurrentColorset == intPreviousColorset){
    intCurrentColorset = random(0,intNumberOfColorsets); //random() excludes the upper limit so ideal to use as array index :)
  }
  

  // Fill arrCurrentCHSV and arrTargetCHSV with new target colors
  for(int i = 0; i < NUM_LEDS; i++){

    //Random number that gets a color in one row of arrColorsets
    int intGetRandomColorFromSet = random(0,12);
    // intGetColor is picked out of the current set and used to retreive the color from arrColors
    int intGetColor = arrColorsets[intCurrentColorset][intGetRandomColorFromSet];

    // Set the new color in arrCurrent
    arrCurrentCHSV[i] = arrColors[intGetColor];
    // Set value to zero(black) because the leds have to fade in again from 0 to 255
    arrCurrentCHSV[i].val = 0;
    // Set the new color in arrTarget
    arrTargetCHSV[i] = arrColors[intGetColor];
    // Set the target brightness V to max
    arrTargetCHSV[i].val = 255;
  } //end for
  
} //end vChangeColorset

What I would like to find out is if there might be a funtions like these: Fade(led, from current color, to target color, fadetime) or: Fade(all leds, from current color, to black, fadetime) or: Fade(all leds, from black, to target colors, fadetime)

You have the source code of the library and whilst this is not as good as full documentation you can see what functions are available and even add more or modify existing ones if you need to.