LED Water Sound Light Show
Last weeks project was using my
Arduino board, some C++ examples, and a strand of WS2801 addressable
RGB LEDs.
This project was completed using mostly spare materials I had around the house.
Needed for project
- Drill with large drill bit (1/2 inch? I used a 3/8 because i did not have a 1/2 inch bit)
- Plastic Tubing - (I used a shower rod cover made of thin plastic.)
- Electrical Tape
- 3/8 inch clear tubing
- Water
- Arduino Uno or other chipboard/controller for ws2801 lights.
- 5V power supply
- 1 strand (20) ws2801 LEDs
- Water pipe insulation (for appearance)
- Misc cutting tools.
- Sparkfun Spectrum Analyzer Shield or something else made with MSGEQ7 chip to analyze audio signals.
Put LEDs in place.
Drill holes in your tube where you want your LEDs to be. I placed one on each end of the tube, and down the length of the tube created holes opposite each other so the water looks as if it is flowing in a spiral.
Be very careful not to shatter your plastic when drilling. Sometimes starting with small holes helps. In this case I used a torch to smooth the holes where they were fractured. Heating the plastic also helped push LED's through where the hole was too tight.
The WS2801 lights fit tightly in 3/8 inch tubing. It might be a good idea to seal them with silicon after filling them with water so they do not pop off and pour one ounce of water over your electronics. The lights themselves are waterproof, but your Xbox sitting under your display is most likely not. I wrapped the tube with electrical tape over the connections between the light and clear tube
.
Aesthetics
After I completed my initial spiral I was not impressed as it did not have even a remotely finished look. I returned to
Home Depot where I found some foam pipe insulation. the color was a dark grey and I felt that would make the center pipe of the display blend better.
Here is a small video of the finished display. The output from the TV audio runs to the spectrum analyzer shield and sends back 1 column of data, a number between 1 and 100 representing the strength of the signal. The line in the code below that reads "if(Counter > 5){" causes the lights to move faster every time it encounters any signal higher than 5 otherwise it will slowly cycle through all the colors in silence.
Arduino Code:
Here is the sketch I used, it is a modified version of the one by Adafruit that can be found
HERE.
// Comment
#include "SPI.h"
#include "WS2801.h"
int spectrumReset=5;
int spectrumStrobe=4;
int spectrumAnalog=0; //0 for left channel, 1 for right.
// Spectrum analyzer read values will be kept here.
int Spectrum[7];
//WS2801 strip = WS2801(32);
int dataPin = 11;
int clockPin = 13;
//WS2801 strip = WS2801(32, dataPin, clockPin);
WS2801 strip = WS2801(20, dataPin, clockPin);
void setup() {
Serial.begin(9600);
spectrum_init();
strip.begin();
strip.show(); // all off
//rainbowCycle(5);
}
int pos = 0;
void loop() {
// Some example procedures showing how to display to the pixels
//colorWipe(Color(255, 0, 0), 10);
//colorWipe(Color(0, 255, 0), 10);
//colorWipe(Color(0, 0, 255), 10);
//rainbow(10);
//rainbowCycle(5);
unsigned int Counter, Counter2;
readSpectrum();
Counter = (Spectrum[0]/10);
//Counter = ((Spectrum[0] + Spectrum[1]+ Spectrum[2]+ Spectrum[3]+ Spectrum[4]+ Spectrum[5]+ Spectrum[6])/7)/10;
Serial.println(Counter);
if(pos > 256 * 1){ // 5 strips 25 colors
pos = 0;
}
if(Counter > 5){
pos += Counter;
pos += 2;
rainbowCycleOne(pos);
}
else{
pos += 2;
rainbowCycleOne(pos);
delay(20);
}
//}
/*
for (pos=0; pos < 256 * 5; pos++) { // 5 cycles of all 25 colors in the wheel
rainbowCycleOne(pos);
}*/
}
void rainbow(uint8_t wait) {
int i, j;
for (j=0; j < 256; j++) { // 3 cycles of all 256 colors in the wheel
for (i=0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel( (i + j) % 255));
}
strip.show(); // write all the pixels out
delay(wait);
}
}
// Slightly different, this one makes the rainbow wheel equally distributed
// along the chain
void rainbowCycle(uint8_t wait) {
int i, j;
for (j=0; j < 256 * 5; j++) { // 5 cycles of all 25 colors in the wheel
for (i=0; i < strip.numPixels(); i++) {
// tricky math! we use each pixel as a fraction of the full 96-color wheel
// (thats the i / strip.numPixels() part)
// Then add in j which makes the colors go around per pixel
// the % 96 is to make the wheel cycle around
strip.setPixelColor(i, Wheel( ((i * 256 / strip.numPixels()) + j) % 256) );
}
strip.show(); // write all the pixels out
delay(wait);
}
}
void rainbowCycleOne(int j) {
int i;
for (i=0; i < strip.numPixels(); i++) {
// tricky math! we use each pixel as a fraction of the full 96-color wheel
// (thats the i / strip.numPixels() part)
// Then add in j which makes the colors go around per pixel
// the % 96 is to make the wheel cycle around
strip.setPixelColor(i, Wheel( ((i * 256 / strip.numPixels()) + j) % 256) );
}
strip.show(); // write all the pixels out
//delay(5);
}
// fill the dots one after the other with said color
// good for testing purposes
void colorWipe(uint32_t c, uint8_t wait) {
int i;
for (i=0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
}
/* Helper functions */
// Create a 24 bit color value from R,G,B
uint32_t Color(byte r, byte g, byte b)
{
uint32_t c;
c = r;
c <<= 8;
c |= g;
c <<= 8;
c |= b;
return c;
}
//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)
{
if (WheelPos < 85) {
return Color(WheelPos * 3, 255 - WheelPos * 3, 0);
} else if (WheelPos < 170) {
WheelPos -= 85;
return Color(255 - WheelPos * 3, 0, WheelPos * 3);
} else {
WheelPos -= 170;
return Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
}
void readSpectrum()
{
byte Band;
for(Band=0;Band <7 data-blogger-escaped-analogread="" data-blogger-escaped-and="" data-blogger-escaped-band="" data-blogger-escaped-spectrum="" data-blogger-escaped-spectrumanalog="">>1; //Read twice and take the average by dividing by 2
digitalWrite(spectrumStrobe,HIGH);
digitalWrite(spectrumStrobe,LOW);
}
}
void spectrum_init()
{
//Setup pins to drive the spectrum analyzer.
pinMode(spectrumReset, OUTPUT);
pinMode(spectrumStrobe, OUTPUT);
//Init spectrum analyzer
digitalWrite(spectrumStrobe,LOW);
delay(1);
digitalWrite(spectrumReset,HIGH);
delay(1);
digitalWrite(spectrumStrobe,HIGH);
delay(1);
digitalWrite(spectrumStrobe,LOW);
delay(1);
digitalWrite(spectrumReset,LOW);
delay(5);
}