Wednesday, December 14, 2011

Arduino Mood Light Controller v3

I finally go some time and some inspiration to update the source code of my Arduino Mood Light Controller. I'll just try to keep it short ...

Code cleanup:
All the light modes have been moved to separate functions.
Replaced a couple of "If, then..." with "Switch, Case", makes the code somewhat easier to read.

New features:
Added two light modes - cycleColor and lightMyFire.
Speed of pulsateColor and cycleColor now controlled via potentiometer.





Download the source code here.
Source code formatted for blogger by: formatmysourcecode.blogspot.com

/* 
  RGB LED controller
  4 modes: off, color select, color pulse and random cycle/pulse
  By Markus Ulfberg 2009-05-19
  
  Updated to Version 2 - 2010-01-13 (Not publicly released)
  Updated to Version 3 - 2011-12-14

  Thanks to: Ladyada, Tom Igoe and 
  everyone at the Arduino forum for excellent 
  tutorials and everyday help. 

  TODO: 
  1. Use millis for debounce instead of delay. 

*/

// set the ledPins
int ledRed = 10;
int ledGreen = 9;
int ledBlue = 11;

// color selector pin
int potPin = 1;
 
// lightMode selector
int switchPin = 2;

// light mode variable
// initial value 0 = off
int lightMode = 0;

// LED Power variables
byte redPwr = 0;
byte greenPwr = 0;
byte bluePwr = 0;

// Variables for lightMode 2
// variables for keeping pulse color
byte redPulse;
byte greenPulse;
byte bluePulse;
int pulseSpeed; 

// Set pulse to down initially
byte pulse = 0;

// floating variables needed to be able to pulse a fixed color 
float redFloat;
float greenFloat;
float blueFloat;

// the amount R,G & B should step up/down to display an fixed color
float redKoff;
float greenKoff;
float blueKoff;

// Variables for lightMode 3
// set the initial random colors
byte redNew = random(255);
byte greenNew = random(255);
byte blueNew = random(255);

// Variables for cycleColor
int truColor = 0;

// misc interface variables
// potVal store the value of the potentiometer for various needs 
int potVal;
// value from the button (debounce)
int switchVal;
int switchVal2;
// buttonState registers if the button has changed
int buttonState;

void setup()
{
  pinMode(ledRed, OUTPUT);
  pinMode(ledGreen, OUTPUT);
  pinMode(ledBlue, OUTPUT);
  
  pinMode(potPin, INPUT);
  
  pinMode(switchPin, INPUT);
  buttonState = digitalRead(switchPin); 
  
  // serial for debugging purposes only
  Serial.begin(9600);
}

void loop()
{
  switchVal = digitalRead(switchPin);      // read input value and store it in val
  delay(10);                         // 10 milliseconds is a good amount of time
    
  switchVal2 = digitalRead(switchPin);     // read the input again to check for bounces
  if (switchVal == switchVal2) {                 // make sure we got 2 consistant readings!
    if (switchVal != buttonState) {          // the button state has changed!
      if (switchVal == LOW) {                // check if the button is pressed
        switch (lightMode) {          // light is off
          case 0:
            lightMode = 1;           // light is on and responds to pot
            break;  
          case 1:
            lightMode = 2;           // light pulsates in the latest color from pot
            break;  
          case 2:     
            lightMode = 3;           // light cycles thru colors
            break;
          case 3:
            lightMode = 4;           // light changes randomly
            break;
          case 4:
            lightMode = 5;           // simulated fire
            break;  
          case 5:     
            lightMode = 0;             // light is off        
            break;  
        } // END switch (lightMode)    
      } // END if (switchVal == LOW)
    } // END if (switchVal != buttonState) 
      
    buttonState = switchVal;                 // save the new state in our variable
  } // END if (switchVal == switchVal2)

  /*
  // Debug
  Serial.print("lightMode: ");
  Serial.println(lightMode);
  */
  
  switch (lightMode) {
    case 0:
      lightsOff();
      break;
    case 1:
      colorControl();
      break;
    case 2:
      pulsateColor();
      break;
    case 3: 
      cycleColor();
      break;
    case 4:
      randomColor();
      break;
    case 5:
      lightMyFire();
      break;  
  }

} // END loop()


// lightMode 0
void lightsOff() {
  redPwr = 0;
  greenPwr = 0;
  bluePwr = 0;
  colorDisplay();
}

// lightMode 1 
void colorControl() {

   // read the potentiometer position
   potVal = analogRead(potPin); 
 
  // RED > ORANGE > YELLOW
   if (potVal > 0 && potVal < 170) {
     redPwr = 255;
     bluePwr = 0;
     greenPwr = map(potVal, 0, 170, 0, 255);
   }
 
   // YELLOW > LIME?? > GREEN 
   if (potVal > 170 && potVal < 341) {
     greenPwr = 255;
     bluePwr = 0;
     redPwr = map(potVal, 341, 170, 0, 255);
   }

    // GREEN > TURQOUISE
    if (potVal > 341 && potVal < 511) {
      greenPwr = 255;
      redPwr = 0;
      bluePwr = map(potVal, 341, 511, 0, 255);
    }
 
   // TURQOUISE > BLUE  
   if (potVal > 511 && potVal < 682) {
     bluePwr = 255;
     redPwr = 0;
     greenPwr = map(potVal, 682, 511, 0, 255);
   }
 
   // BLUE > PURPLE 
   if (potVal > 682 && potVal < 852) {
     bluePwr = 255;
     greenPwr = 0;
     redPwr = map(potVal, 682, 852, 0, 255);
   }
 
   // PURPLE > RED
   if (potVal > 852 && potVal < 1023) {
     redPwr = 255;
     greenPwr = 0;
     bluePwr = map(potVal, 1023, 852, 0, 255);
   } 
   
   redFloat = float(redPwr);
   greenFloat = float(greenPwr);
   blueFloat = float(bluePwr);
   
   redKoff = redFloat / 255;
   greenKoff = greenFloat / 255;
   blueKoff = blueFloat / 255;
   
   redPulse = redPwr;
   greenPulse = greenPwr;
   bluePulse = bluePwr; 
   
  /*
  // Debug 
  Serial.print("redFLoat: ");
  Serial.print(redFloat, DEC);
  Serial.print(" redPwr: ");
  Serial.print(redPwr, DEC);
  Serial.print(" greenFloat: ");
  Serial.print(greenFloat, DEC);
  Serial.print(" greenPwr: ");
  Serial.print(greenPwr, DEC);
  Serial.print(" blueFloat: ");
  Serial.print(blueFloat, DEC);
  Serial.print(" bluePwr: ");
  Serial.println(bluePwr, DEC);
  // End debug
  */
  // Display colors 
  colorDisplay();
}        

// lightMode 2
void pulsateColor() {
  
    // get colors from colorControl
    redPwr = int(redFloat);
    greenPwr = int(greenFloat);
    bluePwr = int(blueFloat);
      
    // Read speed from potentiometer 
    pulseSpeed = analogRead(potPin); 
    pulseSpeed = map(pulseSpeed, 0, 1023, 0, 255);
  
    //display the colors
    colorDisplay();
    
    // set speed of change
    delay(pulseSpeed);
    
    // pulse down
    if (pulse == 0) {
      if (redFloat > 10) {
        redFloat = redFloat - redKoff;
      } 
      if (greenFloat > 10) {
        greenFloat = greenFloat - greenKoff;
      } 
      if (blueFloat > 10) {
        blueFloat = blueFloat - blueKoff;
      } 

    // If all xFloat match 10 get pulse up
    if (byte(redFloat) <= 10) {
     if (byte(greenFloat) <= 10) {
      if (byte(blueFloat) <= 10) {
       pulse = 1;
      }
     }
    }
  }
  // Pulse up
  if (pulse == 1) {
    if (redFloat < redPulse) {
      redFloat = redFloat + redKoff;
    } 
    if (greenFloat < greenPulse) {
      greenFloat = greenFloat + greenKoff;
    } 
    if (blueFloat < bluePulse) {
      blueFloat = blueFloat + blueKoff;
    }
   // If all Pwr match Pulse get pulse down
  
    if (byte(redFloat) == redPulse) {
     if (byte(greenFloat) == greenPulse) {
      if (byte(blueFloat) == bluePulse) {
       pulse = 0;
      }
     }
    }
  }
  
  /*
  // Debug 
  Serial.print("redFloat: ");
  Serial.print(redFloat, DEC);
  Serial.print(" redPulse: ");
  Serial.print(redPulse, DEC);
  Serial.print(" greenFloat: ");
  Serial.print(greenFloat, DEC);
  Serial.print(" greenPulse: ");
  Serial.print(greenPulse, DEC);
  Serial.print(" blueFloat: ");
  Serial.print(blueFloat, DEC);
  Serial.print(" bluePulse: ");
  Serial.print(bluePulse, DEC);
  Serial.print(" pulse: ");
  Serial.println(pulse, DEC);
  // End debug
  */
  
} // pulsateColor END 

// lightMode 3
void cycleColor() {    // Cycles through colors

  switch(truColor) {
  // RED > ORANGE > YELLOW   
   case 0:
     redPwr = 255;
     bluePwr = 0;
     greenPwr++;
     if (greenPwr > 254) {
       truColor = 1;
     }
     break;
   
   // YELLOW > LIME?? > GREEN 
   case 1:
     greenPwr = 255;
     bluePwr = 0;
     redPwr--;
     if (redPwr < 1) {
       truColor = 2;
     }
     break;

   // GREEN > TURQOUISE
   case 2:
     greenPwr = 255;
     bluePwr++;
     redPwr = 0;
     if (bluePwr > 254) {
       truColor = 3;
     }   
    break;
    
   // TURQOUISE > BLUE  
   case 3:
     greenPwr--;
     bluePwr = 255;
     redPwr = 0;
     if (greenPwr < 1) {
       truColor = 4;
     }
     break;
     
   // BLUE > PURPLE 
   case 4:
     greenPwr = 0;
     bluePwr = 255;
     redPwr++;
     if (redPwr > 254) {
       truColor = 5;
     }
     break;
     
   // PURPLE > RED
   case 5:
     greenPwr = 0;
     bluePwr--;
     redPwr = 255;
     if (bluePwr < 1) {
       truColor = 0;
     }   
     break;
 }
  // START SPEED 
  pulseSpeed = analogRead(potPin); 
  pulseSpeed = map(pulseSpeed, 0, 1023, 0, 255);
  
  //display the colors
  colorDisplay();
  // set speed of change
  delay(pulseSpeed);
  // END SPEED
  
}  // END cycleColor 


// lightMode 4 
void randomColor() {     // randomize colorNew and step colorPwr to it
                          
  if (redPwr > redNew) {
    redPwr--;
  } 
  if (redPwr < redNew) {
    redPwr++;
  }
  if (greenPwr > greenNew) {
    greenPwr--;
  } 
  if (greenPwr < greenNew) {
    greenPwr++;
  }
  if (bluePwr > blueNew) {
    bluePwr--;
  } 
  if (bluePwr < blueNew) {
    bluePwr++;
  }

// If all Pwr match New get new colors
  
  if (redPwr == redNew) {
   if (greenPwr == greenNew) {
    if (bluePwr == blueNew) {
     redNew = random(254);
     greenNew = random(254);
     blueNew = random(254);
    }
   }
  }
  
  // display the colors
  colorDisplay();
  // Set speed of change
  delay(20);

} // END randomColor 

// lightMode 5
void lightMyFire() {
  
  // Flicker will determine how often a fast flare will occur
  int flicker;

  // set flicker randomness
  flicker = random(800); 

  // Set random colors, 
  // constrain green to red and blue to green
  // in order to stay within a red, blue, white spectrum
  redPwr = random(220, 240);
  greenPwr = random(180, 200);
  // when flicker occur, the colors shine brighter
  // adding blue creates a white shine 
  if (flicker > 750) {
    redPwr = 254;
    greenPwr = random(200, 230); 
    bluePwr = random(0, 50);    
  } else {
    bluePwr = 0;
  }
  
  // display Colors
  colorDisplay();
  
  // Set speed of fire
  delay(20);  

} // END lightMyFire

// Displays the colors when called from other functions
void colorDisplay() {
  analogWrite(ledRed, redPwr);
  analogWrite(ledGreen, greenPwr);
  analogWrite(ledBlue, bluePwr);
}