Go Down

Topic: Hue-controllable RGB LED lamp (Read 54233 times) previous topic - next topic


I'm trying to do something similar, but instead of a pot, I'm using three Ping))) ultrasonic rangefinders to control fade my LED's. I'm trying to use that map command to get the distance data turned into 0-255 values. Haven't quite got it yet...


I have used your code and get the colors to adjust based on a potentiometer input. There is one thing I observed I do not seem to see any blues. I see green, pinks, reds yellow but do not get a good blue. Any ideas why this seems to be the case.


excellent algorithm :))) i think is good when read 0 from pot to put all colors off /switch off/ and if the pot value is max 1023 to fire all the leds /white/ this will cover this missing part  ::)


ONe can also do the RGB LED control using a mouse x and y position feed from Processing, I think Its the Firmata libary , It efectively changes the Rduino platform inti a data IO device over serial, This is plent useful for pc based control


When you output an PWM value between 0 and 255, it's not even remotely similar to the same RGB value.  The problem is that the LED brightness does not climb linearly with the PWM duty cycle.  If you go from 1 to 2, there's a huge jump in brightness while if you go from 100 to 200 there's almost no discernable change.  Quite often just to save power, I'll PWM my LEDs at about 20% duty cycle and it looks almost the same as full brightness.  I've been considering a similar project for a while but because this issue I was looking at only having 10 possible brightness levels for each colour and then using empirical observation to convert those values to PWM levels.

Also, as far as your map function...Why aren't you just using
Code: [Select]

r = 255 - r;
g = 255 - g;
b = 255 - b;


Jul 22, 2009, 02:06 am Last Edit: Jul 22, 2009, 02:07 am by lqbert Reason: 1

I'm using the TLC5940 PWM LED driver.  No multiplexing... the rows are identical outputs.  This is done with some nested loops and some trig (sine wave conversion).  

I'm sure I could have a potentiometer control 1 or more of the variables used in the loops above to either fade the matrix to a specific color or just take the scrolling part out of it and have the potentiometer just send static values to be used for the color calculation.


Aug 23, 2009, 04:16 am Last Edit: Aug 23, 2009, 04:29 am by DeFex Reason: 1
I would also like to thank you i have used the fade function to test RGB leds in my first little project. it picks random amounts for RGB and fades between them at also a random speed, its like a full color candle :)

eventually what i want to make is a lamp which changes color according to barometric pressure, average ambient noise level, temperature, and other environmental inputs. so this would be perfect.

I just got the arduino for a particular musical instrument project (but im having way too much fun with it)


Hey Peoples,

I Have implemented this code in a project and it works great. I am using a 10k pot and it gives me all the range of color I need.

I wanted to use a flex sensor (variable resistor) to control hue. However when I plugged it into the circuit it doesn't give me the same range I am only getting about half. I know that it is because the flex sensor has a different range of ohms. The flex sensor has a range of about 11k - 40k ohms. Since the flex sensor only has 2 pins I am using a 10K resistor in between on of the pins and ground. I have tried fooling around with some numbers in the code, but not with any luck. I know there are some ways to connect supplemental resistors in parallel to change values, but I am a bit confused.

Is there a way to do what I want with the flex sensor I have and is it a hardware problem or a program problem?

Any help would be greatly appreciated...



I thought up a different value -> RGB formula a couple of years ago when I dabbled a little in Milkdrop. While it isn't perfect, it worked pretty well imho. (I needed it for a lightbeam that splits up into different colors, for a "Dark Side of the Moon" animation: http://raron.deviantart.com/art/Dark-Side-of-the-Moon-54658436) Here, yellow is the worst represented color (although it is present - barely.)

This is what I came up with:
R = 0.5 + 0.5 * cos((value+0.125) * 2 * PI)
G = 0.5 + 0.5 * cos((value+0.375) * 2 * PI)
B = 0.5 + 0.5 * cos (value * PI)

Where value is from 0 to 1, as is the returned RGB values in this case.

As stated, not perfect (could be more tweaking fixes it, but I kind of liked the formulas too  ::) ), it doesn't give quite clean colors.

I had to test it on my arduino with a common-anode RGB LED of course. Unfortunately it didn't turn up too well. Here, it is  the green which is the worst, and also the yellow... so yeah not perfect at all. I just wanted my say in the matter :D Although the original HSV formula is much better (I presume, I haven't tested it yet but I'm pretty sure it is).

Anyway, this sums up my RGB test sketch:
Code: [Select]

const int ledRed = 9;
const int ledGreen = 10;
const int ledBlue = 11;

double redLevel;
double greenLevel;
double blueLevel;

void setup()
pinMode(ledRed, OUTPUT);
pinMode(ledGreen, OUTPUT);
pinMode(ledBlue, OUTPUT);

void loop()
   int value = analogRead(analogPin);
   double RGBslider = (double)value/1024.0;
   redLevel   = 128.0 * ( 1 + cos( 2 * PI * (RGBslider + 0.125)));
   greenLevel = 128.0 * ( 1 + cos( 2 * PI * (RGBslider + 0.375)));
   blueLevel  = 128.0 * ( 1 + cos( PI * RGBslider));
   if (redLevel > 255) redLevel = 255;
   if (redLevel < 0) redLevel = 0;
   if (greenLevel > 255) greenLevel = 255;
   if (greenLevel < 0) greenLevel = 0;
   if (blueLevel > 255) blueLevel = 255;
   if (blueLevel < 0) blueLevel = 0;
   analogWrite(ledRed, 255 - ((byte)redLevel)); // negating the output for common anode (sinking)
   analogWrite(ledGreen, 255 - ((byte)greenLevel));
   analogWrite(ledBlue, 255 - ((byte)blueLevel));


Well RGB LED's are fun, so I've been playing with one of those lately. I got one sitting on a breadboard at the moment, lighting up a crystal above it. It looks quite nice cycling colors in various modes, and will be a little desklamp thingy soon :)

Anyway, now I've tried OP's algorithm, which of course worked much better then my previous one (though mine is more of a rainbow spectrum, or at least it was supposed to be, and this one is a color wheel starting and ending in red).

But I also wanted to adjust  the light/dark-ness of it. However I could simply not get the HSL -> RGB algorithm to work, from this page: http://www.easyrgb.com/index.php?X=MATH&H=19#text19

So I modifyed the HSV -> RGB function instead, making it into a sort of HSVL -> RGB function. Though V is not an argument, it is made dependent of the float variable "L".  I just added a little snippet for lightness (the L float variable, from 0 to 1).

So when the argument L=0.5, the colors are fully saturated, like before. Less than 0.5 and they are darker, above and they are linearly more white until L=1 = white.

Of course, for the color to be as white as possible, one would have to balance the current limiting resistors to the R,G and B portion of the LED.

Anyway, if anyone is interested this is the (slightly) modified function.
Code: [Select]
void hsvl2rgb(float H, float L, int& R, int& G, int& B)
 int var_i;
 float S=1, V, lightness, var_1, var_2, var_3, var_h, var_r, var_g, var_b;

 V = L * 2;                         // For the "darkness" of the LED
 if ( V > 1 ) V = 1;

 if ( S == 0 )                      //HSV values = 0 ÷ 1
   R = V * 255;
   G = V * 255;
   B = V * 255;
   var_h = H * 6;
   if ( var_h == 6 ) var_h = 0;  //H must be < 1
   var_i = int( var_h ) ;            //Or ... var_i = floor( var_h )
   var_1 = V * ( 1 - S );
   var_2 = V * ( 1 - S * ( var_h - var_i ) );
   var_3 = V * ( 1 - S * ( 1 - ( var_h - var_i ) ) );

   if ( var_i == 0 ) {
     var_r = V     ;
     var_g = var_3 ;
     var_b = var_1 ;
   else if ( var_i == 1 ) {
     var_r = var_2 ;
     var_g = V     ;
     var_b = var_1 ;
   else if ( var_i == 2 ) {
     var_r = var_1 ;
     var_g = V     ;
     var_b = var_3 ;
   else if ( var_i == 3 ) {
     var_r = var_1 ;
     var_g = var_2 ;
     var_b = V     ;
   else if ( var_i == 4 ) {
     var_r = var_3 ;
     var_g = var_1 ;
     var_b = V     ;
   else {
     var_r = V     ;
     var_g = var_1 ;
     var_b = var_2 ;

   if ( L > 0.5 )         // Adjusting the Lightness (whiteness)
     lightness = ( L - 0.5 ) / 0.5;
     var_r += ( lightness * ( 1 - var_r ) );
     var_g += ( lightness * ( 1 - var_g ) );
     var_b += ( lightness * ( 1 - var_b ) );

   R = (1-var_r) * 255;     // RGB results = 0 ÷ 255. Reversed for common anode RGB LED's
   G = (1-var_g) * 255;
   B = (1-var_b) * 255;


I too must thank the original thread creator, and all the contributors of this thread as It greatly helped in my first arduino 'project', which has a HSV loop and various other RGB LED controls controlled through serial and a python front end.



Thanks to all the contributors in this thread for helping me get a quick prototype RGB control circuit up and running. When it's late at night and you're working on hardware the last thing you want to do is reinvent the wheel in code!


just wanted to say thanks, im using this code to run a RGB backlight to a lcd thats howing my computer stats :D

Go Up