Possible to customize fill_rainbow colours or make similar customrainbow array ?

I have read over the Fill Raimbow wiki and it seems that this gives four colours that are blended together to give us a rainbow effect. Am I understanding this correctly?

Is it possible to have more than 4 predetermined colours? Can it be customized ?

Also, in this wiki example, I am not seeing how the rainbow "moves" along a LED strip.

#include <FastLED.h>

#define LED_PIN     6

// Information about the LED strip itself
#define NUM_LEDS    30
#define CHIPSET     WS2812
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];

#define BRIGHTNESS  19


// FastLED v2.1 provides two color-management controls:
//   (1) color correction settings for each LED strip, and
//   (2) master control of the overall output 'color temperature' 
//
// THIS EXAMPLE demonstrates the second, "color temperature" control.
// It shows a simple rainbow animation first with one temperature profile,
// and a few seconds later, with a different temperature profile.
//
// The first pixel of the strip will show the color temperature.
//
// HELPFUL HINTS for "seeing" the effect in this demo:
// * Don't look directly at the LED pixels.  Shine the LEDs aganst
//   a white wall, table, or piece of paper, and look at the reflected light.
//
// * If you watch it for a bit, and then walk away, and then come back 
//   to it, you'll probably be able to "see" whether it's currently using
//   the 'redder' or the 'bluer' temperature profile, even not counting
//   the lowest 'indicator' pixel.
//
//
// FastLED provides these pre-conigured incandescent color profiles:
//     Candle, Tungsten40W, Tungsten100W, Halogen, CarbonArc,
//     HighNoonSun, DirectSunlight, OvercastSky, ClearBlueSky,
// FastLED provides these pre-configured gaseous-light color profiles:
//     WarmFluorescent, StandardFluorescent, CoolWhiteFluorescent,
//     FullSpectrumFluorescent, GrowLightFluorescent, BlackLightFluorescent,
//     MercuryVapor, SodiumVapor, MetalHalide, HighPressureSodium,
// FastLED also provides an "Uncorrected temperature" profile
//    UncorrectedTemperature;

#define TEMPERATURE_1 Candle

#define TEMPERATURE_2 Halogen

// How many seconds to show each temperature before switching
#define DISPLAYTIME 40
// How many seconds to show black between switches
#define BLACKTIME   3

void loop()
{
  // draw a generic, no-name rainbow
  static uint8_t starthue = 0;
  fill_rainbow( leds + 1, NUM_LEDS - 1, --starthue, 20);

  // Choose which 'color temperature' profile to enable.
  uint8_t secs = (millis() / 1000) % (DISPLAYTIME * 2);
  if( secs < DISPLAYTIME) {
    FastLED.setTemperature( TEMPERATURE_1 ); // first temperature
    leds[0] = TEMPERATURE_1; // show indicator pixel
  } else {
    FastLED.setTemperature( TEMPERATURE_2 ); // second temperature
    leds[0] = TEMPERATURE_2; // show indicator pixel
  }

  // Black out the LEDs for a few secnds between color changes
  // to let the eyes and brains adjust
  //if( (secs % DISPLAYTIME) < BLACKTIME) {
  //  memset8( leds, 0, NUM_LEDS * sizeof(CRGB));
  //}
  
  FastLED.show();
  FastLED.delay(8);
}

void setup() {
  delay( 3000 ); // power-up safety delay
  // It's important to set the color correction for your LED strip here,
  // so that colors can be more accurately rendered through the 'temperature' profiles
  FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalSMD5050 );
  FastLED.setBrightness( BRIGHTNESS );
}

If you search the FastLED library, you can find the fill_rainbow function

void fill_rainbow( struct CRGB * pFirstLED, int numToFill,
                  uint8_t initialhue,
                  uint8_t deltahue )
{
    CHSV hsv;
    hsv.hue = initialhue;
    hsv.val = 255;
    hsv.sat = 240;
    for( int i = 0; i < numToFill; i++) {
        pFirstLED[i] = hsv;
        hsv.hue += deltahue;
    }
}

which just loops through the array you pass while incrementing the hue of each pixel. You could easily create your own function that does whatever you want.

Ah I see. I'll work with that example and see how it goes.

With the code above in the 1st post, I don't see how the rainbow moves tho ?

since the varaible 'starthue' is declared as static, it retains its value each time through loop and since it gets decremented each time inside the fill_rainbow() function, the rainbow starts at a different value.

I have no experience with the fill_rainbow function. Are there any other examples?

I was thinking of creating a “rainbow” that would have a section that would be black “off” and then maybe 20% of the length of the rainbow would be yellow.

Or maybe a bit of yellow, some black, then red. Is this possible?

You set the colors in the leds[] array and you call FastLed.show().

The colors are made of values for red, green and blue -- 0 to 255 each for 256x256x256 possible colors.

The FastLed library has enough "features" to take a very long time to learn, most all don't need to be learned to use the library. Really it looks like a bunch of people threw in whatever they liked. Just be happy that the Arduino IDE optimizes the parts you don't use out.

The fill_rainbow function fills a LED strip with colours that gradually fade quite well from one color to another. Is there a way to set custom colours that fade similar to this ? Sure, I can create an array, but not sure its as easy as the rainbow function does it ??

If you want more colors and different behavior than you can get from that function then you need different code.

But maybe the function can do more if there are settings you can change.

The FastLed library has to have a leds[] array to work. The Rainbow function uses the array.

What goes on is that the array is set with 3 bytes per led for level of red, green and blue. Every color (of 16777216 possible) is made of how much red/green/blue it has and every led you give a color.

And then the show() function loads the led strip with those colors to be seen.

Soon after that new colors are loaded and shown, soon being perhaps 33 milliseconds which is fast enough to fool human eyes into seeing motion on TV. In 1 second the colors change 30 times, that rainbow appears to move half the length of a 60 led strip. To the Arduino this is very slow, to human senses it is fast, the basis of a lot of Arduino tricks is fooling humans.

The sketch loads the leds[] array and runs the show function over and over.

Makes total sense with your explanation. Thank you!

I have a bit of coding to come up with for my array!

Q: What do the values for initalhue and deltahue do? or describe?

Also, If I want to have several hundred LEDs in my array, is there a method to call out each led[] number ?
I guess just assign them once and then move them along LED strip as shown in the previous example in post#1.

Using FastLed, every led needs 3 bytes just for that array. Maybe an Uno can run 500 leds without crashing while a Mega2560 can support so many that speed and power would become major issues.

I don't have much to say about hue and saturation (color and brightness) except that they are used to make the 3 bytes of red, green, blue.

is there a method to call out each led[] number ?

The leds[] array is leds[0], leds[1], leds[2],... leds[total-1].

This is an example sketch loaded in your IDE (you don't have to type). File->Examples-> in section 5, Control
https://www.arduino.cc/en/Tutorial/Arrays

The reference page on arrays:

One last thing but when I look at the fill_rainbow function, it seems that it takes the array, and then depending on the numbers that are used in the fill_rainbow function, it stretches out, or compacts the array to fill the defined start and stop led position values.

When I change the value from 20 to something smaller, it fits in the array into just that number of LEDs, so 20 in the above code (post#1). And if I make the number larger, it lengthens out the array to that value of LEDs. Am I understanding this correctly ?
Thanks!!

I guess I’m just trying to still understand how fill_raimbow in the above code actually moves the rainbow down the LED strip.

It gets called with a starting hue that you pass as the 'starthue' value. The increment is passed in as a constant of 20.

The next time through loop(), starthue is one less than the previous value so that new value gets passed into fill_rainbow() with the same constant deltahue of 20. This repeats, over and over.

Shanedm1:
I guess I’m just trying to still understand how fill_raimbow in the above code actually moves the rainbow down the LED strip.

It changes the colors many times a second. The colors on leds 0,1,2,3 in one moment become the colors on leds 1,2,3,4 in the next with a new color on led 0 in the next moment.

Think of movies on film, a strip of separate pictures shown one at a time but at 24 pics/sec or faster we see motion.

The FastLed.show() is the showing of 1 picture. It takes a stream of those to give the impression of motion.

................

One Arduino thing I find that beginners don't appreciate is the speed. Arduino can change 100's of leds and still have to wait even longer for a full 33 milliseconds to pass before showing those changes. When blinking a led or a few leds and watching a button or a few, I have put up examples that run void loop() at over 67 times each millisecond to show fast responses to inputs while maintaining timely outputs. When the changes happen fast enough they appear very smooth.

If a certain array is just 4 different colors (eg: Red, Yellow, black, yellow), but I specify the length as 100, does it then stretch those colors out to 100 LED positions and then do the math to blend / fade them ?

it doesn't do anything. You have to write the code to fade over the 100 leds, similar to the fill_rainbow() function that used a for() loop

What I notice with the fill_rainbow program example is that the strays that are used, such as Candle, Tungsten100W, HighNoonSun, etc) are very long- hundreds of pixels. When I change the value of initalHue and deltaHue it takes that very long array and can make it fit just a few pixels, so almost compressing it.

Are these crested arrays very long? Hundreds of pixels?

Shanedm1:
If a certain array is just 4 different colors (eg: Red, Yellow, black, yellow), but I specify the length as 100, does it then stretch those colors out to 100 LED positions and then do the math to blend / fade them ?

You would write or find a function where each color gets copied to elements of the leds[] array 100/4 times making sure that the last color gets written to any remaining leds (like if 102 instead of 100 leds then the last color gets 2 extra leds).

You can store patterns in the Arduino flash to copy into the leds[] array.

Roll your own code and get the hard fun of trying to figure out how to make an effect.

Fading colors down is a matter of reading the values in leds[elements] and writing back smaller values for red, green and blue since each one is how bright to make the RGB color and less bright is fade. Do the opposite to fade up.

You might want to find out how many 100 microseconds it takes to fill your leds[] array. An Uno has 16 cycles each micro and it takes fewer to put a stored value into an array element. This is why I mentioned before that you fill the leds[] array and then WAIT until it's time to show it -- the wait may take much longer than filling the array. Arduino is very very fast at small things done correctly.