Skip to content

Instantly share code, notes, and snippets.

@samuelclay
Last active February 15, 2024 16:07
Show Gist options
  • Save samuelclay/8276775 to your computer and use it in GitHub Desktop.
Save samuelclay/8276775 to your computer and use it in GitHub Desktop.
For New Year's Eve 2014, my girlfriend and I went to a dance party where wearable electronics were not only encouraged but also on display from a variety of hobbyists. I decided to use this as an opportunity to combine two of my favorite hobbies: sewing and electronics. We attached six addressable LED strands from Sparkfun ($20 each) to the lini…
#include <Adafruit_NeoPixel.h>
#include "WS2812_Definitions.h"
#define PIN_A 9
#define PIN_B 3
#define PIN_C 2
#define PIN_D 12
#define PIN_E 10
#define PIN_F 6
#define LED_COUNT 43
#define STRIP_COUNT 5
unsigned long COLORS[] = {
NAVY, DARKBLUE, MEDIUMBLUE, BLUE, DARKGREEN, GREEN, TEAL, DARKCYAN,
DEEPSKYBLUE, DARKTURQUOISE, MEDIUMSPRINGGREEN, LIME, SPRINGGREEN,
AQUA, CYAN, MIDNIGHTBLUE, DODGERBLUE, LIGHTSEAGREEN, FORESTGREEN,
SEAGREEN, DARKSLATEGRAY, LIMEGREEN, MEDIUMSEAGREEN, TURQUOISE,
ROYALBLUE, STEELBLUE, DARKSLATEBLUE, MEDIUMTURQUOISE, INDIGO,
DARKOLIVEGREEN, CADETBLUE, CORNFLOWERBLUE, MEDIUMAQUAMARINE, DIMGRAY,
SLATEBLUE, OLIVEDRAB, SLATEGRAY, LIGHTSLATEGRAY, MEDIUMSLATEBLUE,
LAWNGREEN, CHARTREUSE, AQUAMARINE, MAROON, PURPLE, OLIVE, GRAY,
SKYBLUE, LIGHTSKYBLUE, BLUEVIOLET, DARKRED, DARKMAGENTA, SADDLEBROWN,
DARKSEAGREEN, LIGHTGREEN, MEDIUMPURPLE, DARKVIOLET, PALEGREEN,
DARKORCHID, YELLOWGREEN, SIENNA, BROWN, DARKGRAY, LIGHTBLUE,
GREENYELLOW, PALETURQUOISE, LIGHTSTEELBLUE, POWDERBLUE, FIREBRICK,
DARKGOLDENROD, MEDIUMORCHID, ROSYBROWN, DARKKHAKI, SILVER,
MEDIUMVIOLETRED, INDIANRED, PERU, CHOCOLATE, TAN, LIGHTGRAY,
THISTLE, ORCHID, GOLDENROD, PALEVIOLETRED, CRIMSON, GAINSBORO, PLUM,
BURLYWOOD, LIGHTCYAN, LAVENDER, DARKSALMON, VIOLET, PALEGOLDENROD,
LIGHTCORAL, KHAKI, ALICEBLUE, HONEYDEW, AZURE, SANDYBROWN, WHEAT,
BEIGE, WHITESMOKE, MINTCREAM, GHOSTWHITE, SALMON, ANTIQUEWHITE,
LINEN, LIGHTGOLDENRODYELLOW, OLDLACE, RED, FUCHSIA, MAGENTA,
DEEPPINK, ORANGERED, TOMATO, HOTPINK, CORAL, DARKORANGE, LIGHTSALMON,
ORANGE, LIGHTPINK, PINK, GOLD, PEACHPUFF, NAVAJOWHITE, MOCCASIN,
BISQUE, MISTYROSE, BLANCHEDALMOND, PAPAYAWHIP, LAVENDERBLUSH, SEASHELL,
CORNSILK, LEMONCHIFFON, FLORALWHITE, SNOW, YELLOW, LIGHTYELLOW, IVORY
};
Adafruit_NeoPixel led_a = Adafruit_NeoPixel(LED_COUNT, PIN_A, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel led_b = Adafruit_NeoPixel(LED_COUNT, PIN_B, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel led_c = Adafruit_NeoPixel(LED_COUNT, PIN_C, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel led_d = Adafruit_NeoPixel(LED_COUNT, PIN_D, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel led_e = Adafruit_NeoPixel(LED_COUNT, PIN_E, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel led_f = Adafruit_NeoPixel(LED_COUNT, PIN_F, NEO_GRB + NEO_KHZ800);
void setup() {
// To ensure that the first random color in `loop` is never the same.
randomSeed(analogRead(0));
led_a.begin();
led_b.begin();
led_c.begin();
led_d.begin();
led_e.begin();
led_f.begin();
clearLEDs(true);
}
void loop() {
for (int i=0; i<2; i++) {
hulahoop(randomColor(), random(20,60));
}
sparkle(randomColor(), random(30,70));
raindrops(randomColor(), random(20,60));
spiral(randomColor(), random(15,30));
}
void hulahoop(unsigned long color, byte wait) {
// weight determines how much lighter the outer "eye" colors are
const byte weight = 18;
// It'll be easier to decrement each of these colors individually
// so we'll split them out of the 24-bit color value
byte red = (color & 0xFF0000) >> 16;
byte green = (color & 0x00FF00) >> 8;
byte blue = (color & 0x0000FF);
// Start at closest LED, and move to the outside
for (int i=0; i<=LED_COUNT-1; i++) {
clearLEDs(false);
led_a.setPixelColor(i, red, green, blue);
led_b.setPixelColor(i, red, green, blue);
led_c.setPixelColor(i, red, green, blue);
led_d.setPixelColor(i, red, green, blue);
led_e.setPixelColor(i, red, green, blue);
led_f.setPixelColor(i, red, green, blue);
// Now set two eyes to each side to get progressively dimmer
for (int j=1; j<3; j++) {
byte redWJ = red/(weight*j);
byte greenWJ = green/(weight*j);
byte blueWJ = blue/(weight*j);
if (i-j >= 0) {
led_a.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
led_b.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
led_c.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
led_d.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
led_e.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
led_f.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
}
if (i-j <= LED_COUNT) {
led_a.setPixelColor(i+j, redWJ, greenWJ, blueWJ);
led_b.setPixelColor(i+j, redWJ, greenWJ, blueWJ);
led_c.setPixelColor(i+j, redWJ, greenWJ, blueWJ);
led_d.setPixelColor(i+j, redWJ, greenWJ, blueWJ);
led_e.setPixelColor(i+j, redWJ, greenWJ, blueWJ);
led_f.setPixelColor(i+j, redWJ, greenWJ, blueWJ);
}
}
led_a.show();
led_b.show();
led_c.show();
led_d.show();
led_e.show();
led_f.show();
delay(wait);
}
// Now we go back to where we came. Do the same thing.
for (int i=LED_COUNT-2; i>=1; i--) {
clearLEDs(false);
led_a.setPixelColor(i, red, green, blue);
led_b.setPixelColor(i, red, green, blue);
led_c.setPixelColor(i, red, green, blue);
led_d.setPixelColor(i, red, green, blue);
led_e.setPixelColor(i, red, green, blue);
led_f.setPixelColor(i, red, green, blue);
// Now set two eyes to each side to get progressively dimmer
for (int j=1; j<3; j++)
{
byte redWJ = red/(weight*j);
byte greenWJ = green/(weight*j);
byte blueWJ = blue/(weight*j);
if (i-j >= 0) {
led_a.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
led_b.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
led_c.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
led_d.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
led_e.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
led_f.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
}
if (i-j <= LED_COUNT) {
led_a.setPixelColor(i+j, redWJ, greenWJ, blueWJ);
led_b.setPixelColor(i+j, redWJ, greenWJ, blueWJ);
led_c.setPixelColor(i+j, redWJ, greenWJ, blueWJ);
led_d.setPixelColor(i+j, redWJ, greenWJ, blueWJ);
led_e.setPixelColor(i+j, redWJ, greenWJ, blueWJ);
led_f.setPixelColor(i+j, redWJ, greenWJ, blueWJ);
}
}
led_a.show();
led_b.show();
led_c.show();
led_d.show();
led_e.show();
led_f.show();
delay(wait);
}
}
void sparkle(unsigned long color, uint8_t wait) {
for (int i=0; i < LED_COUNT * STRIP_COUNT; i++) {
clearLEDs(true);
int strip = floor(random(STRIP_COUNT));
int led = floor(random(LED_COUNT));
switch (strip) {
case 0:
led_a.setPixelColor(led, color);
led_a.show();
break;
case 1:
led_b.setPixelColor(led, color);
led_b.show();
break;
case 2:
led_c.setPixelColor(led, color);
led_c.show();
break;
case 3:
led_d.setPixelColor(led, color);
led_d.show();
break;
case 4:
led_e.setPixelColor(led, color);
led_e.show();
break;
case 5:
led_f.setPixelColor(led, color);
led_f.show();
break;
}
delay(wait);
}
}
void raindrops(unsigned long color, byte wait) {
// weight determines how much lighter the outer "eye" colors are
const byte weight = 18;
// It'll be easier to decrement each of these colors individually
// so we'll split them out of the 24-bit color value
byte red = (color & 0xFF0000) >> 16;
byte green = (color & 0x00FF00) >> 8;
byte blue = (color & 0x0000FF);
double sludge = 0.5;
double a_offset = 0;
double b_offset = 3;
double c_offset = 1;
double d_offset = 2;
double e_offset = 4;
double f_offset = 5;
// Start at closest LED, and move to the outside
for (int i=0; i<LED_COUNT*(STRIP_COUNT-1)*sludge+LED_COUNT*10; i++) {
clearLEDs(false);
double n = i % (int)(LED_COUNT*(STRIP_COUNT+1)*sludge-LED_COUNT*sludge);
double led_count = (double)LED_COUNT;
bool a_on = (sludge*a_offset*led_count) <= n &&
n <= (sludge*a_offset*led_count+led_count);
bool b_on = (sludge*b_offset*led_count) <= n &&
n <= (sludge*b_offset*led_count+led_count);
bool c_on = (sludge*c_offset*led_count) <= n &&
n <= (sludge*c_offset*led_count+led_count);
bool d_on = (sludge*d_offset*led_count) <= n &&
n <= (sludge*d_offset*led_count+led_count);
bool e_on = (sludge*e_offset*led_count) <= n &&
n <= (sludge*e_offset*led_count+led_count);
bool e_alt= (sludge*a_offset*led_count) <= n &&
n <= (sludge*a_offset*led_count+led_count*sludge);
bool f_on = (sludge*f_offset*led_count) <= n &&
n <= (sludge*f_offset*led_count+led_count);
if (!a_on && !b_on && !c_on && !d_on && !e_on && !f_on) {
clearLEDs(true);
break;
}
int a = n-a_offset*LED_COUNT*sludge;
int b = n-b_offset*LED_COUNT*sludge;
int c = n-c_offset*LED_COUNT*sludge;
int d = n-d_offset*LED_COUNT*sludge;
int e = n-e_offset*LED_COUNT*sludge;
if (e_alt) {
e = a+(LED_COUNT/2);
}
int f = n-f_offset*LED_COUNT*sludge;
if (a_on) led_a.setPixelColor(a, red, green, blue);
if (b_on) led_b.setPixelColor(b, red, green, blue);
if (c_on) led_c.setPixelColor(c, red, green, blue);
if (d_on) led_d.setPixelColor(d, red, green, blue);
if (e_on || e_alt) led_e.setPixelColor(e, red, green, blue);
if (f_on) led_f.setPixelColor(f, red, green, blue);
// Now set two eyes to each side to get progressively dimmer
for (int j=1; j<3; j++) {
byte redWJ = red/(weight*j);
byte greenWJ = green/(weight*j);
byte blueWJ = blue/(weight*j);
if (a-j >= 0 && a_on)
led_a.setPixelColor(a-j, redWJ, greenWJ, blueWJ);
if (b-j >= 0 && b_on)
led_b.setPixelColor(b-j, redWJ, greenWJ, blueWJ);
if (c-j >= 0 && c_on)
led_c.setPixelColor(c-j, redWJ, greenWJ, blueWJ);
if (d-j >= 0 && d_on)
led_d.setPixelColor(d-j, redWJ, greenWJ, blueWJ);
if (e-j >= 0 && e_on)
led_e.setPixelColor(e-j, redWJ, greenWJ, blueWJ);
if (f-j >= 0 && f_on)
led_f.setPixelColor(f-j, redWJ, greenWJ, blueWJ);
if (a-j <= LED_COUNT && a_on)
led_a.setPixelColor(a+j, redWJ, greenWJ, blueWJ);
if (b-j <= LED_COUNT && b_on)
led_b.setPixelColor(b+j, redWJ, greenWJ, blueWJ);
if (c-j <= LED_COUNT && c_on)
led_c.setPixelColor(c+j, redWJ, greenWJ, blueWJ);
if (d-j <= LED_COUNT && d_on)
led_d.setPixelColor(d+j, redWJ, greenWJ, blueWJ);
if (e-j <= LED_COUNT && e_on)
led_e.setPixelColor(e+j, redWJ, greenWJ, blueWJ);
if (f-j <= LED_COUNT && f_on)
led_f.setPixelColor(f+j, redWJ, greenWJ, blueWJ);
}
led_a.show();
led_b.show();
led_c.show();
led_d.show();
led_e.show();
led_f.show();
delay(wait);
}
}
void spiral(unsigned long color, byte wait) {
const byte weight = 18;
byte red = (color & 0xFF0000) >> 16;
byte green = (color & 0x00FF00) >> 8;
byte blue = (color & 0x0000FF);
for (int level=LED_COUNT-1; level >= 0; level--) {
for (int strip=0; strip < STRIP_COUNT; strip++) {
clearLEDs(false);
switch (strip) {
case 0:
led_f.setPixelColor(level, red/weight, green/weight, blue/weight);
led_a.setPixelColor(level, color);
led_b.setPixelColor(level, red/weight, green/weight, blue/weight);
break;
case 1:
led_a.setPixelColor(level, red/weight, green/weight, blue/weight);
led_b.setPixelColor(level, color);
led_c.setPixelColor(level, red/weight, green/weight, blue/weight);
break;
case 2:
led_b.setPixelColor(level, red/weight, green/weight, blue/weight);
led_c.setPixelColor(level, color);
led_d.setPixelColor(level, red/weight, green/weight, blue/weight);
break;
case 3:
led_c.setPixelColor(level, red/weight, green/weight, blue/weight);
led_d.setPixelColor(level, color);
led_e.setPixelColor(level, red/weight, green/weight, blue/weight);
break;
case 4:
led_d.setPixelColor(level, red/weight, green/weight, blue/weight);
led_e.setPixelColor(level, color);
led_f.setPixelColor(level, red/weight, green/weight, blue/weight);
break;
case 5:
led_e.setPixelColor(level, red/weight, green/weight, blue/weight);
led_f.setPixelColor(level, color);
led_a.setPixelColor(level, red/weight, green/weight, blue/weight);
break;
}
led_a.show();
led_b.show();
led_c.show();
led_d.show();
led_e.show();
led_f.show();
delay(wait);
}
}
}
// Sets all LEDs to off, but DOES NOT update the display;
// call leds.show() to actually turn them off after this.
void clearLEDs(bool immediate)
{
for (int i=0; i<LED_COUNT; i++)
{
led_a.setPixelColor(i, 0);
led_b.setPixelColor(i, 0);
led_c.setPixelColor(i, 0);
led_d.setPixelColor(i, 0);
led_e.setPixelColor(i, 0);
led_f.setPixelColor(i, 0);
}
if (immediate) {
led_a.show();
led_b.show();
led_c.show();
led_d.show();
led_e.show();
led_f.show();
}
}
unsigned long randomColor() {
return COLORS[random(sizeof(COLORS)/sizeof(unsigned long))];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment