Instantly share code, notes, and snippets.
ppelleti/alitove_with_button.ino
Last active Dec 24, 2016
Arduino sketch for displaying several different patterns of lights on WS2811/WS2812 LEDs, controlled by a pushbutton.
/* This Arduino sketch is for controlling a string of Alitove lights | |
* from an Adafruit Trinket. The lights are connected to the | |
* Trinket's pin 1 through a resistor. A pushbutton is connected from | |
* pin 0 to ground. You can use the pushbutton to cycle through the | |
* following modes: | |
* | |
* 1. Solid purple | |
* 2. Blue with white twinkles | |
* 3. Rainbow | |
* 4. Multicolored blinking | |
* | |
* We use the Trinket's EEPROM to store the mode, so it is retained | |
* when the power is off. | |
* | |
* For more information, see my blog post: | |
* | |
* http://funwithsoftware.org/posts/2016-12-23-programmable-christmas-lights-with-trinket.html | |
* | |
* | |
* Portions of this code (most notably, the setup(), rainbowCycle(), | |
* and Wheel() functions, and the comments about NeoPixels) are | |
* derived from: | |
* | |
* https://github.com/adafruit/Adafruit_NeoPixel/blob/master/examples/strandtest/strandtest.ino | |
* | |
* I'm not entirely clear whether strandtest.ino is under the LGPLv3+, | |
* like the NeoPixel library itself, or not. The strandtest.ino file | |
* doesn't say. | |
* | |
* The rest of the code in this sketch is by Patrick Pelletier and is | |
* dedicated to the public domain. (cc0) | |
*/ | |
#include <Adafruit_NeoPixel.h> | |
#ifdef __AVR__ | |
#include <avr/power.h> | |
#endif | |
#include <EEPROM.h> | |
#define SWITCH 0 | |
#define PIN 1 | |
// Parameter 1 = number of pixels in strip | |
// Parameter 2 = Arduino pin number (most are valid) | |
// Parameter 3 = pixel type flags, add together as needed: | |
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) | |
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) | |
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products) | |
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2) | |
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products) | |
Adafruit_NeoPixel strip = Adafruit_NeoPixel(50, PIN, NEO_RGB + NEO_KHZ800); | |
// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across | |
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input | |
// and minimize distance between Arduino and first pixel. Avoid connecting | |
// on a live circuit...if you must, connect GND first. | |
void setup() { | |
// This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket | |
#if defined (__AVR_ATtiny85__) | |
if (F_CPU == 16000000) clock_prescale_set(clock_div_1); | |
#endif | |
// End of trinket special code | |
strip.begin(); | |
strip.show(); // Initialize all pixels to 'off' | |
// initialize the SWITCH pin as an input. | |
pinMode(SWITCH, INPUT); | |
// ...with a pullup | |
digitalWrite(SWITCH, HIGH); | |
} | |
#define MODE_ADDR 0 | |
#define N_MODES 4 | |
void loop() { | |
uint8_t mode = EEPROM.read(MODE_ADDR) % N_MODES; | |
switch (mode) { | |
case 0: | |
singleColor(strip.Color(192, 0, 255)); // purple | |
break; | |
case 1: | |
twinkle(strip.Color(0, 0, 255), strip.Color(255, 255, 255), 50); | |
break; | |
case 2: | |
rainbowCycle(20); | |
break; | |
case 3: | |
colorBlink(50); | |
break; | |
} | |
mode = (mode + 1) % N_MODES; | |
EEPROM.write(MODE_ADDR, mode); | |
} | |
bool buttonPressed() { | |
bool pressed = false; | |
while (! digitalRead(SWITCH)) | |
pressed = true; | |
return pressed; | |
} | |
// Fill the dots with a color | |
void singleColor(uint32_t c) { | |
for(uint16_t i=0; i<strip.numPixels(); i++) { | |
strip.setPixelColor(i, c); | |
} | |
strip.show(); | |
while (! buttonPressed()) | |
; | |
} | |
#define MAX_TWINKLE 5 | |
void twinkle(uint32_t c1, uint32_t c2, uint8_t wait) { | |
int16_t tw[MAX_TWINKLE]; | |
for(uint16_t i=0; i<strip.numPixels(); i++) { | |
strip.setPixelColor(i, c1); | |
} | |
strip.show(); | |
for (uint8_t i = 0; i < MAX_TWINKLE; i++) { | |
tw[i] = -1; | |
} | |
for ( ; ; ) { | |
for (uint8_t i = 0; i < MAX_TWINKLE; i++) { | |
if (tw[i] >= 0) | |
strip.setPixelColor(tw[i], c1); | |
tw[i] = random(strip.numPixels()); | |
strip.setPixelColor(tw[i], c2); | |
strip.show(); | |
delay(wait); | |
if (buttonPressed()) | |
return; | |
} | |
} | |
} | |
void colorBlink(uint8_t wait) { | |
uint16_t i; | |
uint8_t hue; | |
uint32_t c; | |
while (! buttonPressed()) { | |
i = random(strip.numPixels()); | |
hue = random(256); | |
c = Wheel(hue); | |
strip.setPixelColor(i, c); | |
strip.show(); | |
delay(wait); | |
} | |
} | |
// Slightly different, this makes the rainbow equally distributed throughout | |
void rainbowCycle(uint8_t wait) { | |
uint16_t i, j; | |
for ( ; ; ) { | |
for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel | |
for(i=0; i< strip.numPixels(); i++) { | |
strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255)); | |
} | |
strip.show(); | |
delay(wait); | |
if (buttonPressed()) | |
return; | |
} | |
} | |
} | |
// Input a value 0 to 255 to get a color value. | |
// The colours are a transition r - g - b - back to r. | |
uint32_t Wheel(byte WheelPos) { | |
WheelPos = 255 - WheelPos; | |
if(WheelPos < 85) { | |
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3); | |
} | |
if(WheelPos < 170) { | |
WheelPos -= 85; | |
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3); | |
} | |
WheelPos -= 170; | |
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment