Go Down

Topic: LPD8806 LED strip project (Read 7997 times) previous topic - next topic

pcox

Thought you might like to see the end result of my first Arduino project.  It involved the local High School band percussion group, three buckets with some piezo transducers for pickups on them, some circuitry for signal conditioning before inputs on the Arduino board, and switches and code to make each of these different "modes" during the different parts of the cadences.  I'm on the right flipping switches to change the modes during their performance.  It was dark.  This is a 5m strip. 
http://www.youtube.com/watch?v=M-4S7i0Z77s&feature=youtube_gdata_player

I used the adafruit LPD8806 library which makes the LEDs incredibly easy to use.  Based on my horribly inefficient code (hey, first project - I can optimize it later), I was getting enough refresh rate on it to even possibly turn the light strip into a pseudo strobe light.  Version 2 project.

The code essentially splits the LED strip into 3 zones, one for the red drum, one for green, and one for blue.  I kept the light intensities in each of the arrays based on the switch settings, then combined them on the set.pixel routine to allow me to combine the lights for the final chase sequence.

It was definitely fun to work with the drummers as well and see how they interacted with it.  I'll post the code once I get that "postable".

funkyguy4000

Hey that was super sweet! (just a heads up there is another section down further in the forum category page for this called exhibition i believe but i'm glad you posted in here cause I would have never seen it)

Could you post a list of materials?  You mentioned that you used a 5m LED strip, was there only one or were there more?
Also what sort of drums were they that you could differentiate the size of the light blip according to the pitch of the drum?
Accelerate to 88 miles per hour.

pcox

Completely missed the gallery.  Maybe a moderator can move it there for me.  I had gotten some previous assistance in this forum and so thought I would post it here.  Sorry.  I'll answer the questions anyway. :)

Just a single LED strip.  It looks like there are two due to the reflection off of the stage.  I had mounted them on a piece of wood that allowed them to face the audience.  The stage paint was slighty shiny and gave it that double look.  I got lucky.

As for the drums, they were just black plastic buckets that the kids were hitting in different places to get the different sounds.  The piezo pickups allowed me to see the amount of vibration and map that to a suitable range to change the intensity of the lights.  For the different modes, I had decay values, borders between the colors, and end points to worry about, but after a first practice, I thought 5m may be two small so I hooked up the other 5m strip, changed my constants in the sketch, and voila, 30 feet of LED coolness.  The timing didn't work which the chase sequence and the green drummer changes the red and blue blips with his drum hit, so I went with version 1.0

LOM and code coming when I can get to the computer I did the development on.

funkyguy4000

Yea I noticed that it was a reflection. I've done my fair share of stage time. 

The code would be really great considering i've never worked with piezo sensors.
Accelerate to 88 miles per hour.

daveydav27

I must say, That was frickin awesome!!! Nice work, very well done.

talofer99

#5
Jun 07, 2012, 05:10 am Last Edit: Jun 07, 2012, 05:17 am by talofer99 Reason: 1
Very cool !!!!! :)

Would love to see the code when u post it, I defently know whats the next thing I'm orderign from ebay ;)
Can you be kind and post a link to a simlir product that u used, like the piazo pickups and the led strip ?
Thanks for sharing :)

april

If thats all your own work you are incredibly talented
Never seen anything like it
Look forward to more detail on this .......and to your next project.
Top stuff

Cranium

Awesome work!  I like all the different modes you did.

I'd like to see how you wired up the piezo transducers and calibrated them.  :)

pcox

Here's the code.  Read the switches, read the piezo elements, fill the red/green/blue arrays based on switch settings, write strip. repeat.

Couple of comments about the video, during the finale when the strip goes white, you can see the right side is brighter.  Voltage drop.  Need to drive the strip from both sides or middle as well.  version 2.  

As for calibration, I didn't.  Since the Arduino A/D returns a value up to 1023, I never saw higher than 500 or so based on my circuit.  What I did was map the value from 0-600 to 0-127 for the relative value:

 outputValue1 = map(sensorValue1, 0, 600, 0, 127);

My calibration will be from a pot for each drum to modify the 600 value to make it more sensitive or not.  version 2.  electronic sensitivity.

I'll draw up a schematic for the piezo elements, but they were just Radio Shack piezo elements that I attached to the buckets about 4 inches from the bottom of the bucket.  The drummers flipped them over to play them and the wires just came back to the switch box.  I originally was playing with momentary contact buttons, hence the "button" in the code, but I moved to switches for more functionality.  The piezo elements were connected to some diodes (rectify step), a zener (5.1 v to protect the arduino), and an RC circuit for a decent decay value.  had to play with that since my math didn't work right with the sampling frequency of the loop.

Even though my code is horribly inefficient, because it does the same things over and over, the timing is very stable per loop.  Very evident on the chase sequences where there are no hiccups.  I'd love to get some pointers on arrays and optimizations since version 2 will include both strips and a few more outputs.  

And because the code is modular, adding another strip and another drum or two wouldn't be hard.  

The sparkle effect was my favorite so I'll let the interested folks peruse the finale code for that. involved random values larger than the decreasing loop variable and pushing that out to the various LEDs.

Thanks for the comments and looking forward to suggestions for improvements.  Code in two parts:

Code: [Select]


#include "LPD8806.h"
#include "SPI.h"

#define button1 22
#define button2 23
#define button3 24
#define button4 25
#define button5 26
#define button6 27
#define button7 28
#define button8 29
#define button9 30
#define button10 31

#define stripSize 160

const int analogInPin1 = A0;  // Analog input pin for Drum1
const int analogInPin2 = A1;  // Analog input pin for Drum2
const int analogInPin3 = A2;  // Analog input pin for Drum3

int sensorValue1 = 0;        // value read from the Drum1
int sensorValue2 = 0;        // value read from the Drum2
int sensorValue3 = 0;        // value read from the Drum3
int outputValue1 = 0;        // mapped value for the strip
int outputValue2 = 0;        // mapped value for the strip
int outputValue3 = 0;        // mapped value for the strip
int redPulseWidthDecay = 4;   // Decay value for pulse widths.  higher for shorter pulses
int greenPulseWidthDecay = 4;   // Decay value for pulse widths.  higher for shorter pulses
int bluePulseWidthDecay = 4;   // Decay value for pulse widths.  higher for shorter pulses
int redGreen = 53;            //edge between red and green segments
int greenBlue = 106;          //edge between green and blue segments
int redLeft = 0;              // Set up edges for loops
int redRight = 53;
int greenLeft= 54;
int greenRight = 106;
int blueLeft = 107;
int blueRight = 160;

int drum1[stripSize];      // set up array for red drum hits
int drum2[stripSize];      // set up array for green drum hits
int drum3[stripSize];      // set up array for blue drum hits
int drum1position=26;      // drum location on strip.  Centered at 26 for red
int drum2position=80;      // 80 for green
int drum3position=134;     // 134 for Blue
int redPulseButton=0;      // set up button states for six buttons
int greenPulseButton=0;
int bluePulseButton=0;
int redChaseButton=0;
int greenChaseButton=0;
int blueChaseButton=0;
int finaleButton = 0;
int redFullButton = 0;
int greenFullButton = 0;
int blueFullButton = 0;



// use the 51/52 default for hardware SPI on the Mega
LPD8806 strip = LPD8806(stripSize);

void setup() {
 
 // Start up the LED strip
 strip.begin();


 // Update the strip, to start they are all 'off'
 strip.show();

 pinMode(button1,INPUT);
 pinMode(button2,INPUT);
 pinMode(button3,INPUT);
 pinMode(button4,INPUT);
 pinMode(button5,INPUT);
 pinMode(button6,INPUT);
 pinMode(button7,INPUT);
 pinMode(button8,INPUT);
 pinMode(button9,INPUT);
 pinMode(button10,INPUT);

}

void loop() {

 //read digital pins and map to variables

 redPulseButton = digitalRead(button1);
 redChaseButton = digitalRead(button2);
 redFullButton = digitalRead(button8);
 greenPulseButton = digitalRead(button3);
 greenChaseButton = digitalRead(button4);
 greenFullButton = digitalRead(button9);
 bluePulseButton = digitalRead(button5);
 blueChaseButton = digitalRead(button6);
 blueFullButton = digitalRead(button10);

 finaleButton = digitalRead(button7);



 // read the drum values:
 sensorValue1 = analogRead(analogInPin1);            
 sensorValue2 = analogRead(analogInPin2);            
 sensorValue3 = analogRead(analogInPin3);            

 // map it to the range of the analog out:
 outputValue1 = map(sensorValue1, 0, 600, 0, 127);
 outputValue2 = map(sensorValue2, 0, 600, 0, 127);
 outputValue3 = map(sensorValue3, 0, 600, 0, 127);

 //Finale button hit?  Big Red Button

 if (finaleButton==1) {

   int finaleDecay=1;

   /// white for a flash, then decay to red/green/blue
   for (int i=0; i<stripSize; i++) {
     drum1[i]=127;
     drum2[i]=127;
     drum3[i]=127;
   }


   for (int i=0; i<stripSize; i++) {
     strip.setPixelColor(i,drum1[i],drum2[i],drum3[i]);
   }
   strip.show();
   delay(1000);

   for (int i=0; i<stripSize; i++) {
     strip.setPixelColor(i,0,0,0);
   }
   strip.show();
   delay(1500);



   // red green blue full for 3 seconds

   for (int i=0; i<54; i++) {
     drum1[i]=50;
     drum2[i]=0;
     drum3[i]=0;
   }
   for (int i=54; i<107; i++) {
     drum2[i]=50;
     drum1[i]=0;
     drum3[i]=0;  
   }
   for (int i=107; i<160; i++) {
     drum3[i]=50;
     drum1[i]=0;
     drum2[i]=0;
   }



   //slow down the last bit for effect
   for (int dimmerLoop=55; dimmerLoop>0;dimmerLoop--) {
     for (int i=0; i<54; i++) {

       drum1[i]=dimmerLoop-random(0,127);
       if (drum1[i]<0) drum1[i]=0;
       //   drum1[i]=dimmerLoop;
     }
     for (int i=54; i<107; i++) {
       drum2[i]=dimmerLoop-random(0,127);
       if (drum2[i]<0) drum2[i]=0;
       //drum2[i]=dimmerLoop;
     }
     for (int i=107; i<160; i++) {
       drum3[i]=dimmerLoop-random(0,127);
       if (drum3[i]<0) drum3[i]=0;
       //      drum3[i]=dimmerLoop;
     }
     for (int i=0; i<stripSize; i++) {
       strip.setPixelColor(i,drum1[i],drum2[i],drum3[i]);
     }
     strip.show();
     delay(60);
   }

   //turn off all LEDs and wait for 20 seconds for someone to turn off power
   for (int i=0; i<stripSize; i++) {
     strip.setPixelColor(i,0,0,0);
   }
   strip.show();
   delay(20000);
 }


pcox

Code part deux:

Code: [Select]


 //red drum analysis

 if (redChaseButton==1) {
   redPulseWidthDecay=0;
   redRight=stripSize-1;
 }
 else {
   if (redPulseButton==1) {
     redPulseWidthDecay=2;
   }
   else {
     redPulseWidthDecay=6;
   }
   redRight=53;
 }
 //Red Drum array setup
 for (int i=redLeft; i<drum1position; i++) {
   drum1[i]=drum1[i+1]-redPulseWidthDecay;
   if (drum1[i]<0) drum1[i]=0;
 }
 for (int i=redRight-1;i>drum1position;i--) {
   drum1[i]=drum1[i-1]-redPulseWidthDecay;
   if (drum1[i]<0) drum1[i]=0;
 }
 //clear out other segments if chase button is turned off
 if (redChaseButton!=1) {
   for (int i=redRight;i<stripSize;i++) {
     drum1[i]=drum1[i]-10;
     if (drum1[i]<0) drum1[i]=0;
   }
 }


 drum1[drum1position]=outputValue1;

 if ((outputValue1!=0) && (redChaseButton==1))  {
   drum1[drum1position]=127;
 }

 if ((redFullButton==1) && (redChaseButton!=1)) {
   for (int j=redLeft;j<redRight;j++) {
     drum1[j]=outputValue1;
   }
 }



 //green drum analysis

 if (greenChaseButton==1) {
   greenPulseWidthDecay=0;
   greenLeft=0;
   greenRight=stripSize-1;
 }
 else {
   if (greenPulseButton==1) {
     greenPulseWidthDecay=1;
   }
   else {
     greenPulseWidthDecay=4;
   }
   greenLeft=54;
   greenRight=106;
 }
 //green Drum array setup
 for (int i=greenLeft; i<drum2position; i++) {
   drum2[i]=drum2[i+1]-greenPulseWidthDecay;
   if (drum2[i]<0) drum2[i]=0;
 }
 for (int i=greenRight-1;i>drum2position;i--) {
   drum2[i]=drum2[i-1]-greenPulseWidthDecay;
   if (drum2[i]<0) drum2[i]=0;
 }

 //clear out other segments if chase button is turned off
 if (greenChaseButton!=1) {
   for (int i=0;i<greenLeft;i++) {
     drum2[i]=drum2[i]-10;
     if (drum2[i]<0) drum2[i]=0;
   }
   for (int i=greenRight+1;i<stripSize;i++) {
     drum2[i]=drum2[i]-10;
     if (drum2[i]<0) drum2[i]=0;
   }
 }


 drum2[drum2position]=outputValue2;

 if ((outputValue2!=0) && (greenChaseButton==1))  {
   drum2[drum2position]=127;
 }

 if ((greenFullButton==1) && (greenChaseButton!=1)) {
   for (int j=greenLeft;j<greenRight;j++) {
     drum2[j]=outputValue2;
   }
 }



 //blue drum analysis

 if (blueChaseButton==1) {
   bluePulseWidthDecay=0;
   blueRight=stripSize-1;
   blueLeft=0;
 }
 else {
   if (bluePulseButton==1) {
     bluePulseWidthDecay=1;
   }
   else {
     bluePulseWidthDecay=4;
   }
   blueLeft=107;
   blueRight=160;
 }
 //blue Drum array setup
 for (int i=blueLeft; i<drum3position; i++) {
   drum3[i]=drum3[i+1]-bluePulseWidthDecay;
   if (drum3[i]<0) drum3[i]=0;
 }
 for (int i=blueRight-1;i>drum3position;i--) {
   drum3[i]=drum3[i-1]-bluePulseWidthDecay;
   if (drum3[i]<0) drum3[i]=0;
 }

 //clear out other segments if chase button is turned off
 if (blueChaseButton!=1) {
   for (int i=0;i<blueLeft;i++) {
     drum3[i]=drum3[i]-10;
     if (drum3[i]<0) drum3[i]=0;
   }
 }

 drum3[drum3position]=outputValue3;

 if ((outputValue3!=0) && (blueChaseButton==1))  {
   drum3[drum3position]=127;
 }

 if ((blueFullButton==1) && (blueChaseButton!=1)) {
   for (int j=blueLeft;j<blueRight;j++) {
     drum3[j]=outputValue3;
   }
 }

 // Now that the arrays are good, push them to the strip
 for (int i=0; i<stripSize; i++){
   strip.setPixelColor(i,drum1[i],drum2[i],drum3[i]);
 }

 strip.show();    

}

tekket

From Gree-Leds.com  the 32pixel LPD8806 were $13/meter and the new 52pixels were $17/meter (plus change)

funkyguy4000

Interesting. 
I just purchased a 5m RGB 5050 addressable from ebay for $32
Accelerate to 88 miles per hour.

april


Interesting. 
I just purchased a 5m RGB 5050 addressable from ebay for $32

Think this might be 1 meter
http://www.ebay.com/sch/i.html?clk_rvr_id=386315056407&_kw=RGB+5050+addressable

marc017

#13
Oct 02, 2012, 07:02 am Last Edit: Oct 02, 2012, 08:26 am by marc017 Reason: 1
Cool project! I am looking to start my first arduino project with lpd8806 lights. Hopefully I can learn it as fast as you did  :D

I have spoken to a few (15) china suppliers. Looks like the going rate is about $40 for 5m and then $40-50 shipping via DHL.


Well, $98.89 was the total after shipping and paypal fees for 3 - 5m 5050 PD8806 Strips, 300/5m, ip68, Tape Backing.

tekket

You sure that's not $40 per one(1) m ?  That's the standard retail price.  $40 for 5 meters is incredibly cheap.  You should double check that they aren't going to send you one(1) meter -cut- from a five(5) meter reel, which is what is done if you buy under 5 meters.




Go Up