Psychedelic Mushroom (wk3)

ian's picture

Description

Create an interesting control of RGB LEDs via 3 potentiometers. After controlling each LED separately from each pot, I decided it would be interesting to try to control Hue, Saturation, and Brightness, then convert to RGB for LED output. I used this code to convert from HSB to RGB. I found the saturation control to be somewhat ineffective, since for better color display, usually amber and white LEDs are used, and this setup only has RGB. I changed the saturation to control strobe, and then added a condition so that the light would blink faster and faster, then become constant, instead of effectively PWMing the signal so it just gets fainter, as in the original code. I used the same diffuser as last week because I like the shape and it is pretty effective at diffusing the colors when the LEDs are pointed correctly towards the center of the inside top of the cap. The final product is a psychedelic mushroom; one pot controls hue, another brightness, and another the blink speed.

Components

  • 3 x 330Ω Resistors
  • R G B LEDs
  • 3x 10kΩ Potentiometers
  • Repurposed bottle stopper diffuser

Arduino Code

 

// Ian Leighton
// TUI 2011-09-14
// Homework 3: Serial RGB LED Pot Dimmer
 
/*
Dims RGB LEDs using 3 pots.
adapted from HSB to RGB & getRGB code by kasperkamperman.com
*/
 
#define huePot 0
#define satPot 1
#define brightPot 2
 
#define redPin 11   // Red LED
#define greenPin 10  // Green LED
#define bluePin 9  // Blue LED
 
#define thresh 100
 
int rB=0; int gB=0; int bB=0;
//int check = 0;
//int oldcheck = 0;
 
int rgb_colors[3]; 
 
int hueVal; int waitVal; int brightVal;
int hue; int saturation; int brightness;
 
/* 
  dim_curve 'lookup table' to compensate for the nonlinearity of human vision.
  Used in the getRGB function on saturation and brightness to make 'dimming' look more natural. 
  Exponential function used to create values below : 
  x from 0 - 255 : y = round(pow( 2.0, x+64/40.0) - 1)   
*/
 
const byte dim_curve[] = {
    0,   1,   1,   2,   2,   2,   2,   2,   2,   3,   3,   3,   3,   3,   3,   3,
    3,   3,   3,   3,   3,   3,   3,   4,   4,   4,   4,   4,   4,   4,   4,   4,
    4,   4,   4,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   6,   6,   6,
    6,   6,   6,   6,   6,   7,   7,   7,   7,   7,   7,   7,   8,   8,   8,   8,
    8,   8,   9,   9,   9,   9,   9,   9,   10,  10,  10,  10,  10,  11,  11,  11,
    11,  11,  12,  12,  12,  12,  12,  13,  13,  13,  13,  14,  14,  14,  14,  15,
    15,  15,  16,  16,  16,  16,  17,  17,  17,  18,  18,  18,  19,  19,  19,  20,
    20,  20,  21,  21,  22,  22,  22,  23,  23,  24,  24,  25,  25,  25,  26,  26,
    27,  27,  28,  28,  29,  29,  30,  30,  31,  32,  32,  33,  33,  34,  35,  35,
    36,  36,  37,  38,  38,  39,  40,  40,  41,  42,  43,  43,  44,  45,  46,  47,
    48,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,
    63,  64,  65,  66,  68,  69,  70,  71,  73,  74,  75,  76,  78,  79,  81,  82,
    83,  85,  86,  88,  90,  91,  93,  94,  96,  98,  99,  101, 103, 105, 107, 109,
    110, 112, 114, 116, 118, 121, 123, 125, 127, 129, 132, 134, 136, 139, 141, 144,
    146, 149, 151, 154, 157, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 190,
    193, 196, 200, 203, 207, 211, 214, 218, 222, 226, 230, 234, 238, 242, 248, 255,
};
 
void setup() {
  pinMode(redPin,   OUTPUT);   // sets the pins as output
  pinMode(greenPin, OUTPUT);   
  pinMode(bluePin,  OUTPUT);
  Serial.begin(9600);
  analogWrite(redPin,   0); 
  analogWrite(greenPin, 0); 
  analogWrite(bluePin,  0);
}
 
void loop () {
  hueVal = analogRead(huePot);
  waitVal = analogRead(satPot);
  brightVal = analogRead(brightPot);
  
  hue        = map(hueVal,0, 1023,0, 359);     // hue is a number between 0 and 360
  saturation = 255;                               // saturation is a number between 0 - 255
  brightness = map(brightVal,0, 1023, 0, 255);                           // value is a number between 0 - 255
  
  getRGB(hue,saturation,brightness,rgb_colors);
  
//  check = rB + gB + bB;
//  if (abs(check - oldcheck) > thresh) {
//    Serial.print(rB);
//    Serial.print(gB);
//    Serial.println(bB); }
    
  analogWrite(redPin, rgb_colors[0]);            // red value in index 0 of rgb_colors array
  analogWrite(greenPin, rgb_colors[1]);            // green value in index 1 of rgb_colors array
  analogWrite(bluePin, rgb_colors[2]);            // blue value in index 2 of rgb_colors array
 
  if (waitVal > 8) {
    // strobe it, why not?
    delay(waitVal);
    analogWrite(redPin, 0);
    analogWrite(greenPin,0);
    analogWrite(bluePin,0);
    delay(waitVal); }
}
 
 
 
 
// getRGB Code from kasperkamperman.com
 
void getRGB(int hue, int sat, int val, int colors[3]) { 
  /* convert hue, saturation and brightness ( HSB/HSV ) to RGB
     The dim_curve is used only on brightness/value and on saturation (inverted).
     This looks the most natural.      
  */
 
  val = dim_curve[val];
  sat = 255-dim_curve[255-sat];
 
  int r;
  int g;
  int b;
  int base;
 
  if (sat == 0) { // Acromatic color (gray). Hue doesn't mind.
    colors[0]=val;
    colors[1]=val;
    colors[2]=val;  
  } else  { 
 
    base = ((255 - sat) * val)>>8;
 
    switch(hue/60) {
    case 0:
        r = val;
        g = (((val-base)*hue)/60)+base;
        b = base;
    break;
 
    case 1:
        r = (((val-base)*(60-(hue%60)))/60)+base;
        g = val;
        b = base;
    break;
 
    case 2:
        r = base;
        g = val;
        b = (((val-base)*(hue%60))/60)+base;
    break;
 
    case 3:
        r = base;
        g = (((val-base)*(60-(hue%60)))/60)+base;
        b = val;
    break;
 
    case 4:
        r = (((val-base)*(hue%60))/60)+base;
        g = base;
        b = val;
    break;
 
    case 5:
        r = val;
        g = base;
        b = (((val-base)*(60-(hue%60)))/60)+base;
    break;
    }
 
    colors[0]=r;
    colors[1]=g;
    colors[2]=b; 
  }   
}

 

 

wiring close up
setup
0
Your rating: None