I'm creating a natural light simulation from sunrise > daytime > sunset, and figured out how to use self-made FastLED palettes animating over very long timeframes, a whole day in this case. Below, for practical testing reasons, squeezed into 10 minutes with the sunrise part only. The total duration is divided into 256 intervals, so the strip updates every 2.3 seconds over 10 minutes. Later, the update intervals will lengthen, with the sunrise duration stretched over 3 hours. So far, so good.
But for good realism, I need to introduce the effect of light passing through long grass, shrubs, foliage or clouds. That means that while the palette transitions do their thing, random LEDs have to randomly "shimmer" and very slowly at that, meaning dimming down and up again just about 10%.
In other words, while with every interval all LEDs of the strip receive new colour values from the active palette in skyEffect() and then the result is displayed with FastLED.show() in loop(), a clouds() function somehow needs to modify these colour values, before the "final result" (palette transition of all LEDs in unison + changed brightness of random LEDs randomly) is displayed.
Maybe you or any of the resident effect wizards has an idea how that shimmering effect can be "overlaid"?
Any suggestions very much appreciated!
/**** Skylight */
/* Adafruit Metro Mini, 1m APA102C LED strip */
/* LIBRARIES */
#include "FastLED.h"
/* VARIABLES */
const byte pinData = 3;
const byte pinClock = 4;
const byte ledCount = 144; // Standard number for 1m APA102C LED strip
byte maxBrightness = 128; // Values from 0 - 255, can be changed interactively with a potentiometer
DEFINE_GRADIENT_PALETTE(testPalette) {
0, 255, 0, 0,
128, 0, 255, 0,
255, 0, 0, 255
}; // http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/atmospheric/tn/Sunset_Real.png .index.html
DEFINE_GRADIENT_PALETTE(sunsetSky) {
0, 10, 62, 123,
36, 56, 130, 103,
87, 153, 225, 85,
100, 199, 217, 68,
107, 255, 207, 54,
115, 247, 152, 57,
120, 239, 107, 61,
128, 247, 152, 57,
180, 255, 207, 54,
223, 255, 227, 48,
255, 255, 248, 42
};
DEFINE_GRADIENT_PALETTE(midsummerSky) { // Only this one is used for this 10 minute demo
0, 33, 55, 153,
25, 80, 119, 197,
89, 153, 215, 250,
95, 199, 233, 252,
102, 255, 255, 255,
120, 197, 219, 240,
147, 150, 187, 223,
200, 159, 171, 172,
255, 169, 154, 128
};
DEFINE_GRADIENT_PALETTE(cloudySky) {
0, 152, 164, 155,
30, 139, 152, 140,
64, 126, 141, 128,
92, 80, 95, 82,
107, 46, 59, 47,
114, 74, 88, 71,
123, 110, 124, 102,
196, 46, 58, 39,
255, 11, 18, 8
};
CRGBPalette16 activePalette = midsummerSky;
struct CRGB leds[ledCount];
/* FUNCTIONS ****/
void setup() {
LEDS.addLeds<APA102, pinData, pinClock, BGR>(leds, ledCount); // BGR for APA102C LED strips
LEDS.setCorrection(Candle); // Or Tungsten40W
// LEDS.setCorrection(UncorrectedColor);
} // End of setup
void loop() {
skyEffect();
FastLED.show();
} // End of loop
void skyEffect() {
static const float transitionDuration = 10; // Minutes (10 minutes: one step = 2343.75 milliseconds ~ 2.3 seconds)
static const float interval = ((float)(transitionDuration * 60) / 256) * 1000; // Steps in milliseconds
static uint8_t paletteIndex = 0; // Current gradient palette colour
CRGB colour = ColorFromPalette(activePalette, paletteIndex, maxBrightness, LINEARBLEND); // Or use a built-in palette
fill_solid(leds, ledCount, colour); // Light the whole strip with the colour fetched from the palette
EVERY_N_MILLISECONDS(interval) { // Traverse the palette
if (paletteIndex < 240) { // Don't use 255, see https://github.com/FastLED/FastLED/issues/515#issuecomment-340627525
paletteIndex++;
}
}
} // End of skyEffect