RobotThoughts

Neopixel Lamp

Splash_Light_by_Apex_3_preview_featured.jpg

After seeing the SplashLight from Avoooq and enjoying the image of a pouring bottle lamp, I felt I had to make one and make it awesome. My first idea was to recycle a lamp from around the house and create something completely new. I discovered that all my lamps already had a good use case. So I dug into the electronics drawers and found I had an unused Arduino UNO and enough electronic bits and lights to build my own lamp.

So first I had to protoype something. NeoPixels from Adafruit seemed like a good lighting choice with the Arduino board I had and I just happened to have a nice 60 strand without a purpose. I had 4 matching potentiometers and enough solder and wire to get started. Figuring that a mode selection switch and individual red, green, and blue controls would give me maximum flexibility, I began prototyping.

 

 

Once I had the basic code banged out (and I am a terrible and lazy coder…like all the good ones), I began refining the functions of the potentiomters.  I ended up with four modes.

  1. A white light mode with a variable brightness knob.
  2. Three knobs controlling red, green and blue to create your own specific lighting color.
  3. A simple random color applied to random pixel mode.
  4. Run all of the Adafruit example strand tests and more.

Here is a listing of the code below. Be sure to grab the NeoPixel library and read the Uberguide for NeoPixel:

include <Adafruit_NeoPixel.h>

define PIN 6
define MODEPIN 0
define REDPIN 1
define GREENPIN 2
define BLUEPIN 3
int MODEPOT = 0;
int MODE = 0;
int REDPOT = 0;
int REDCTL = 0;
int GREENPOT = 0;
int GREENCTL = 0;
int BLUEPOT = 0;
int BLUECTL = 0;
int rand1 = 0;
int rand2 = 0;
int rand3 = 0;
int rand4 = 0;

// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEOKHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEOKHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEOGRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEORGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)

AdafruitNeoPixel strip = AdafruitNeoPixel(60, PIN, NEOGRB + NEOKHZ800);

// 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() {
strip.begin();
strip.show(); // Initialize all pixels to 'off'
//  Enable for testing
//  Serial.begin(9600);
}

void loop() {
MODEPOT = analogRead(MODEPIN);
REDPOT = analogRead(REDPIN);
GREENPOT = analogRead(GREENPIN);
BLUEPOT = analogRead(BLUEPIN);
MODE = MODEPOT * (5.0 / 1023.0);
REDCTL = REDPOT * (255.0 / 1023.0);
GREENCTL = GREENPOT * (255.0 / 1023.0);
BLUECTL = BLUEPOT * (255.0 / 1023.0);
//  Enable for testing
//  Serial.println(GREENPOT);
//  Serial.println(GREENCTL);
if (MODE >= 0 && MODE < .5){                // Off
colorWipe(strip.Color(0, 0, 0), 5);        // Nothing
}
if (MODE >= .5 && MODE < 2){                // First Position
colorWipe(strip.Color(REDCTL, REDCTL, REDCTL), 5);  // White
}
if (MODE >= 2 && MODE < 3.5){                // Second Position
colorWipe(strip.Color(REDCTL, GREENCTL, BLUECTL), 5);      // COLOR MIX Based on Knob Position
}
if (MODE >= 3.5 && MODE < 4.5){                // Third Position
rand1 = random(10, 127);
rand2 = random(10, 127);
rand3 = random(10, 127);
rand4 = random(0, 60); // 60 is the number of my NeoPixels, yours may vary
strip.setPixelColor(rand4, rand1, rand2, rand3);      // Random Pixel Firing
strip.show();
}
if (MODE >= 4.5){                             // Fourth Position Modified strand testing
theaterChase(strip.Color(255, 255, 255), 50); // White
theaterChase(strip.Color(255,   0,   0), 50); // Red
theaterChase(strip.Color(  0,   255, 0), 50); // Green
theaterChase(strip.Color(  0,   0, 255), 50); // Blue
theaterChase(strip.Color(  0,   255, 255), 50); // Cyan
theaterChase(strip.Color(  255,   0, 255), 50); // Purple
theaterChase(strip.Color(  255,   255, 0), 50); // Yellow
rainbow(20);
rainbowCycle(20);
theaterChaseRainbow(50);
}
}

// Fill the dots one after the other with a color
void colorWipe(uint32t c, uint8t wait) {
for(uint16t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
}

// Single entry Color
void colorSingle(uint32t c,uint8t wait) {
for(uint16t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
}

void rainbow(uint8t wait) {
uint16t i, j;
for(j=0; j<256; j++) {
for(i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel((i+j) & 255));
}
strip.show();
delay(wait);
}
}

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8t wait) {
uint16t i, j;
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);
}
}

//Theatre-style crawling lights.
void theaterChase(uint32t c, uint8t wait) {
for (int j=0; j<10; j++) {  //do 10 cycles of chasing
for (int q=0; q < 3; q++) {
for (int i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, c);    //turn every third pixel on
}
strip.show();
delay(wait);
for (int i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, 0);        //turn every third pixel off
}
}
}
}

//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8t wait) {
for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
for (int q=0; q < 3; q++) {
for (int i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel on
}
strip.show();
delay(wait);
for (int i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, 0);        //turn every third pixel off
}
}
}
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if(WheelPos < 85) {
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
} else if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
} else {
WheelPos -= 170;
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
}

With the code ready enough, I turned to producing something more than a protypical collection of loose wires and alligator clips. Time to exercise the 3D printer. With my aging, but by no means useless, Makerbot Replicator 2, I began modeling and printing a case for the Arduino and a place to attach all of the potentiometers. After way more iterations than a skilled engineer would have taken, I arrived upon a flexible design that I could assemble the parts into.

I was able to solder together everything following this basic layout:

Finally, some wire routing and soldering to get the lamp assembled and I am ready for a first test:

 

Here are a few more pictures of the finished project:

 

 

 

Next Post

Previous Post

2 Comments

  1. Avooq December 3, 2014

    This is really cool, using strip lighting inside the bottle is very nice. Having a clear Splash with the lights inside the fountain might also be very effective.

  2. Rich Thompson December 4, 2014 — Post Author

    A clear splash with lights moving downward would look really cool…good idea.

Leave a Reply

© 2017 RobotThoughts

Theme by Anders Norén