Skip to content

Instantly share code, notes, and snippets.

@davidegironi
Created March 1, 2017 19:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davidegironi/3144efdc6d67e5df55438cc3cba613c8 to your computer and use it in GitHub Desktop.
Save davidegironi/3144efdc6d67e5df55438cc3cba613c8 to your computer and use it in GitHub Desktop.
Arduino Random Rainbow Stop
/*
Arduino Random Rainbow Stop
Random Led Strip Selection
Copyright (c) Davide Gironi, 2015
References:
+ https://github.com/technobly/NeoPixel-KnightRider
+ https://github.com/adafruit/Adafruit_NeoPixel
Released under GPLv3.
Please refer to LICENSE file for licensing information.
*/
#include <Adafruit_NeoPixel.h>
#include <avr/power.h>
// Stop/Start button pin
#define BUTTONPIN 6
// Pin number for the led strip
#define LEDPIN 5
// Number of led connected
#define LEDNUM 12
// Random minimum led increase interval for selection
#define LEDSELMIN 25
// Random minimum led increase interval for selection
#define LEDSELMAX 45
// Minimum time to delay on rainbow random select loop
#define RAINBOWSPEEDMIN 50
// Maximum time to delay on rainbow random select loop
#define RAINBOWSPEEDMAX 80
// With of the previous dim led
#define PREVIOUSLEDDIMWITH 10
// Loop back and forth or circular
#define LOOPBACKANDFORTH 0
// Delay used for rainbow (ms)
#define RAYINBOWDELAYMS 20
// Enabled the idle loop after a button is selected
#define IDLELOOPENABLEDONSELECT 1
// Time to enable the idle loop (ms)
#define IDLELOOPENABLEDTIMEMS 30000
// NeoPixel library initialization
Adafruit_NeoPixel strip = Adafruit_NeoPixel(LEDNUM, LEDPIN, NEO_GRB + NEO_KHZ800);
// Actual led
static uint16_t current_led = 0;
// Actual color number
static uint8_t colornum = 0;
// Actual direction
static uint8_t dir = 1;
// Idle loop
static uint8_t idleloop = 1;
// Setup the Arduino
void setup() {
uint8_t i;
//set button
pinMode(BUTTONPIN, INPUT);
//set first led
current_led = 0;
//set first color
colornum = 0;
//initialize random
randomSeed(analogRead(0));
//start NeoPixel
strip.begin();
//set all off
for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, 0, 0, 0);
strip.show();
}
//wait a little
delay(1000);
}
// Main Arduino loop
void loop() {
uint16_t i, j;
//perform an idleloop
while(idleloop) {
for(j=0; j<256; j++) {
for(i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, colorWheel((i+j) & 255));
}
strip.show();
if(digitalRead(BUTTONPIN) == HIGH) {
while(digitalRead(BUTTONPIN) == HIGH);
idleloop = 0;
//set all off
for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, 0, 0, 0);
strip.show();
}
delay(500);
break;
}
delay(RAYINBOWDELAYMS);
}
}
//set the stop led
uint16_t stop_led = random(LEDSELMIN, LEDSELMAX);
//do the rainbox selection
stopRainbow(stop_led, RAINBOWSPEEDMIN, RAINBOWSPEEDMAX, PREVIOUSLEDDIMWITH);
//set all off
for(i=0; i<LEDNUM; i++) {
strip.setPixelColor(i, 0, 0, 0);
strip.show();
}
//stay on the select led until button is pressed, or idle timer is passed
uint32_t preMillis = millis();
while(digitalRead(BUTTONPIN) == LOW) {
#if IDLELOOPENABLEDONSELECT == 1
uint32_t curMillis = millis();
if(curMillis - preMillis > IDLELOOPENABLEDTIMEMS) {
idleloop = 1;
break;
}
#endif
colornum++;
uint32_t color = colorWheel(colornum);
strip.setPixelColor(current_led, color);
strip.show();
delay(RAYINBOWDELAYMS);
}
//wait for the button to release
while(digitalRead(BUTTONPIN) == HIGH);
}
// Loop colors and stop on selected led
// stop_led - led to stop on
// speedmin - timed led on/off minimum speed
// speedmax - timed led on/off maxmimum speed
// width - preious leds dim width
void stopRainbow(uint16_t stop_led, uint16_t speedmin, uint16_t speedmax, uint8_t width) {
uint16_t prev_color[LEDNUM];
uint16_t current_stopled = 0;
uint32_t color = 0;
uint16_t x = 0;
uint8_t changeddir = 0;
//rest previous color
for(x=0; x<LEDNUM; x++) {
prev_color[x] = 0;
}
while(1) {
//set a color
color = colorWheel(colornum);
prev_color[current_led] = color;
strip.setPixelColor(current_led, color);
//dim previous colors
for(x=0; x<LEDNUM; x++) {
if(x != current_led) {
prev_color[x] = dimColor(prev_color[x], width);
strip.setPixelColor(x, prev_color[x]);
}
}
//show strip
strip.show();
//next color
colornum++;
//stop on destination led
current_stopled++;
if(current_stopled>stop_led) {
//stop running
break;
}
//next led
#if LOOPBACKANDFORTH == 1
if(dir) {
current_led++;
if(current_led == LEDNUM-1) {
dir = 0;
}
} else {
if(current_led == 0) {
current_led++;
dir = 1;
} else
current_led--;
}
#else
current_led++;
if(current_led == LEDNUM)
current_led = 0;
#endif
//delay a little
uint16_t speed = random(speedmin, speedmax);
delay(speed);
}
}
// Dim a color given a width
uint32_t dimColor(uint32_t color, uint8_t width) {
return (((color&0xFF0000)/width)&0xFF0000) + (((color&0x00FF00)/width)&0x00FF00) + (((color&0x0000FF)/width)&0x0000FF);
}
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t colorWheel(uint8_t pos) {
if(pos < 85) {
return strip.Color(pos * 3, 255 - pos * 3, 0);
} else if(pos < 170) {
pos -= 85;
return strip.Color(255 - pos * 3, 0, pos * 3);
} else {
pos -= 170;
return strip.Color(0, pos * 3, 255 - pos * 3);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment