Author Options:

Looking for an RGB color table, constant intensity? Answered

Hi, looking for a constant intensity RGB color table to use with a RGB LED.

In R, I'd generate a color sequence like this:
p=colorRampPalette(c("blue","cyan","green","yellow","red"))(255);data=data.frame(red=substr(gsub("#","",p),1,2),green=substr(gsub("#","",p),3,4),blue=substr(gsub("#","",p),4,5));for(j in names(data))for(i in 1:nrow(data)){data[i,j]=eval(parse(text=paste("0x",data[i,j],sep="")))};for(i in names(data))data[,i]=as.numeric(data[,i]);data$c="";for(i in 1:nrow(data))data[i,"c"]=sprintf("%03d%03d%03d",data[i,]$red,data[i,]$green,data[i,]$blue);paste(data$c,collapse="', '")

giving me:
000000015', '000004079', '000008143', '000012207', '000016015', '000020079', '000024143', '000028207', '000032015', '000036079', '000040143', '000044207', '000048015', '000052079', '000056143', '000060207', '000064015', '000068079', '000072143', '000076207', '000080015', '000084079', '000088143',.....

which gives me a sequence of 255 RBG ( 1-255 values).

The problem is when I put that to my LED, I do get sort of the intended sequence of color, but as I am driving the LED color via PWM, I see a huge change in intensity as well as the color.

Does anyone know how to create a constant intensity palette for PWM use? Do I need to work with HSV then transform back? Is there a nice existing library (R or arduino) that'll give me the values?


Putting aside the intensity question, part of the problem is that generating a typical "rainbow" of perceived colors, where blue/violet is cold and red is hot, maps to RGB in a fairly complicated way.

If you want violet (R+B) to be coldest, then blue, then green, yellow (R+G), orange (2R+G), red, you need to run the intensities something like this:

R: 1 . . - . . 0 . . . . . 0 . . - . . 1 . . 1
G: 0 . . . . . 0 . . - . . 1 . . - . . - . . 0
B: 1 . . . . . 1 . . - . . 0 . . . . . . . . 0

where I'm using "-" to mean 50%.

Once you've got the relative proportions, then you need to do some overall scaling of each color to make the intensities consistent to the eye (in particular, scale down the green relative to the other colors, as Steve mentioned).

Doing this "correctly" is a fairly complicated job, and is different for pigments than for LEDs. A Google search for color temperature chart may give you some help in fabricating a solution.

You'll see a huge change in intensity because of the photopic sensitivity of the human eye - we don't see red and deep blues anything like as well as green,

Like Steve said constant intensity to a PV cell, a vid camera or your eye.

Whichever you decide, the eye will be the hardest to achieve.

You need to study tri-stimulis color of food theory. 


5 years ago

So what microprocessor do you use ?

Rather then tables,
  1. Set up two delay counters Blue and Red.
  2. load 90 into blue-on and 10 into blue-off or red on. 
  3. simple takea blue bit away and a bit to the red.
  4. Count down 89 x 10us and blue off turn red on for 11 x 10us
  5. Decrement a big loop counter
  6. Test for big loop zero and B ==> R shift Step_3
  7. Now red off and blue on  as Step_4

  • start with blue 90%PWM on
  • then start red 10% PWM on
  • Next add a pulse to red and take away a blue pulse
  • continue until red is 90%PWM on and blue is 10% PWM on
  • play with the big loop timing between cycles to taste.

That is how I blend RgB


This is on an arduino mega, but only because the rest of the project is.

I have no problem making a specific colour, but fading between two colours while maintaining the same intensity is what is giving me difficulty.

I found this: http://arduino.cc/forum/index.php?PHPSESSID=012d0d65de70a9e4747f6ab5ad5a3518&topic=8320.msg66886#msg66886 excellent code for HSV transforms for arduino, so as long as you're going between two points on the H spectrum it does wonders, but for two arbitrary colours, it won't help (eg fade magenta to green).

ah sorry, I see what you're doing, and that's more compact than the HSV code, and yeah that'd work, but again only for certain gradients (I think?).

You goto play with it and save your trial code.
I have found some very neat color accidents
trying for one effect and discovered better:-D

You need to be logarithmic -
The first 10% will appear as about 40% total intensity
output 50% will be about 90% visible intensity
The last 50% will be the last 90-100% intensity.

Your eye iris will close as it gets brighter, making everything after 'perceived' seem the same brightness.

I have an arduino sketch I wrote that puts 255 'constant' brightness rainbow values into an array, then you reference that array later for values (lookup is faster than doing the math in my application). I can post code later when I boot up my laptop.

Tricky to calculate, as red, green and blue LEDs have widely varying intensities for the same current.  The eye's sensitivity to each colour also comes into play.
When I was making a PWM driven RGB circuit I used 3 different series resistors to produce white at 255 setting.  Values lower than 255 then gave a pretty good intensity match.  I think I've still got the circuit made up, but can't check now.  I'll tell you the values I used tomorrow if you're interested in this approach. (Mine was a Picaxe rather than Arduino, but the principle's the same.)

Yeah, I can get decent white. I'm somewhat familiar with the concepts of CIE and luminosity.

It is generating an arbitrary gradient that is giving me trouble.


5 years ago

Let me start at the beginning. Making a weather station. Want to represent the temperature outside with a colored light. When it is cold, I want the light to be blue, and when it is hot, I want red.