Skip to content

Instantly share code, notes, and snippets.

@yomimono
Created December 14, 2013 07:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yomimono/7956501 to your computer and use it in GitHub Desktop.
Save yomimono/7956501 to your computer and use it in GitHub Desktop.
An Arduino program which instructs independently-addressable wearable LEDs to change color at random while avoiding certain undesirable states, and to set their intensity in accordance with input from a light sensor.
#include <Wire.h>
#include <Adafruit_NeoPixel.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_TSL2561.h>
#define PIN 6
#define MINIMUM_LUX 20
// Parameter 1 = number of pixels in strip
// Parameter 2 = 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)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, PIN, NEO_GRB + NEO_KHZ800);
Adafruit_TSL2561 tsl = Adafruit_TSL2561(TSL2561_ADDR_FLOAT, 12345);
int lux = 127;
void configureSensor(void)
{
tsl.setGain(TSL2561_GAIN_1X); /* No gain ... use in bright light to avoid sensor saturation */
//tsl.setGain(TSL2561_GAIN_16X); /* 16x gain ... use in low light to boost sensitivity */
//tsl.enableAutoGain(true); /* Auto-gain ... switches automatically between 1x and 16x */
/* Changing the integration time gives you better sensor resolution (402ms = 16-bit data) */
tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS); /* fast but low resolution */
//tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_101MS); /* medium resolution and speed */
//tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_402MS); /* 16-bit data but slowest conversions */
}
void setup() {
//onboard LED, for problem reporting
int blinky;
blinky = 13;
pinMode(blinky, OUTPUT);
//pixels
strip.begin();
//serial port; useful only for debug output
Serial.begin(9600);
//light sensor
if(!tsl.begin()) {
// Give a visual indication with the onboard LED (pin 13, initialized above) if there is a probable wiring problem
digitalWrite(blinky, HIGH);
Serial.print("Ooops, no TSL2561 detected ... Check your wiring or I2C ADDR!");
digitalWrite(blinky, LOW);
delay(10);
while(1);
}
configureSensor();
randomSeed(analogRead(10)); //analog read of an unconnected pin gives us good-enough entropy
}
void loop() {
random_walk(50, 10);
}
uint8_t permute_color(uint8_t start_color, uint8_t max_change) {
uint8_t rand;
rand = random(1, max_change);
//always wander away from overflow/underflow
if(rand > start_color) {
return start_color + rand;
} else if(255 - rand > start_color) {
return start_color - rand;
}
if(random(1, 2) == 2) {
return start_color - rand;
}
return start_color + rand;
}
uint8_t calculate_tween(uint8_t start_color, uint8_t end_color, uint8_t this_step, uint8_t tween_constant) {
float tweenfactor;
float difference;
uint8_t change;
if(this_step == 0) return start_color;
tweenfactor = ((float) this_step / (float) tween_constant);
if(end_color > start_color) {
difference = (float) end_color - (float) start_color;
change = (uint8_t) (start_color + difference*tweenfactor);
} else if(start_color > end_color) {
difference = (float) start_color - (float) end_color;
change = (uint8_t) (start_color - difference*tweenfactor);
}
//Serial.print("Saying we should do "); Serial.print(change); Serial.print(" to get the tween between "); Serial.print (start_color); Serial.print(" and "); Serial.print(end_color); Serial.print(" for step "); Serial.print(this_step); Serial.print(" of "); Serial.println(tween_constant);
return change;
}
void random_walk(uint8_t max_change, uint8_t tween) {
uint16_t i, j;
sensors_event_t event;
uint8_t nextred[strip.numPixels()];
uint8_t nextgreen[strip.numPixels()];
uint8_t nextblue[strip.numPixels()];
uint8_t lastred[strip.numPixels()];
uint8_t lastgreen[strip.numPixels()];
uint8_t lastblue[strip.numPixels()];
//set colors separately from brightness
//for every color cycle, do 20 brightness reads
for(j=0; ; j++) {
if ((j % 5) == 0) {
tsl.getEvent(&event);
if(event.light) {
lux = (int) ((double) (event.light) *(.15));
//Serial.print("Raw light reading: "); Serial.println(event.light);
if(lux < MINIMUM_LUX) lux = MINIMUM_LUX;
if(lux > 255) lux = 255;
//Serial.print("Read lux as "); Serial.println(lux);
} else {
//sensor is likely saturated; crank it
lux = 255;
}
}
strip.setBrightness(lux);
if((j % tween) == 0) {
//choose a new color for each pixel
for(i=0; i<strip.numPixels(); i++) {
if(j == 0 && lastred[i] == 0 && lastgreen[i] == 0 && lastblue[i] == 0) {
//Serial.print("Randomizing initial value for pixel "); Serial.println(i);
lastred[i] = random(0, 255);
lastgreen[i] = random(0, 255);
lastblue[i] = random(0, 255);
} else {
//Serial.print("Shifting old value into previous array for pixel "); Serial.println(i);
lastred[i] = nextred[i];
lastgreen[i] = nextgreen[i];
lastblue[i] = nextblue[i];
}
nextred[i] = permute_color(lastred[i], max_change);
nextgreen[i] = permute_color(lastgreen[i], max_change);
nextblue[i] = permute_color(lastblue[i], max_change);
}
}
for(i=0; i < strip.numPixels(); i++) {
uint8_t redtween;
uint8_t greentween;
uint8_t bluetween;
//Serial.print("Going from "); Serial.print(lastred[i]); Serial.print(", ");
//Serial.print(lastgreen[i]); Serial.print(", ");
//Serial.print(lastblue[i]); Serial.print(", ");
//Serial.print("to "); Serial.print(nextred[i]); Serial.print(", ");
//Serial.print(nextgreen[i]); Serial.print(", ");
//Serial.print(nextblue[i]);
//Serial.print(" on pixel number "); Serial.print(i);
//Serial.println("");
//take tween cycles to go between lastred and nextred, etc
redtween = calculate_tween(lastred[i], nextred[i], j%tween, tween);
greentween = calculate_tween(lastgreen[i], nextgreen[i], j%tween, tween);
bluetween = calculate_tween(lastblue[i], nextblue[i], j%tween, tween);
//Serial.print("Setting color to "); Serial.print(redtween); Serial.print(", ");
//Serial.print(greentween); Serial.print(", ");
//Serial.print(bluetween); Serial.print(", ");
//Serial.print(" on pixel number "); Serial.print(i);
//Serial.println("");
strip.setPixelColor(i, redtween, greentween, bluetween);
}
strip.show();
delay(10);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment