cookbook/intermediate/palettes.md
Difficulty Level: ⭐⭐ Intermediate Time to Complete: 40-50 minutes Prerequisites:
You'll Learn:
ColorFromPalette()nblendPaletteTowardPalette()Color palettes allow you to define a set of colors and smoothly blend between them. This is one of the most powerful features in FastLED for creating sophisticated color effects.
FastLED comes with several built-in color palettes ready to use:
#include <FastLED.h>
CRGBPalette16 palette = RainbowColors_p; // Built-in rainbow palette
// Other built-in palettes:
// - PartyColors_p
// - CloudColors_p
// - LavaColors_p
// - OceanColors_p
// - ForestColors_p
// - HeatColors_p
Create your own color palettes to match your specific needs:
// Define colors at specific positions (0-255)
DEFINE_GRADIENT_PALETTE(sunset_gp) {
0, 255, 0, 0, // Red at position 0
128, 255, 128, 0, // Orange at position 128
255, 255, 255, 0 // Yellow at position 255
};
CRGBPalette16 sunsetPalette = sunset_gp;
DEFINE_GRADIENT_PALETTE(ocean_gp) {
0, 0, 0, 128, // Deep blue at start
64, 0, 64, 255, // Medium blue
128, 0, 128, 255, // Cyan
192, 0, 255, 192, // Light cyan
255, 64, 255, 255 // White foam at end
};
CRGBPalette16 oceanPalette = ocean_gp;
// Create palette from specific CRGB colors
CRGBPalette16 myPalette = CRGBPalette16(
CRGB::Red,
CRGB::Orange,
CRGB::Yellow,
CRGB::Green,
CRGB::Blue,
CRGB::Purple,
CRGB::Pink,
CRGB::White
);
The ColorFromPalette() function retrieves colors from a palette with automatic blending:
void paletteEffect() {
static uint8_t paletteIndex = 0;
for (int i = 0; i < NUM_LEDS; i++) {
// Calculate color index for this LED
uint8_t colorIndex = paletteIndex + (i * 4);
// Get color from palette with linear blending
leds[i] = ColorFromPalette(palette, colorIndex, 255, LINEARBLEND);
}
paletteIndex++; // Animate through palette
}
ColorFromPalette(
palette, // The palette to use
index, // Color index (0-255)
brightness, // Brightness (0-255)
blendType // LINEARBLEND or NOBLEND
);
LINEARBLEND: Smooth gradients (recommended)NOBLEND: Discrete color stepsvoid movingPalette() {
static uint8_t startIndex = 0;
startIndex++; // Move through palette over time
for (int i = 0; i < NUM_LEDS; i++) {
uint8_t colorIndex = startIndex + (i * 2);
leds[i] = ColorFromPalette(palette, colorIndex, 255, LINEARBLEND);
}
}
void stretchedPalette() {
for (int i = 0; i < NUM_LEDS; i++) {
// Map LED position to full palette range
uint8_t colorIndex = map(i, 0, NUM_LEDS-1, 0, 255);
leds[i] = ColorFromPalette(palette, colorIndex, 255, LINEARBLEND);
}
}
void palettePulse() {
static uint8_t paletteIndex = 0;
uint8_t brightness = beatsin8(15, 50, 255); // Pulsing brightness
for (int i = 0; i < NUM_LEDS; i++) {
uint8_t colorIndex = paletteIndex + (i * 3);
leds[i] = ColorFromPalette(palette, colorIndex, brightness, LINEARBLEND);
}
paletteIndex++;
}
Smoothly transition between different palettes:
CRGBPalette16 currentPalette;
CRGBPalette16 targetPalette;
void setup() {
currentPalette = RainbowColors_p;
targetPalette = LavaColors_p;
}
void loop() {
// Blend toward target palette
EVERY_N_MILLISECONDS(10) {
nblendPaletteTowardPalette(currentPalette, targetPalette, 12);
}
// Change target palette periodically
EVERY_N_SECONDS(5) {
targetPalette = targetPalette == RainbowColors_p ?
LavaColors_p : RainbowColors_p;
}
// Use current palette
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = ColorFromPalette(currentPalette, i * 4, 255, LINEARBLEND);
}
FastLED.show();
}
void noisyPalette() {
for (int i = 0; i < NUM_LEDS; i++) {
// Use noise to select palette color
uint8_t noise = inoise8(i * 50, millis() / 10);
leds[i] = ColorFromPalette(palette, noise, 255, LINEARBLEND);
}
}
CRGBPalette16 palette1 = RainbowColors_p;
CRGBPalette16 palette2 = LavaColors_p;
void dualPalette() {
for (int i = 0; i < NUM_LEDS; i++) {
// Alternate between palettes
CRGBPalette16 &usePalette = (i % 2) ? palette1 : palette2;
leds[i] = ColorFromPalette(usePalette, i * 8, 255, LINEARBLEND);
}
}
LINEARBLEND for smoother effectsnblendPaletteTowardPalette() for smooth changes#include <FastLED.h>
#define NUM_LEDS 60
#define DATA_PIN 6
CRGB leds[NUM_LEDS];
CRGBPalette16 currentPalette;
CRGBPalette16 targetPalette;
TBlendType currentBlending = LINEARBLEND;
void setup() {
FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(50);
currentPalette = RainbowColors_p;
targetPalette = RainbowColors_p;
}
void loop() {
// Change palette every 5 seconds
EVERY_N_SECONDS(5) {
ChangePalettePeriodically();
}
// Blend toward target palette
EVERY_N_MILLISECONDS(10) {
nblendPaletteTowardPalette(currentPalette, targetPalette, 12);
}
// Animate palette
static uint8_t startIndex = 0;
startIndex++;
FillLEDsFromPaletteColors(startIndex);
FastLED.show();
FastLED.delay(1000 / 60); // 60 FPS
}
void FillLEDsFromPaletteColors(uint8_t colorIndex) {
uint8_t brightness = 255;
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = ColorFromPalette(currentPalette, colorIndex, brightness, currentBlending);
colorIndex += 3;
}
}
void ChangePalettePeriodically() {
uint8_t secondHand = (millis() / 1000) % 60;
static uint8_t lastSecond = 99;
if (lastSecond != secondHand) {
lastSecond = secondHand;
if (secondHand == 0) { targetPalette = RainbowColors_p; }
if (secondHand == 10) { targetPalette = LavaColors_p; }
if (secondHand == 20) { targetPalette = OceanColors_p; }
if (secondHand == 30) { targetPalette = ForestColors_p; }
if (secondHand == 40) { targetPalette = PartyColors_p; }
if (secondHand == 50) { targetPalette = CloudColors_p; }
}
}