Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Pacifica: gentle, blue-green ocean waves. For Dan.
// "Pacifica"
// Gentle, blue-green ocean waves.
// December 2019, Mark Kriegsman and Mary Corey March.
// For Dan.
#include <FastLED.h>
#define DATA_PIN 13
#define NUM_LEDS 60
#define LED_TYPE WS2812B
void setup() {
delay( 3000); // 3 second delay for boot recovery, and a moment of silence
.setCorrection( TypicalLEDStrip );
FastLED.setMaxPowerInVoltsAndMilliamps( 5, MAX_POWER_MILLIAMPS);
void loop()
// 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,
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
// Deepen the blues and greens a bit
// 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);
Copy link

georgeterbush commented Jan 12, 2020

Hi Mark,

Pacifica is really beautiful and calming. Although you made it to be used under Mary's "Beneath These Waves Lies Light" art, it looks really nice as a straight strip in a tall light box. Thank you.
George TerBush

Copy link

kriegsman commented Jan 14, 2020

Thank you for sharing the video, @georgeterbush. It's beautiful the way you've built it. Although I wrote this code originally for "Beneath These Waves Lies Light", it makes me happy to open-source it so that other people can create their own works with it, too. Thank you again for sharing the video; it's beautiful.

Copy link

solarkennedy commented Mar 28, 2020

I also really appreciate this art and I'm thankful that you open-sourced it.
I wake up to this pattern every morning now with this project:
Thank you :)

Copy link

M1949 commented Apr 30, 2020

Dear Mark Kriegsman, I would like to thank you with all my heart for your Pacifica program. I know that it was an obituary for your friend Daniel Carcia, who died in the tragic accident at the Conception. The program has had yet another effect for me. During the Corona crisis I immediately felt better every evening when the light installation in our house was running. I know that WS2812b does not emit UV light and that there is no scientific justification for protection against viruses. But: as soon as the calming wave blue glowed in the evening, my psyche was completely relaxed, I was not afraid, nothing could disturb me.
Unfortunately, this light effect can hardly be captured with a camera. The automatic brightness correction destroys the real impression.
Once again, many thanks for your work, a truly honorable obituary for the victims of this tragic accident.
Michael Kunert

Copy link

nervusvagus commented Jun 24, 2020

cant decide which is more beautiful; the animation or the code.

Copy link

iketan312 commented Aug 10, 2020

exit status 1
'class CFastLED' has no member named 'setMaxPowerInVoltsAndMilliamps'

Copy link

gitTinker commented Nov 29, 2020

I saw this in the FastLED examples, and didn't know who to thank (until I stumbled on to this page).

THANK YOU! Pacifica is my wife's favorite pattern - she [almost] forgives me for all the $s spent on LED strands :^)

Copy link

SteelyGlint50 commented Apr 11, 2021

Thank you for your generous sharing of well commented code. You make it easier to see how some nigh impenetrable code can be adjusted to different set ups.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment