#define FASTLED_ALLOW_INTERRUPTS 0
#include <FastLED.h>
FASTLED_USING_NAMESPACE
#define DATA_PIN 3
#define NUM_LEDS 64
#define MAX_POWER_MILLIAMPS 500
#define LED_TYPE WS2812B
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];
void setup() {
Serial.begin(9600);
#if defined(FASTLED_VERSION)
Serial.print(F("FastLED Version: "));
Serial.println(FASTLED_VERSION);
#else
Serial.println(F("FastLED Version not defined."));
#endif
delay(3000); // 3 second delay for boot recovery, and a moment of silence
FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS)
.setCorrection(TypicalLEDStrip);
FastLED.setMaxPowerInVoltsAndMilliamps(5, MAX_POWER_MILLIAMPS);
}
void loop() {
EVERY_N_MILLISECONDS( 20) {
pacifica_loop();
FastLED.show();
}
}
///////////////////////////////////////////////////////////////////////////////
//
// The code for this animation is more complicated than other examples, and
// while it is "ready to run", and documented in general, it is probably not
// the best starting point for learning. Nevertheless, it does illustrate some
// useful techniques.
//
///////////////////////////////////////////////////////////////////////////////
//
// In this animation, there are four "layers" of waves of light.
//
// Each layer moves independently, and each is scaled separately.
//
// All four wave layers are added together on top of each other, and then
// another filter is applied that adds "whitecaps" of brightness where the
// waves line up with each other more. Finally, another pass is taken
// over the led array to 'deepen' (dim) the blues and greens.
//
// The speed and scale and motion each layer varies slowly within independent
// hand-chosen ranges, which is why the code has a lot of low-speed 'beatsin8'
// functions with a lot of oddly specific numeric ranges.
//
// These three custom blue-green color palettes were inspired by the colors
// found in the waters off the southern coast of California,
// https://goo.gl/maps/QQgd97jjHesHZVxQ7
//
CRGBPalette16 pacifica_palette_1 = { 0x000507, 0x000409, 0x00030B, 0x00030D,
0x000210, 0x000212, 0x000114, 0x000117,
0x000019, 0x00001C, 0x000026, 0x000031,
0x00003B, 0x000046, 0x14554B, 0x28AA50 };
CRGBPalette16 pacifica_palette_2 = { 0x000507, 0x000409, 0x00030B, 0x00030D,
0x000210, 0x000212, 0x000114, 0x000117,
0x000019, 0x00001C, 0x000026, 0x000031,
0x00003B, 0x000046, 0x0C5F52, 0x19BE5F };
CRGBPalette16 pacifica_palette_3 = { 0x000208, 0x00030E, 0x000514, 0x00061A,
0x000820, 0x000927, 0x000B2D, 0x000C33,
0x000E39, 0x001040, 0x001450, 0x001860,
0x001C70, 0x002080, 0x1040BF, 0x2060FF };
void pacifica_loop() {
// Increment the four "color index start" counters, one for each wave layer.
// Each is incremented at a different speed, and the speeds vary over time.
static uint16_t sCIStart1, sCIStart2, sCIStart3, sCIStart4;
static uint32_t sLastms = 0;
uint32_t ms = GET_MILLIS();
uint32_t deltams = ms - sLastms;
sLastms = ms;
uint16_t speedfactor1 = beatsin16(3, 179, 269);
uint16_t speedfactor2 = beatsin16(4, 179, 269);
uint32_t deltams1 = (deltams * speedfactor1) / 256;
uint32_t deltams2 = (deltams * speedfactor2) / 256;
uint32_t deltams21 = (deltams1 + deltams2) / 2;
sCIStart1 += (deltams1 * beatsin88(1011, 10, 13));
sCIStart2 -= (deltams21 * beatsin88(777, 8, 11));
sCIStart3 -= (deltams1 * beatsin88(501, 5, 7));
sCIStart4 -= (deltams2 * beatsin88(257, 4, 6));
// Clear out the LED array to a dim background blue-green
fill_solid(leds, NUM_LEDS, CRGB(2, 6, 10));
// Render each of four layers, with different scales and speeds, that vary
// over time
pacifica_one_layer(pacifica_palette_1, sCIStart1,
beatsin16(3, 11 * 256, 14 * 256), beatsin8(10, 70, 130),
0 - beat16(301));
pacifica_one_layer(pacifica_palette_2, sCIStart2,
beatsin16(4, 6 * 256, 9 * 256), beatsin8(17, 40, 80),
beat16(401));
pacifica_one_layer(pacifica_palette_3, sCIStart3, 6 * 256,
beatsin8(9, 10, 38), 0 - beat16(503));
pacifica_one_layer(pacifica_palette_3, sCIStart4, 5 * 256,
beatsin8(8, 10, 28), beat16(601));
// Add brighter 'whitecaps' where the waves lines up more
pacifica_add_whitecaps();
// Deepen the blues and greens a bit
pacifica_deepen_colors();
}
// Add one layer of waves into the led array
void pacifica_one_layer(CRGBPalette16 &p, uint16_t cistart, uint16_t wavescale,
uint8_t bri, uint16_t ioff) {
uint16_t ci = cistart;
uint16_t waveangle = ioff;
uint16_t wavescale_half = (wavescale / 2) + 20;
for (uint16_t i = 0; i < NUM_LEDS; i++) {
waveangle += 250;
uint16_t s16 = sin16(waveangle) + 32768;
uint16_t cs = scale16(s16, wavescale_half) + wavescale_half;
ci += cs;
uint16_t sindex16 = sin16(ci) + 32768;
uint8_t sindex8 = scale16(sindex16, 240);
CRGB c = ColorFromPalette(p, sindex8, bri, LINEARBLEND);
leds[i] += c;
}
}
// Add extra 'white' to areas where the four layers of light have lined up
// brightly
void pacifica_add_whitecaps() {
uint8_t basethreshold = beatsin8(9, 55, 65);
uint8_t wave = beat8(7);
for (uint16_t i = 0; i < NUM_LEDS; i++) {
uint8_t threshold = scale8(sin8(wave), 20) + basethreshold;
wave += 7;
uint8_t l = leds[i].getAverageLight();
if (l > threshold) {
uint8_t overage = l - threshold;
uint8_t overage2 = qadd8(overage, overage);
leds[i] += CRGB(overage, overage2, qadd8(overage2, overage2));
}
}
}
// Deepen the blues and greens
void pacifica_deepen_colors() {
for (uint16_t i = 0; i < NUM_LEDS; i++) {
leds[i].blue = scale8(leds[i].blue, 145);
leds[i].green = scale8(leds[i].green, 200);
leds[i] |= CRGB(2, 5, 7);
}
}
FPS: 0
Power: 0.00W
Power: 0.00W