January 15, 2011

Arduino RGB LED HSV "Color Wheel"

Recently I've been playing with Arduino, Scratch and the 3pi robot for a personal project that I hope will be interesting enough to show soon. (I've got a lot of motivation from these guys specially the little one with big eyes).

To start I made this little example of a RGB Led. Usually you begin making a loop through the RGB scale of colors. But it doesn't look very natural since you expect to loop through a color hue. What you need is to convert a HSV (Hue Saturation Value) scale to RGB (Red Green Blue) scale that the LED support, and then loop through the Hue domain mantaining the Saturation and Value constants.

Circuit is here, look for the RGB LED example

Video:

Code (I've coded it as close as I could to the Arduino sample guidelines):


/*
 * Color Wheel LED
 *
 * Loops a RGB LED attached to pins 9,10,11 through
 * all the "exterior" colors of a Color Wheel
 * 
 * The RGB LED uses a 3 component (red green blue) model which adds light colors to produce 
 * a composite color. But the RGB does not make easy to loop through a more
 * "natural" sequence of colors. The HSV (hue saturation value) model uses a color cylinder
 * in which each color is a point inside the cylinder. 
 * The hue is represented by the angle at which the point is, the saturation represents
 * the length (how close to the center the point is) and the value represent the height at
 * which the point is. 
 *
 * By cycling the hue value from 0 to 360 degrees, and keeping the saturation and value at 1
 * we can represent all the brightest colors of the wheel, in a nice natural sequence.
 *
 * The algorithm to convert a HSV value to a RGB value is taken from Chris Hulbert's blog (splinter)
 *
 * Created 1 January 2011
 * By Eduardo A. Flores Verduzco
 * http://eduardofv.com
 *
 * References:
 * http://en.wikipedia.org/wiki/HSL_and_HSV
 * http://en.wikipedia.org/wiki/Color_wheel
 * http://splinter.com.au/blog/?p=29
 *
 *
 */

void setup() {
  //Set the pins to analog output
  pinMode(9,OUTPUT);
  pinMode(10,OUTPUT);
  pinMode(11,OUTPUT);
}

void loop() {
  //The Hue value will vary from 0 to 360, which represents degrees in the color wheel
  for(int hue=0;hue<360;hue++)
  {
    setLedColorHSV(hue,1,1); //We are using Saturation and Value constant at 1
    delay(10); //each color will be shown for 10 milliseconds
  }
}

//Convert a given HSV (Hue Saturation Value) to RGB(Red Green Blue) and set the led to the color
//  h is hue value, integer between 0 and 360
//  s is saturation value, double between 0 and 1
//  v is value, double between 0 and 1
//http://splinter.com.au/blog/?p=29
void setLedColorHSV(int h, double s, double v) {
  //this is the algorithm to convert from RGB to HSV
  double r=0; 
  double g=0; 
  double b=0;

  double hf=h/60.0;

  int i=(int)floor(h/60.0);
  double f = h/60.0 - i;
  double pv = v * (1 - s);
  double qv = v * (1 - s*f);
  double tv = v * (1 - s * (1 - f));

  switch (i)
  {
  case 0: //rojo dominante
    r = v;
    g = tv;
    b = pv;
    break;
  case 1: //verde
    r = qv;
    g = v;
    b = pv;
    break;
  case 2: 
    r = pv;
    g = v;
    b = tv;
    break;
  case 3: //azul
    r = pv;
    g = qv;
    b = v;
    break;
  case 4:
    r = tv;
    g = pv;
    b = v;
    break;
  case 5: //rojo
    r = v;
    g = pv;
    b = qv;
    break;
  }

  //set each component to a integer value between 0 and 255
  int red=constrain((int)255*r,0,255);
  int green=constrain((int)255*g,0,255);
  int blue=constrain((int)255*b,0,255);

  setLedColor(red,green,blue);
}

//Sets the current color for the RGB LED
void setLedColor(int red, int green, int blue) {
  //Note that we are reducing 1/4 the intensity for the green and blue components because 
  //  the red one is too dim on my LED. You may want to adjust that.
  analogWrite(9,red); //Red pin attached to 9
  analogWrite(10,green/3); //Red pin attached to 9
  analogWrite(11,blue/3); //Red pin attached to 9
}


Comments

fribbe said over 3 years ago
Dear Eduano, for an article on our not commercial website (http://macherzin.net) I am just writing an article about RGB-powered-LEDs: http://macherzin.net/article28-Arduino-LED-RGB-Lampe I would like to include your sketch. the only changes that would be made would be the translation of your comments and a change in the fading time. Of course the credits would be set accordingly. Because I found no remarks about the license of your code I therefore ask for your permission. Looking forward to her from you. Best regards fribbe
eduardofv said over 3 years ago
fribbe, feel free to use the code. I really appreciate the attribution and you taking the time to contact me. Regards.
fribbe said over 3 years ago
Eduarno, thank you very much. Here you can have a look at the result: http://macherzin.net/tiki-read_article.php?articleId=28 all the best fribbe
Andreas Grech said over 3 years ago
Encountered this post while searching for a way of converting HSV to RGB, and I found what I was looking for here. Cheers. Just two minor comments. The correct link to Chris Hulbert's blog post is http://splinter.com.au/converting-hsv-to-rgb-colour-using-c and in setLedColor, the last two comments should be "Green pin attached to 10" and "Blue pin attached to 11".
Mary said over 3 years ago
Hello I am working on the exact same project in school. What I have found out so far is that you convert from HSV to RGB. However, I can't find any explanation on why you have to do this. Hope you can help Regards Mary
Jason Judge said over 2 years ago
I don't suppose you could provide any pointers on what needs to be changed in this algorithm to cycle though the colours of the rainbow? Is it just taking a limited range of the hue (e.g. 0 to 196 rather than 0 to 255)? I am looking at doing this to help with a school project.
Jason Judge said over 2 years ago
I think I have found the answer. The algorithm above implements the one described here: http://en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB Looking at the diagram, the rainbow covers the first 240 degrees of the 360 degree colour wheel. 240/360 * 255 = 170 So cycling the hue from 0 to 170 will take an RGB LED through the complete range of colours in a rainbow, and skip tge extended colours (around Magenta) that the colour wheel includes.

Add Comment

Name 
Your comment 
Enter the verification code
simple_captcha.jpg