Skip to content

Instantly share code, notes, and snippets.

@yeutterg
Last active January 5, 2018 13:49
Show Gist options
  • Save yeutterg/2909ab05c726c4f8a4ab3f417c720d17 to your computer and use it in GitHub Desktop.
Save yeutterg/2909ab05c726c4f8a4ab3f417c720d17 to your computer and use it in GitHub Desktop.
Arduino Code for the NYC Window Display
// Arduino Code for the 2017 NYC Holiday Window Display
// More info about this project: https://yeutterg.github.io/nyc-display-2017
#include "FastLED.h"
#define BRIGHTNESS 255
#define NUM_LEDS_PER_STRIP 100
#define NUM_STRIPS 4
#define NUM_LEDS NUM_STRIPS * NUM_LEDS_PER_STRIP
#define LED_START_PIN 30
#define UPDATES_PER_SECOND 100
//#define LED_PIN 30
#define SNOW_SPEED 20
//#define SNOW_DELAY 50 // runs between snowfall
CRGB leds[NUM_LEDS];
bool SNOWFALL = true;
// some nice reference colors for the Green Wire WS2811 pixels
CHSV r(0, 255, 255); // red
CHSV o(15, 255, 255); // orange
CHSV y(30, 255, 255); // yellow
CHSV g(92, 255, 255); // green
CHSV t(120, 255, 255); // teal
CHSV b(160, 255, 255); // blue
CHSV p(195, 255, 255); // purple
CHSV k(240, 255, 255); // pink
CRGB c = CRGB::Black; // off
CRGB w = CRGB::White; // cool white
CRGB x = CRGB::LightSalmon; // warm white
CRGBPalette16 palette_off = CRGBPalette16( c,c,c,c, c,c,c,c, c,c,c,c, c,c,c,c);
CRGBPalette16 palette_twinkle = CRGBPalette16( c,c,c,w, c,c,c,c, c,c,c,w, c,c,c,w);
CRGBPalette16 palette_red = CRGBPalette16( r,r,r,r, r,r,r,r, r,r,r,r, r,r,r,w);
CRGBPalette16 palette_orange = CRGBPalette16( o,o,o,o, o,o,o,o, o,o,o,o, o,o,o,w);
CRGBPalette16 palette_yellow = CRGBPalette16( y,y,y,y, y,y,y,y, y,y,y,y, y,y,y,w);
CRGBPalette16 palette_green = CRGBPalette16( g,g,g,g, g,g,g,g, g,g,g,g, g,g,g,w);
CRGBPalette16 palette_blue = CRGBPalette16( b,b,b,b, b,b,b,b, b,b,b,b, b,b,b,w);
CRGBPalette16 palette_teal = CRGBPalette16( t,t,t,t, t,t,t,t, t,t,t,t, t,t,t,w);
CRGBPalette16 palette_purple = CRGBPalette16( p,p,p,p, p,p,p,p, p,p,p,p, p,p,p,w);
CRGBPalette16 palette_pink = CRGBPalette16( k,k,k,k, k,k,k,k, k,k,k,k, k,k,k,w);
//CRGBPalette16 palette_multi = CRGBPalette16( k,y,t,r, b,o,p,w, k,y,t,r, b,o,p,w);
CRGBPalette16 palette_multi = CRGBPalette16(0xFF0000, 0xD52A00, 0xAB5500, 0xAB7F00,
0xABAB00, 0x56D500, 0x00FF00, 0x00D52A,
0x00AB55, 0x0056AA, 0x0000FF, 0x2A00D5,
0x5500AB, 0x7F0081, 0xAB0055, w);
CRGBPalette16 palette_ww = CRGBPalette16( x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,w);
CRGBPalette16 palette_cw = CRGBPalette16( w,w,w,w, w,w,w,w, w,w,w,w, w,w,w,t);
CRGBPalette16 palette_snow = CRGBPalette16( w,w,w,w, w,w,w,w, w,w,w,w, w,w,w,w);
// Start by fading on to rainbow
CRGBPalette16 currentPalette( CRGB::Black);
CRGBPalette16 currentSnowPalette = currentPalette;
//CRGBPalette16 targetPalette( RainbowColors_p );
CRGBPalette16 targetPalette = palette_yellow;
// Vertical map for snowfall effect
int verticalMap[][2] = {
{0, 74},
{75, 149},
{150, 224},
{225, 299},
{300, 374},
{375, 449},
{450, 524},
{525, 599}
};
int numVerticalRows = sizeof(verticalMap)/sizeof(*verticalMap);
byte currentSnowRow = 0;
int currentSnowTimestep = 0;
int currentSnowDelay = 0;
//boolean snowOn = true;
void setup() {
delay(1000); // power-up safety delay
Serial.begin(9600);
// Add all the LED strips
// WS2811_PORTA: 69,68,61,60,59,100,58,31 (note: pin 100 only available on the digix)
// WS2811_PORTB: 90,91,92,93,94,95,96,97 (note: only available on the digix)
// WS2811_PORTD: 25,26,27,28,14,15,29,11
FastLED.addLeds<WS2811_PORTD, NUM_STRIPS, RGB>(leds, NUM_LEDS_PER_STRIP);
// FastLED.addLeds<WS2811_PORTA, 31>(leds, NUM_LEDS_PER_STRIP, NUM_LEDS_PER_STRIP);
// FastLED.addLeds<WS2811_PORTB, 27>(leds, 2*NUM_LEDS_PER_STRIP, NUM_LEDS_PER_STRIP);
// FastLED.addLeds<WS2811, LED_START_PIN+3>(leds, 3*NUM_LEDS_PER_STRIP, NUM_LEDS_PER_STRIP);
// FastLED.addLeds<WS2811, LED_START_PIN+4>(leds, 4*NUM_LEDS_PER_STRIP, NUM_LEDS_PER_STRIP);
// FastLED.addLeds<WS2811, LED_START_PIN+5>(leds, 5*NUM_LEDS_PER_STRIP, NUM_LEDS_PER_STRIP);
// FastLED.addLeds<WS2811, LED_START_PIN+6>(leds, 6*NUM_LEDS_PER_STRIP, NUM_LEDS_PER_STRIP);
// FastLED.addLeds<WS2811, LED_START_PIN+7>(leds, 7*NUM_LEDS_PER_STRIP, NUM_LEDS_PER_STRIP);
FastLED.setBrightness(BRIGHTNESS);
}
void loop() {
uint8_t maxChanges = 24; // Min 1 (slowest), max 48 - speed of palette crossfade
nblendPaletteTowardPalette(currentPalette, targetPalette, maxChanges);
static uint8_t startIndex = 0;
startIndex = startIndex + 1; /* motion speed */
FillLEDsFromPaletteColors(startIndex);
FastLED.show();
FastLED.delay(1000 / UPDATES_PER_SECOND);
if (Serial.available() > 0) {
// read the incoming byte:
char serialChar = Serial.read();
Serial.print(serialChar);
switch(serialChar) {
case 'r':
targetPalette = palette_red;
SNOWFALL = true;
break;
case 'g':
targetPalette = palette_green;
SNOWFALL = true;
break;
case 'b':
targetPalette = palette_blue;
SNOWFALL = true;
break;
case 'y':
targetPalette = palette_yellow;
SNOWFALL = true;
break;
case 'p':
targetPalette = palette_purple;
SNOWFALL = true;
break;
case 'o':
targetPalette = palette_orange;
SNOWFALL = true;
break;
case 'q':
targetPalette = palette_pink;
SNOWFALL = true;
break;
case 't':
targetPalette = palette_teal;
SNOWFALL = true;
break;
case 'm':
targetPalette = palette_multi;
SNOWFALL = true;
break;
case 'w':
targetPalette = palette_cw;
SNOWFALL = true;
break;
case 'x':
targetPalette = palette_ww;
SNOWFALL = true;
break;
case 'c':
targetPalette = palette_off;
SNOWFALL = false;
break;
case 'a':
// TODO random
targetPalette = palette_purple;
SNOWFALL = true;
break;
case 'n':
targetPalette = palette_multi;
SNOWFALL = true;
break;
}
}
}
void rainbowAll(int delayVal) {
for (byte i = 0; i < 255; i++) {
setAllHue(i);
Serial.println(i);
FastLED.delay(delayVal);
}
}
void multiAll() {
for (int i = 0; i < NUM_LEDS; i += 8) {
setColor(i, g);
setColor(i+1, k);
setColor(i+2, y);
setColor(i+3, t);
setColor(i+4, r);
setColor(i+5, b);
setColor(i+6, o);
setColor(i+7, p);
}
FastLED.show();
}
void setAllHue(byte hue) {
for (int i = 0; i < NUM_LEDS; i++) {
setHue(i, hue);
}
FastLED.show();
}
void setHue(int led, byte hue) {
setHSV(led, hue, 255, 255);
}
void setHSV(int led, byte hue, byte sat, byte val) {
if (led < NUM_LEDS) {
leds[led] = CHSV(hue, sat, val);
}
}
void setAllColor(CRGB color) {
for (int i = 0; i < NUM_LEDS; i++) {
setColor(i, color);
}
FastLED.show();
}
void setColor(int led, CRGB color) {
if (led < NUM_LEDS) {
leds[led] = color;
}
}
void setAllColor(CHSV color) {
for (int i = 0; i < NUM_LEDS; i++) {
setColor(i, color);
}
FastLED.show();
}
void setColor(int led, CHSV color) {
if (led < NUM_LEDS) {
leds[led] = color;
}
}
void FillLEDsFromPaletteColors(uint8_t colorIndex) {
uint8_t brightness = 255;
if (!SNOWFALL) {
// Just apply the color palette, no snowfall
for( int i = 0; i < NUM_LEDS; i++) {
CRGB paletteValue = ColorFromPalette(currentPalette, colorIndex + sin8(i*16), brightness);
leds[i] = paletteValue;
}
} else {
// Snowfall overlay
// Note this only works with 1 row right now!
byte rowsFullOn = 1; // 1 row fading on, rowsFullOn full on, 1 row fading off
// Get the current LEDs that should be white
int (&rowFadeOff)[2] = verticalMap[currentSnowRow];
int rowFullOn[2] = {0, 0};
for (int i = 0; i < rowsFullOn; i++) {
int (&thisRow)[2] = verticalMap[(currentSnowRow + i + 1) % numVerticalRows];
if (i == 0) {
// Get initial position
rowFullOn[0] = thisRow[0];
}
if (i == (rowsFullOn - 1)) {
// Get final position
rowFullOn[1] = thisRow[1];
}
}
int (&rowFadeOn)[2] = verticalMap[(currentSnowRow + rowsFullOn + 1) % numVerticalRows];
for( int i = 0; i < NUM_LEDS; i++) {
CRGB paletteValue = ColorFromPalette(currentPalette, colorIndex + sin8(i*16), brightness);
uint8_t snowBlendVal = (float)currentSnowTimestep / (float)SNOW_SPEED * 255;
uint8_t negSnowBlendVal = 255 - snowBlendVal;
CRGB snowValue = ColorFromPalette(palette_snow, colorIndex + sin8(i*16), brightness);
if (i >= rowFadeOn[0] && i <= rowFadeOn[1]) {
leds[i] = nblend(paletteValue, snowValue, snowBlendVal);
} else if (i >= rowFadeOff[0] && i <= rowFadeOff[1]) {
leds[i] = nblend(paletteValue, snowValue, negSnowBlendVal);
} else if (i >= rowFullOn[0] && i <= rowFullOn[1]) {
leds[i] = snowValue;
} else {
leds[i] = paletteValue;
}
colorIndex += 3;
}
// Iterate the timestep
currentSnowTimestep++;
if (currentSnowTimestep > SNOW_SPEED) {
currentSnowTimestep = 0;
// Reset the snow palette
currentSnowPalette = currentPalette;
// Iterate the snow row
currentSnowRow++;
if (currentSnowRow >= numVerticalRows) {
currentSnowRow = 0;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment