Showing posts with label steampunk. Show all posts
Showing posts with label steampunk. Show all posts

Wednesday, February 18, 2015

Victorian Steampunk Light Dress - Graphic Equalizer Function

Got the base function working with a shift register and two RGB LED's.

 Pinout is:

  • Datapin: 2 ->SR1(14)
  • Latchpin: 8->SR1(4)
  • Clockpin: 4 ->SR1(11)
  • SR1&2(16,10)->+5V
  • SR1&2(8) ->GND
  • SR1&2(13)->GND
  • SR1&2(15,1-7) LED's
  • SR1(9)->SR2(14)
  • SR1(4)->SR2(4)
  • SR1(11)->SR2(11)
  • Sound sensor VCC-5V
  • Sound Sensor GND->GND
  • Sound Sensor Out-> Analog 0
  • in/out 3 -> RGB1 Red pin
  • RGB1 GND->GND
  • in/out 5 -> RGB1 Green Pin
  • in/out 6 ->RGB1 Blue Pin
  • in/out 9 -> RGB2 Red pin
  • RGB2 GND->GND
  • in/out 10 -> RGB2 Green Pin
  • in/out 11 ->RGB2 Blue Pin

(photos to come)

Code below.  Please see references to LED, ShiftRegister and RGBColor class.

#include <LED.h>
#include <ShiftRegister.h>
#include <RGBColor.h>
// DO NOT COPY
RGBColor * color;
RGBColor * color2;
Led * c2;
Led * c1;
byte dataPin = 2;              // The Serial Data Pin to the Shift Register
byte latchPin = 8;             // The Latch Pin to the Shift Register
byte clockPin = 4;

ShiftRegister * sr=new ShiftRegister(clockPin,latchPin,dataPin,16,2);

// END DO NOT COPY

// Tracking SR variabes
byte trackVector=0;
byte oldTrackAvg=0;
byte trackCount=0;
int trackTotal=0;
byte newTrackAvg=0;
//Standard SR Variables
int soundPin=A0;
byte mus_peak=0;
int mus_peakAdj=0;
byte mus_avg=0;
int mus_colorCount=5000;
long mus_count=0;
long mus_total=0;


void setup()
{
  c1=new Led(3,5,6);
  c2=new Led(9,10,11);
  pinMode(3, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  
  pinMode(dataPin, OUTPUT);    // Configure Digital Pins
    
  pinMode(latchPin, OUTPUT);
    
  pinMode(clockPin, OUTPUT);  
  
  color=new RGBColor();
  color2=new RGBColor();
  Serial.begin(9600);
}

void loop()
{
  //Serial.println(analogRead(soundPin));
  //delay(40);
  musicBox(*c1,*c2);

}


void musicBox(Led &led1, Led &led2)
{
  // Bytes for the shift register
  byte SRPulse[]={B00000000,B00011000,B00111100,B01111110,B11111111};
// Turn off the Shift Register pins and LEDS


  // set the color
    // increment the music color count
  mus_colorCount=mus_colorCount+1;
  
  if (mus_colorCount>=5000)
  {
    color->SetRandom();
    color2->setColors(color->Compliment());
    mus_colorCount=0;

    
  }
  
  // collect the local sound value
  byte val=collectAnalogAVG(2);
  clearLed(led1);
  clearLed(led2);
  // add the value to the track total
  trackTotal=trackTotal+val;
  trackCount=trackCount+1;
  if (trackCount>=10)
  {
    oldTrackAvg=newTrackAvg;
    newTrackAvg=trackTotal/trackCount;
    int trackDifferent=newTrackAvg-oldTrackAvg;
    if (trackDifferent<0)
    {
      Serial.print(trackVector);
      // if we've picked up less noise, decrement the vector.
      if (trackVector>=1) trackVector=trackVector-1;
      Serial.print("=");
      Serial.print(trackVector);
    }
    else if (trackDifferent==0)
    {
      // if the sound value has not changed, trackvector should stay the same.
    }
    else if (trackDifferent>100)
    {
      // if the difference is great, increment by 2.
      if (trackVector<=2)  trackVector=trackVector+2;
      else if (trackVector<=3) trackVector=trackVector+1;
    }
    else {
    
      if (trackVector<=3) trackVector=trackVector+1;
    }
    Serial.print("=");
      Serial.println(trackVector);
    // reset SR tracking
    trackTotal=0;
    trackCount=0;
  }
  

  // if the current value is above the average...
  // TODO: Add an array of bytes that go from 0 up to to 255 in steps of 30.  If the sound goes up, pulse up every 2 (add counter.)  If it goes down, pulse down every 30.
  // weight the value against the peak
  if (val>mus_avg)
  {
  double perc=map(val,0,mus_peak,12,100)*.01;
  led1.SetRGB(color->Red()*perc,color->Green()*perc,color->Blue()*perc);
  led2.SetRGB(color2->Red()*perc,color2->Green()*perc,color2->Blue()*perc);
  fireLed(led1);
  fireLed(led2);
  
  delay(15);
  }
  fireLEDs(SRPulse[trackVector]);
}

byte SRNum(double perc)
{
  if (perc>.9)
  {
    return 255;
  }
  else if (perc>.7)
  {
    return 85;
  }
  else if (perc>.5)
  {
    return 68;
  }
  else {
    return 0;
  }
}

byte collectAnalogAVG(byte times)


  
  int total=0;
  for (int i=0;i<times;i++)
  {
    //total=total+map(analogRead(pin),0,500,0,255);
    byte val=map(analogRead(soundPin),0,255,0,255);
    // add it to the total
    mus_total+=val;
    // increment the count
    mus_count=mus_count+1;
    // calculate the average
    mus_avg=mus_total/mus_count;
    // If we've hit a musical peak
    if (val>=mus_peak)
    {
    trackCount=trackCount+5;
    mus_peak=val;
    // increment the color count; it goes up faster with loud noise!
    mus_colorCount=mus_colorCount+500;
    mus_peakAdj=0;
    // return right away!
    return mus_peak;
    }
    else {
    // increment the adjustment
    mus_peakAdj=mus_peakAdj+1;
    if (mus_peakAdj>=10000)
    {
      // if we've gone lower a hundred times, reduce the peak.
      mus_peak=mus_peak*.9;
      mus_peakAdj=0;
    }
    }
    total=total+val;
    delay(2);
    
  }
  return total/times;
}

void SRFireDiv(ShiftRegister &r, byte div)
{
     for (int i=0;i<r.NoPins();i++)
      {
        if (i%div==0) r.ActivatePin(i);
      }
      fireLED(r);
}
void clearLed(Led led)
{
    
    
    analogWrite(led.RPin(),0);
    analogWrite(led.GPin(),0);
    analogWrite(led.BPin(),0);
  
}

// STOP DO NOT COPY



void fireLed(Led led)
{
    
    
    analogWrite(led.RPin(),led.Red());
    analogWrite(led.GPin(),led.Green());
    analogWrite(led.BPin(),led.Blue());
  
}

    void fireLEDs(int data)
  {
        digitalWrite(latchPin,LOW);
        shiftOut(dataPin,clockPin,MSBFIRST,data);  
        shiftOut(dataPin,clockPin,MSBFIRST,data);   // Send the data byte 2
        digitalWrite(latchPin, HIGH);

  }
    void fireLED(ShiftRegister &r)
  {
     
       
        digitalWrite(r.LatchPin(),LOW);
       // for (byte i=0; i<r.NoRegs();i++)
        //{
          // if the current register is active, fire its pins
           // Serial.println(i);
            shiftOut(r.DataPin(),r.ClockPin(),MSBFIRST,r.ShiftNum(0));
            shiftOut(r.DataPin(),r.ClockPin(),MSBFIRST,r.ShiftNum(1));
          
        //}
         digitalWrite(r.LatchPin(), HIGH);
  }
  

Saturday, February 7, 2015

A Rose by Pretty Much Any Color You'd Like...

Got the RGB led's to working with three functions:
  • Sparkle (fire random colors)
  • Fade multiple Led's to a single color
  • Fade multiple Led's to a to complimentary colors

While I could have written the code to handle an array of Led's, I'm only really going to use two for the main dress (run in series of 8 each for the panels of the dress and 2-4 for the hair,) so decided to keep it simple.

Code follows.

Shiftcolors.ino


#include <RGBColor.h>

#include <LED.h>
Led * c2;
Led * c1;
void setup()
{
  c1=new Led(3,5,6);
  c2=new Led(9,10,11);
  Serial.begin(9600);
}

void loop() 
{
  do {
    Serial.println("Flashing");
    RGBFlash(*c1,*c2,100);
    Serial.println("Fading");
  RGBColor * color=new RGBColor();
  shiftTogether(*c1, *c2, *color, random(10,50));
  Serial.println("FadingComplete");
  delay(5000);
  RGBColor * color2=new RGBColor();
  Serial.println("Fading compliments");
  shiftCompliments(*c1,*c2, *color2,30);
  Serial.println("Fading complete");
  delay(5000);
  }
  while (true);
  delay(5000);
  
}


void ShiftRandomColor()
  RGBColor * color=new RGBColor();
  shiftCompliments(*c1,*c2, *color,30);
}

void RGBFlash (Led &led1, Led &led2, int times)
{
    int count=0;
    do {
      RGBColor * color=new RGBColor();
      RGBColor * color2=new RGBColor();
      led1.SetRGB(color->Red(),color->Green(),color->Blue());
      led2.SetRGB(color2->Red(),color2->Green(),color2->Blue());
      
     fireLed(led1);
     fireLed(led2);

      delay(random(30,100));     
            
      count++;
      
    } while (count<times);

}

void shiftTogether (Led &led1, Led &led2, RGBColor color, byte pause)
{
  bool halt=false;
   do {
   if (matchColors(led1,color)==true&&matchColors(led2,color)==true)
    {
      halt=true;
    }
   
     fireLed(led1);
     fireLed(led2);
     
     delay(pause);
     
  } while(halt==false);
}

void shiftCompliments(Led &led1, Led &led2, RGBColor color, byte pause)
{
  RGBColor * color2=new RGBColor(color.ID(),true);
  bool halt=false;
  do {
    if (matchColors(led1,color)==true&&matchColors(led2,*color2)==true)
    {
      halt=true;
    }
     
     fireLed(led1);
     fireLed(led2);
     
     delay(pause);
     
  } while(halt==false);

}

bool matchColors(Led &led,RGBColor &color)
{
  bool r=0;
  bool g=0;
  bool b=0;
  
  if (led.Blue()==color.Blue())
  {
    b=1;
  }
  else {
    if (led.Blue()>color.Blue()) led.SetBlue(led.Blue()-1);
    else led.SetBlue(led.Blue()+1); 
  }
  
  
  if (led.Red()==color.Red())
  {
    r=1;
  }
  else {
    if (led.Red()>color.Red()) led.SetRed(led.Red()-1);
    else led.SetRed(led.Red()+1); 
  }
  
  
  if (led.Green()==color.Green())
  {
    g=1;
  }
  else {
    if (led.Green()>color.Green()) led.SetGreen(led.Green()-1);
    else led.SetGreen(led.Green()+1); 
  }
  if (r==1)
  {
    if (g==1) {
      if (b==1) {
    Serial.print(led.RPin());
    Serial.print(" ");
    Serial.print(led.GPin());
    Serial.print(" ");
    Serial.print(led.BPin());
    Serial.print(" ");
    Serial.print(color.Red());
    Serial.print(",");
    Serial.print(color.Green());
    Serial.print(",");
    Serial.print(color.Blue());
    Serial.print("=");
    Serial.print(led.Red());
    Serial.print(",");
    Serial.print(led.Green());
    Serial.print(",");
    Serial.println(led.Blue());
    return true;
      }
    }
  }
  
  return false;
  
}

void shiftColors(Led &led, RGBColor color, int pause)
{
  
bool halt=0;

  do {
      // fade to black until colors match
    if (matchColors(led,color)==true)
    {
      halt=true;
    }
     
     fireLed(led);
     
     delay(pause);
     
  } while(halt==false);
  
  
}


void fadeLed(Led led, int pause)
{
  // Create a color of 0,0,0 (black)
  RGBColor * color=new RGBColor(0,0,0);
  bool halt=false;
    do {
      // fade to black until colors match
    if (matchColors(led,*color)==true)
    {
      halt=true;
    }
     
     fireLed(led);
     
     delay(pause);
     
  } while(halt==false);

}

void fireLed(Led led)
{
  if (led.IsRGB())
  {
    analogWrite(led.RPin(),led.Red());
    analogWrite(led.GPin(),led.Green());
    analogWrite(led.BPin(),led.Blue());
  }
}

Led.h

#ifndef LED_h
#define LED_h
#include <Arduino.h>
#include <WProgram.h>

/*
  LED.h - Library for standard and RGB LED's
  Beau Bureau, 2014
  Released into the public domain.
*/

class Led {
private:
// sets the colors red, green, and blue, and the RGB pins.  Red is the power pin for standard LED's.
byte red, green, blue, rPin, gPin, bPin;

public:
Led() {};
~Led() {};
// Standard static constructor
Led(byte);
// standard RGB constructor
Led(byte,byte,byte);
// Public members for red, green and blue.
byte Blue() {return blue;}
byte Green() {return green;}
byte Red() {return red;}
//Pins for RGB.  RPin is also the power pin.
byte RPin() {return rPin;}
byte GPin() {return gPin;}
byte BPin() {return bPin;}
// Public member for power.
byte Power() {return rPin;}
// checks whether the bPin has been set to -1.  If it is set to -1 in the constructor, it is not an RGB LED.
bool IsRGB() {return bPin!=255;}
// public methods to set RGB
void SetRed(byte);
void SetGreen(byte);
void SetBlue(byte);
void SetRGB(byte,byte,byte);
// public method to set a random color
void SetRandomColor();
};


#endif


Led.cpp

#include<LED.h>
#include <Arduino.h>
#include <WProgram.h>
Led::Led(byte p) {
  //Initiates a standard LED.  the rPin is power.
  rPin=p;
  // Either g or b can bee tested against to see if this is an RGB.  They will be equal to -1 if a standard RGB.
  gPin=-1;
  bPin=-1;
  red=0;
  green=0;
  blue=0;
}


Led::Led(byte r,byte g,byte b) {
// Initiates an RGB LED, sets color to white. 
rPin=r;
gPin=g;
bPin=b;
red=255;
green=255;
blue=255;
}



void Led::SetRandomColor() {

  // Randomize, choose a color of 0-6. 0=red, 1=green, 2=blue, 3=purple, 4=yellow, 5=orange
  
  int color=random(0,5);

switch (color) {
   case 0: 
   red=255;
   green=0;
   blue=0;
   break;
   case 1:
   green=255;
   red=0;
   blue=0;
   break;
   case 2: 
   blue=255;
   red=0;
   blue=0;
   break;
   case 3:
   red=255;
   blue=255;
   green=0;
   break;
   case 4:
   red=255;
   green=255;
   blue=0;
   break;
   default:
   red=255;
   green=128;
   blue=0;
   break;
 }

}

void Led::SetRGB(byte r, byte g, byte b) {
red=r;
green=g;
blue=b;
}

void Led::SetRed(byte val) {


  red=val;

}

void Led::SetBlue(byte val) {

  blue=val;

}

void Led::SetGreen(byte val) {

  green=val;

}


RGBColor.h


#ifndef RGBColor_h
#define RGBColor_h
#include <Arduino.h>
#include <WProgram.h>

/*
  RGBColor.h - Library for standard and RGB LED's
  Beau Bureau, 2014
  Released into the public domain.
*/

class RGBColor {
private:
// sets the colors red, green, and blue, and the RGB pins.  Red is the power pin for standard LED's.
byte red, green, blue, id, compliment;
void setColors(byte);
void setCompliment();

public:
RGBColor();
~RGBColor(){Serial.println("Destructor called");}
RGBColor(byte);
RGBColor(byte, bool);
RGBColor(byte,byte,byte);
// Standard static constructor
byte Red() {return red;}
byte Blue() {return blue;}
byte Green() {return green;}
byte ID(){return id;}

};


#endif


RGBColor.cpp

#include<RGBColor.h>
#include <Arduino.h>
#include <WProgram.h>

RGBColor::RGBColor() {
      byte input=random(1,9);
setColors(input);
}
RGBColor::RGBColor(byte input) {

setColors(input);
  
}

RGBColor::RGBColor(byte input, bool comp) {
setColors(input);
setCompliment();
  
}

RGBColor::RGBColor(byte r, byte g, byte b) {
  //Initiates a standard LED.  the rPin is power.
  red=r;
  green=g;
  blue=b;
  id=255;
  compliment=255;
}

void RGBColor::setCompliment() {
  setColors(compliment);

}

void RGBColor::setColors(byte input) {
if (input>0&&input<12) {}
else input=random(1,9);
switch (input)
  {
    // red
    case 1:
      red=255;
      green=0;
      blue=0;
      id=1;
      compliment=2;
      break;
    //green
    case 2:
      red=0;
      green=255;
      blue=0;
      id=2;
      compliment=1;
      break;
    // blue
    case 3:
      red=0;
      green=0;
      blue=255;
id=3;
compliment=4;
      break;
    // orange
    case 4:
      red=255;
      green=102;
      blue=0;
id=4;
compliment=3;
      break;
    // crimson
    case 5:
      red=255;
      green=0;
      blue=71;
id=5;
compliment=6;
      break;
   // lemon
    case 6:
      red=255;
      green=255;
      blue=102;
id=6;
compliment=7;
      break; 
   // purple
    case 7:
       red=102;
       green=0;
       blue=204;
id=7;
compliment=6;
       break;
    // Different purple
    case 8:
      red=204;
      green=0;
      blue=102;
id=8;
compliment=6;
      break;
    // Yet another purple
    case 9:
      red=215;
      green=30;
      blue=172;
id=9;
compliment=4;
break;
    case 10:
      red=0;
      green=255;
      blue=255;
id=10;
compliment=11;
      break;
    case 11:
      red=255;
      green=127;
      blue=80;
id=11;
compliment=10;
      break;
  }
}

Saturday, January 31, 2015

Steampunk Light Dress Part Four: Progress Thus Far

A basic video showing the progress of the shift register and 16 LED's.  Have ended up cutting corners and not using the ShiftRegister class in all functions; while being a little bit heavier from a documentation standpoint, I managed to trim about 2000 bytes of pointless variables from the wave and pulse functions.

So  

Sunday, January 11, 2015

Steampunk Light Dress Part Five: Overloading Sparkle()

By dividing my  arrays of LED's into groups, or arrays, I can fire off a wider array of effects.  Take the example below.  I have three arrays of LED arrays:
  • 12X2 single-colored LED's (1-12.) 
  • An array of 2X12 RGB LED's  (A and B.)
  • Another array of 12X2 single-color LED's (13-24)
Using arrays OF arrays of LED's, I can:
  • Chase sequentially from 1-23, ignoring the RGB LED's.
  • Do a ping-pong effect (chasing back and forth across the panel) on 1-12 and 13-23 simultaneously.
  • Fade the RGB LED's, leaving 1-23 off.
  • Fire off every other or every third single-color LED.
Only thing that remains is to overload the functions to take either arrays of LED's or arrays OF arrays of LED's.  Why?  Because I'd like to allow for applications that use fewer LED's (like the parasol,) to still use the functions without getting overly complicated.

(As of yet untested) example code follows:

void sparkle(Led ledList[], int arraySize, long seconds)
{
  // the intial setting of the potentiometer.
  int initVal=analogRead(potPin);
  
Serial.println(seconds);
// Convert the milliseconds to seconds
Serial.println("Going to sparkle for ");
Serial.println(seconds);
Serial.println("MS!");
// Set the count variable (this will track the MS invested in the run and tell the program when to stop.)
 long count=0;
 do
 {
 // Select a random bulb
 int bulb=random(0,arraySize);  
 // Turn it on (if it's RGB, randomize the color)
 fireLed(ledList[bulb], true);
 // The on sensitivity obtained from the static sense pin
 byte onSensitivity=map(analogRead(staticSensePin),0,1023,1,12); 
 // Select a random pause time
 int inPause=random(20*onSensitivity,50*onSensitivity);
 // Add this to the total count time
 count+=inPause;
 // Pause
 delay(inPause);z
 // Turn off the selected bulb
 turnOffLed(ledListarrayNum[bulb]);
 // break if we've gone beyond the time
 if (analogRead(potPin)>high||analogRead(potPin)<low)
 {
   return;
 }
 // Adds a value calculated from the sensitivity pot
 byte sensitivity=map(analogRead(sensePin),0,1023,1,12); 
 // Select a random pause time
 int outPause=random(50*sensitivity,500*sensitivity);
 // Add this to the total count time.
 count+=outPause;
 // Pause
 delay(outPause);
Serial.println(count);
 }
 while ((seconds)>count);
 // Stop once the alloted number of minutes are done.
}


void sparkle(Led ledList[][], int arraySize, byte noOfArrays, long seconds)
{
  // the intial setting of the potentiometer.
  int initVal=analogRead(potPin);
  
Serial.println(seconds);
// Convert the milliseconds to seconds
Serial.println("Going to sparkle for ");
Serial.println(seconds);
Serial.println("MS!");
// Set the count variable (this will track the MS invested in the run and tell the program when to stop.)
 long count=0;
 do
 {
 // Select a random bulb
 int arrayNum=random(0,noOfArrays);
 int bulb=random(0,arraySize);  
 // Turn it on (if it's RGB, randomize the color)
 fireLed(ledList[arrayNum][bulb], true);
 // The on sensitivity obtained from the static sense pin
 byte onSensitivity=map(analogRead(staticSensePin),0,1023,1,12); 
 // Select a random pause time
 int inPause=random(20*onSensitivity,50*onSensitivity);
 // Add this to the total count time
 count+=inPause;
 // Pause
 delay(inPause);z
 // Turn off the selected bulb
 turnOffLed(ledListarrayNum[bulb]);
 // break if we've gone beyond the time
 if (analogRead(potPin)>high||analogRead(potPin)<low)
 {
   return;
 }
 // Adds a value calculated from the sensitivity pot
 byte sensitivity=map(analogRead(sensePin),0,1023,1,12); 
 // Select a random pause time
 int outPause=random(50*sensitivity,500*sensitivity);
 // Add this to the total count time.
 count+=outPause;
 // Pause
 delay(outPause);
Serial.println(count);
 }
 while ((seconds)>count);
 // Stop once the alloted number of minutes are done.
}


Wednesday, January 7, 2015

Steampunk Light Dress Part Four: Using Map() and Constrain() to Calibrate a Sound Sensor



Setting up the  Arduino Compatible Mini Sound Sensor for my Victorian bustle project was a bit of a challenge.  This is not a complaint regarding the device.  The sensor is simplicity itself; hook vcc to your 5V, gnd to ground, and OUT to one of your Arduino's analog inputs. Interpreting those values (which in theory could be as high as 1024, but I've never actually had peak above 400,) in a meaningful way is more of a challenge.

The goal was to get the lights in the bustle gown to pulse to music.  Fans, low level chatter, and other ambient noises are not a part of the music, and as such should be filtered as much as possible.  Determining the ambient noise level is, again, simplicity incarnate; just have it collect a steady sum of incoming values and divide that against the number of samples collected to get a running average.  Collecting a peak level is just as simple; have a global peak variable (initialized to 0.)  If the collected sample is above this peak level, it becomes the new peak level.

So you have your average and your peak values.  To determine how brightly your LED's should fire, all you have to do is determine where your collected value falls between these two values, and map that to a number that's meaningful to your RGB (which accepts numbers between 0 and 254.)  A function called 'map' does just that.  Map takes five arguments: an input value (val below,) the range this value should fall into (two values; valAvg (my average) and globalPeak (my ceiling,) and the range you want to put it into (two values: 0 and 254).

int soundNum=map(val,valAvg,globalPeak,0,254); 

So you've got your calibrated sound value.  Probably.  Problems could occur above if val somehow eluded my range.  Let's say a scandal occurs, the room falls silent for >30ms (an eternity in computer time.)   The sensor pulls a 0.  My average is 5.  As this falls outside the expected input range, ti will also be mapped outside the output range.  The result could be -1, a number my LED's (expecting a range of 0-254) won't care for.

The solution is constrain.  Constrain takes three arguments, your initial value (soundNum below,) a floor (0,) and a ceiling (254.)  

soundNum=constrain(soundNum,0,254);

If, in the above example, soundNum was initially -15, it would be set to 0.  If it was 1024, it would be set to 254.

Beautiful.  We now have something that SHOULD accurately represent a calibrated sound level within the room.  We don't HAVE to trust math, of course.  With a simple adjustment of a steampunk dial, my lovely wife can have some level of manual control over the interpreted input value.  Still, proper calibration makes the whole process easier.

There are still bugs to be worked out.  Feeding the global sum variable (even a long) 1-1024 every ms will eventually break it, resulting in highly questionable results (granted, this would take 9,223,372,036,854,775,807 minutes even with a steady input of peak values.)  I'll likely tell it to stop likely stop pulling the average after 10 minutes or so.

Saturday, January 3, 2015

Fading Like a Flower

There comes a time in each man's life when he questions whether or not RGB LED's absolutely need to be incorporated in all the functions he's programming into his wife's Victorian-era bustle dress.  The answer, in my case at least, is "no, no they don't."

It wasn't an easy decision, of course.  On the one hand, the RGB LED's separate red green and blue lamps can be set independently to mock up just about any color, and you can shift and fade through the spectrum at will.  On the other, each of those lamps consume just as many resources as any standard lamp; eg 30ma and a precious pwm pin (the Uno only has six.)  

Unless you want to add an analog mux to the system (am opting to keep things light and simple at this point,) this means you only get two RGB's per strand.  That is unless I run them in parallel 1, A, 2, B, 3, C, 4 (etc...) fashion (where "A" represents the first RGB, "B" represents the second, and the numbers represent the static LED's in line.) This would give me a potential 9 RGB's per strand+9 standard LED's for a total of 18 per side, or 36 total per strand (there will be 2 strands.)  The only function both would interact in would be 'solid,' where the RGB's could be set to a standard red, green, or blue, maxing out only 1 lamp.

Friday, January 2, 2015

Tesla Coil Umbrella?

After seeing it in a Christmas display, seriously considering a tesla coil design for the lights on the umbrella.  Would be relatively simple... 3-4 rows of LED's, each fired off by one pin.

Steampunk Light Dress Part Three: The Easy Part

Hammered and QA'd the code for keeping the lights steady.  Simple, really; just a for loop that iterates over the all the passed lights (which I established in their own custom class and are passed in the function via an array) and sets them all to on.

Once one of these two things happen:

  •  Given number of seconds (passed to the function as an argument of type long) have passed.
  • The user changes the setting on the main potentiometer (effectively changing the setting.)
The "turnOffAll" function turns off all the lamps and return routes back to the function that called it.

Code follows.  A few values pulled from outside the scope of the function:
  • potPin: the pin of the main potentiometer.  This passes a value from 0 to 1024, and determines which setting the Arduino kicks off.
  • High and Low: the floor and ceiling value range for the current function.  Believe this one runs when the potentiometer is set in the 400-500 range... so if the user sets it below 399 or above 501, they would like the lights to do something different.
 To do:
  • Rename a few of the functions to something more logical
  • More comments

void solid(Led ledList[],int arraySize, long seconds)
{
  // The count increments each time the lights fire.  Once the count exceeds the number of seconds passed, it returns to the main/random loop. 
 long count=0;
// Stores the initial value of the Main Pot.
  int initVal=analogRead(potPin);
// This is our loop.  It runs while both the 
  do {
    for (int thisPin = 0; thisPin < arraySize; thisPin++)  {
        if (ledList[thisPin].IsRGB())
        {
        fireLed(ledList[thisPin],true);
        }
        else {
        digitalWrite(ledList[thisPin].RPin(), HIGH); 
        }
        // Reads the Main Pot.  If the user has set the potentiometer outside the range of the current function (represented by high and low,) set the count to seconds, breaking to do/while loop.
       if (analogRead(potPin)<low||analogRead(potPin)>high)
       {
         // Set the count to seconds.  Once count is iterated, the do/while loop stops. 
         count=seconds;
       }
       count=count+50;
 }
delay(50);
while (count<seconds);
  turnOffAll(ledList,arraySize);
  return;
}

void turnOffAll(Led ledList[], int arraySize)
{
    for (int i=0; i<arraySize;i++)
  {
    turnOffLed(ledList[i]);
  }

}

// Note: the random parameter determines whether or not the LED's color is randomized (false leaves it set at the current color.)
void fireLed(Led led, bool rand)
{
  // Randomize the color
  if (rand&&(led.IsRGB()))
  {
    led.SetRandomColor();
    led.SetRed(255);
    Serial.println("setting random color");


  }

      // Fire red, green, then blue
      analogWrite(led.RPin(),led.Red());
      analogWrite(led.GPin(),led.Green());
      analogWrite(led.BPin(),led.Blue());
      }
      else
      {
      digitalWrite(led.RPin(),HIGH);
      }
}

void turnOffLed(Led led)
{
      if (led.IsRGB())
      {
      // If it's an RGB, turn off red, green, then blue
      analogWrite(led.RPin(),0);
      analogWrite(led.GPin(),0);
      analogWrite(led.BPin(),0);
      }
      else
      {
        digitalWrite(led.RPin(),LOW);
      }

}

Thursday, January 1, 2015

Steampunk Light Dress Part Two: Let there be Sparkles

Hammered out (and tested) a function to make the lights sparkle.  The general idea is:

  • Accept an array of the custom Led class, the size of the array, and the number of seconds the function is to be executed.
  • Select a random bulb
  • If it's an LED bulb, set it to a random color.
  • Light the bulb for a random period of time modified by the static sensitivity pot, which is mapped from x1 to x12.
  •  Verify that the wearer has not changed the settings potentiometer.  If they have, return to the main loop to run another function.
  • Turn off the bulb for a random period of time modified per above on the sensitivity pot.
  • Track the total number of seconds paused.  If more than the number of seconds passed, return to the main loop.
The idea is that the "bursts" should be brief in comparison to the pauses, and both should randomize between long and short, giving it a very random, "sparkling" appearance.

The code follows.  Note that it relies upon the following global variables set outside the function scope:
  •  potPin, Sensepin, Staticsensepin: constants referring to the pin #'s of the setting potentiometer(the dial that tells the Arduino what function to run,) the sensitivity potentiometer (the dial that, in our music application, tells it how much gain to add to the sound sensor's analog signal,) and the static sensitivity potentiometer (the dial that tells the music program how sensitive the static (non RGB) LED's should be.)
  • fireLed, turnOffLed: functions to fire and turn off the LED.
  • High, Low: The floor and ceiling values for the setting potentiometer.  If the potentiometer changes beyond these bounds it means that the user wants to go to another function.


  void sparkle(Led ledList[], int arraySize, long seconds)
{
  // the intial setting of the Settings potentiometer.
  int initVal=analogRead(potPin);
  
// Set the count variable (this will track the MS invested in the run and tell the program when to stop.)
 long count=0;
 do
 {
 // Select a random bulb
 int bulb=random(arraySize);  
 // Turn it on (if it's RGB, randomize the color)
 fireLed(ledList[bulb], true);
 // The on sensitivity obtained from the static sense pin
 byte onSensitivity=map(analogRead(staticSensePin),0,1023,1,12); 
 // Select a random pause time
 int inPause=random(20*onSensitivity,50*onSensitivity);
 // Add this to the total count time
 count+=inPause;
 // Pause
 delay(inPause);
 // Turn off the selected bulb
 turnOffLed(ledList[bulb]);
 // break if we've gone beyond the time
 if (analogRead(potPin)>high||analogRead(potPin)<low)
 {
   return;
 }
 // Adds a value calculated from the sensitivity pot
 byte sensitivity=map(analogRead(sensePin),0,1023,1,12); 
 // Select a random pause time

 int outPause=random(50*sensitivity,500*sensitivity);
 // Add this to the total count time.
 count+=outPause;
 // Pause
 delay(outPause);
Serial.println(count);
 }
 while ((seconds)>count);
 // Stop once the alloted number of minutes are done.
}