# Fastled: fade single leds from color to a target color

Hi all,

I would really like to learn to use the fastled library and have set a goal for a first project. I've been breaking my head over it so far but I think I might have found a possible solution.

It's a pretty long post so thanks for reading in advance :) ... I had to split it up in two post even

First, what do I want to achieve: - I have 20 leds set to a colorset of 2-3 different colors, say red, green, yellow - Every few seconds a number of random leds should fade red to green, green to yellow, yellow to green, within the colorset red/green - Every 30 seconds all leds should fade to colors from a new colorset, say white and blue - Then every few seconds a number of leds should fade from white to blue, blue to white - Repeat

I got this worked out in code and my code does what I want. Except for the fading part. Now the leds just switch to their target color instantly. (see first reply for code)

I found a piece of code by mr. Kriegsman himself that has functions that do the fading trick. (see first reply for code)

I have trouble understanding these and hope someone can help.

Ok, so every led has a current CRGB. The code below seems to check it's current CRGB against the target CRGB. It uses nblendU8TowardU8 to adjust it towards the target by "amount"

``````// Blend one CRGB color toward another CRGB color by a given amount.
// Blending is linear, and done in the RGB color space.
// This function modifies 'cur' in place.
CRGB fadeTowardColor( CRGB& cur, const CRGB& target, uint8_t amount)
{
nblendU8TowardU8( cur.red,   target.red,   amount);
nblendU8TowardU8( cur.green, target.green, amount);
nblendU8TowardU8( cur.blue,  target.blue,  amount);
return cur;
}

// Helper function that blends one uint8_t toward another by a given amount
void nblendU8TowardU8( uint8_t& cur, const uint8_t target, uint8_t amount)
{
if( cur == target) return;

if( cur < target ) {
uint8_t delta = target - cur;
delta = scale8_video( delta, amount);
cur += delta;
} else {
uint8_t delta = cur - target;
delta = scale8_video( delta, amount);
cur -= delta;
}
}
``````

So "CRGB fadeTowardColor" accepts : - the current CRGB - the target CRGB - the amount of adjustment

Also "CRGB fadeTowardColor" directly modifies the CRGB value of a single led, in place, at the actual memory location it is stored (right?).

So now for my actual question: How do I pass the CRGB value of one led to "CRGB fadeTowardColor" so that it is directly adjusted toward the target ?

My code that works as I want it, except for the fading part:

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

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

CRGB leds[NUM_LEDS];

// FRAMES PER SECONDS
int intFramesPerSec = 25;

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

// == Target color
// For each led in the strip a target CRGB color is stored in an array
CRGB arrTargetColor[NUM_LEDS];

// Define some usable/nice colors:
CRGB White = CRGB(240,156,66);
CRGB Red = CRGB(255,0,0);
CRGB Green = CRGB(0,255,0);
CRGB Blue = CRGB(0,0,255);
CRGB Yellow = CRGB(255,110,0);
CRGB Purple = CRGB( 255, 0, 160);
CRGB Lightblue = CRGB( 255, 255, 255);
CRGB Turquiose = CRGB( 0, 255, 255);
CRGB Pink = CRGB( 255, 43, 148);
CRGB Orange = CRGB( 255, 75, 0);

CRGB arrColors[10]=
{
White,       //0
Red,         //1
Green,       //2
Blue,        //3
Yellow,      //4
Purple,      //5
Lightblue,   //6
Turquiose,   //7
Pink,        //8
Orange       //9
};
// 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[3][12] = {
//{0,3,2,0,3,2,0,3,2,0,3,2},    //0 red white blue
//{0,1,2,0,1,2,0,1,2,0,1,2},    //1 red green blue
//{0,3,0,3,0,3,0,3,0,3,0,3},    //2 red white
{2,1,2,1,2,1,2,1,2,1,2,1},    //3 red green
//{0,1,4,0,1,4,0,1,4,0,1,4},    //4 red yellow green
{2,4,2,4,2,4,2,4,2,4,2,4},    //5 yellow green
{3,6,3,6,3,6,3,6,3,6,3,6}     //6 white lightblue
};

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

int intCurrentColorset = 0;

void setup() {

Serial.begin(9600);

delay(3000); // 3 second delay for recovery

// tell FastLED about the LED strip configuration

// set master brightness control
FastLED.setBrightness(BRIGHTNESS);

// Fill arrTargetColor  with a single target color
for(int i = 0; i < NUM_LEDS; i++){
arrTargetColor[i][0] = White.red;
arrTargetColor[i][1] = White.green;
arrTargetColor[i][2] = White.blue;
}

// Set all leds to the current color
for(int i = 0; i < NUM_LEDS; i++){
leds[i].setRGB(arrTargetColor[i].red, arrTargetColor[i].green, arrTargetColor[i].blue);
}

FastLED.show();

} // end setup

void loop(){

FastLED.show();

// Change the target color of some leds
EVERY_N_SECONDS(2){

// Change the target color for a few leds
// 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
for(int led = 0; led <NUM_LEDS; 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];

arrTargetColor[led].red = arrColors[intGetColor].red;
arrTargetColor[led].green = arrColors[intGetColor].green;
arrTargetColor[led].blue = arrColors[intGetColor].blue;
}
// set the leds to the targetcolor
vSetLedColor();
}

EVERY_N_SECONDS(20){
vChangeColorset();
}

FastLED.delay(1000/intFramesPerSec);

}

void vSetLedColor(){

for(int i = 0; i < NUM_LEDS; i++){

leds[i].setRGB(arrTargetColor[i].red, arrTargetColor[i].green, arrTargetColor[i].blue);
}

} // end vSetLedColor

void vChangeColorset(){

intCurrentColorset = random(0,intNumberOfColorsets); //random() excludes the upper limit so ideal to use as array index :)

// Fill the array 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];

arrTargetColor[i][0] = arrColors[intGetColor].red;
arrTargetColor[i][1] = arrColors[intGetColor].green;
arrTargetColor[i][2] = arrColors[intGetColor].blue;
}

}
``````

Complete original code:

``````#include <FastLED.h>

//
// Sample code that includes a function for fading one RGB color toward a target RGB color
// Also includes a function for fading a whole array of pixels toward a given color
//
// Both of these functions _modify_ the existing color, in place.
//
// All fades are done in RGB color space.
//
// Mark Kriegsman
// December 2016

#define NUM_LEDS 50
#define LED_PIN 3
#define LED_TYPE WS2811
#define COLOR_ORDER GRB

CRGB leds[NUM_LEDS];

void setup() {
delay(3000); // sanity delay
}

// Helper function that blends one uint8_t toward another by a given amount
void nblendU8TowardU8( uint8_t& cur, const uint8_t target, uint8_t amount)
{
if( cur == target) return;

if( cur < target ) {
uint8_t delta = target - cur;
delta = scale8_video( delta, amount);
cur += delta;
} else {
uint8_t delta = cur - target;
delta = scale8_video( delta, amount);
cur -= delta;
}
}

// Blend one CRGB color toward another CRGB color by a given amount.
// Blending is linear, and done in the RGB color space.
// This function modifies 'cur' in place.
CRGB fadeTowardColor( CRGB& cur, const CRGB& target, uint8_t amount)
{
nblendU8TowardU8( cur.red,   target.red,   amount);
nblendU8TowardU8( cur.green, target.green, amount);
nblendU8TowardU8( cur.blue,  target.blue,  amount);
return cur;
}

// Fade an entire array of CRGBs toward a given background color by a given amount
// This function modifies the pixel array in place.
{
for( uint16_t i = 0; i < N; i++) {
}
}

void loop()
{
CRGB bgColor( 0, 15, 2); // pine green ?

// fade all existing pixels toward bgColor by "5" (out of 255)

// periodically set random pixel to a random color, to show the fading
EVERY_N_MILLISECONDS( 300 ) {
uint16_t pos = random16( NUM_LEDS);
CRGB color = CHSV( random8(), 255, 255);
leds[ pos ] = color;
}

FastLED.show();
FastLED.delay(10);
}
``````

Before you go too far down this road, you should consider the HSV color model for color-to-color transitions.

FastLED supports HSV.

Well, I'm already too far down this road :) I would like this to work for now, I could realy use a "wow this works" feeling.

But yes, I am reading up on the HSV model. I try to learn as I go along, also if that means choosing the wrong path initially.

Whoohoo, I got it working just like I wanted it to !

So now for my actual question: How do I pass the CRGB value of one led to "CRGB fadeTowardColor" so that it is directly adjusted toward the target ?

"CRGB fadeTowardColor" takes : - the current CRGB which is actually just "leds[ i ]" from the decalred CRGB leds[NUM_LEDS]; - the targe CRGB, from arrTargetColor - a change value 0-255 ``` for(int i = 0; i ``` ``` *// Blend one CRGB color toward another CRGB color by a given amount. // Blending is linear, and done in the RGB color space. // This function modifies 'cur' in place. CRGB fadeTowardColor( CRGB& cur, const CRGB& target, uint8_t amount) {   nblendU8TowardU8( cur.red,  target.red,  amount);   nblendU8TowardU8( cur.green, target.green, amount);   nblendU8TowardU8( cur.blue,  target.blue,  amount);   return cur; }

// Helper function that blends one uint8_t toward another by a given amount void nblendU8TowardU8( uint8_t& cur, const uint8_t target, uint8_t amount) {   if( cur == target) return;     if( cur < target ) {     uint8_t delta = target - cur;     delta = scale8_video( delta, amount);     cur += delta;   } else {     uint8_t delta = cur - target;     delta = scale8_video( delta, amount);     cur -= delta;   } }* ```