Kelvin to RGB convertion

Hya,

i'm trying to use the Kelvin light temperature to set my led RGB LED stripe.

I've found this table, but it's conversion is quite bad.

kelvin_table = {
    1000: (255, 56, 0),
    1100: (255, 71, 0),
    1200: (255, 83, 0),
    1300: (255, 93, 0),
    1400: (255, 101, 0),
    1500: (255, 109, 0),
    1600: (255, 115, 0),
    1700: (255, 121, 0),
    1800: (255, 126, 0),
    1900: (255, 131, 0),
    2000: (255, 138, 18),
    2100: (255, 142, 33),
    2200: (255, 147, 44),
    2300: (255, 152, 54),
    2400: (255, 157, 63),
    2500: (255, 161, 72),
    2600: (255, 165, 79),
    2700: (255, 169, 87),
    2800: (255, 173, 94),
    2900: (255, 177, 101),
    3000: (255, 180, 107),
    3100: (255, 184, 114),
    3200: (255, 187, 120),
    3300: (255, 190, 126),
    3400: (255, 193, 132),
    3500: (255, 196, 137),
    3600: (255, 199, 143),
    3700: (255, 201, 148),
    3800: (255, 204, 153),
    3900: (255, 206, 159),
    4000: (255, 209, 163),
    4100: (255, 211, 168),
    4200: (255, 213, 173),
    4300: (255, 215, 177),
    4400: (255, 217, 182),
    4500: (255, 219, 186),
    4600: (255, 221, 190),
    4700: (255, 223, 194),
    4800: (255, 225, 198),
    4900: (255, 227, 202),
    5000: (255, 228, 206),
    5100: (255, 230, 210),
    5200: (255, 232, 213),
    5300: (255, 233, 217),
    5400: (255, 235, 220),
    5500: (255, 236, 224),
    5600: (255, 238, 227),
    5700: (255, 239, 230),
    5800: (255, 240, 233),
    5900: (255, 242, 236),
    6000: (255, 243, 239),
    6100: (255, 244, 242),
    6200: (255, 245, 245),
    6300: (255, 246, 247),
    6400: (255, 248, 251),
    6500: (255, 249, 253),
    6600: (254, 249, 255),
    6700: (252, 247, 255),
    6800: (249, 246, 255),
    6900: (247, 245, 255),
    7000: (245, 243, 255),
    7100: (243, 242, 255),
    7200: (240, 241, 255),
    7300: (239, 240, 255),
    7400: (237, 239, 255),
    7500: (235, 238, 255),
    7600: (233, 237, 255),
    7700: (231, 236, 255),
    7800: (230, 235, 255),
    7900: (228, 234, 255),
    8000: (227, 233, 255),
    8100: (225, 232, 255),
    8200: (224, 231, 255),
    8300: (222, 230, 255),
    8400: (221, 230, 255),
    8500: (220, 229, 255),
    8600: (218, 229, 255),
    8700: (217, 227, 255),
    8800: (216, 227, 255),
    8900: (215, 226, 255),
    9000: (214, 225, 255),
    9100: (212, 225, 255),
    9200: (211, 224, 255),
    9300: (210, 223, 255),
    9400: (209, 223, 255),
    9500: (208, 222, 255),
    9600: (207, 221, 255),
    9700: (207, 221, 255),
    9800: (206, 220, 255),
    9900: (205, 220, 255),
    10000: (207, 218, 255),
    10100: (207, 218, 255),
    10200: (206, 217, 255),
    10300: (205, 217, 255),
    10400: (204, 216, 255),
    10500: (204, 216, 255),
    10600: (203, 215, 255),
    10700: (202, 215, 255),
    10800: (202, 214, 255),
    10900: (201, 214, 255),
    11000: (200, 213, 255),
    11100: (200, 213, 255),
    11200: (199, 212, 255),
    11300: (198, 212, 255),
    11400: (198, 212, 255),
    11500: (197, 211, 255),
    11600: (197, 211, 255),
    11700: (197, 210, 255),
    11800: (196, 210, 255),
    11900: (195, 210, 255),
    12000: (195, 209, 255)}

Is there a better translation for this?

Thx in advance!

What is bad about it and how is that array really declared in your sketch ?

1 Like

Are you talking about the correlated color temperature, i.e. the plankian locus on the CIE color chart?

So 1000 is the colour temperature and 255 56 0 are the RGB values?

If so I'd download that wikpedia image and use a paint program to find out the rgb values along the locus.

You also probably need a typedef like this, with just two samples as an example:


typedef struct {
    int ColorTemp ;
    int R ;
    int G ;
    int B ;
   
} PlankPoint_t ;

PlankPoint_t PlankianColors [] = {
    { 1000, 255, 56, 0},
    { 1100, 255, 71, 0},
} ;

thx for the answer. the program is working... but the colors seams to unreal, comparing with the real devices, that's why i asked if someone can point a more realistic conversion table.

the real program is:

/*
 Using a potentiometer to selectl kelvin .

 struct   CHSV
  Representation of an HSV pixel (hue, saturation, value (aka brightness))
 
 struct    CRGB
  Representation of an RGB pixel (Red, Green, Blue) 
 */


#include <FastLED.h>


#define LED_PIN 6             // which pin are LEDS connected to?
#define NUM_LEDS 4
#define COLOR_ORDER BRG // RGB - BRG
#define LED_TYPE WS2812B        // i'm using WS2811s, FastLED supports lots of different types.
#define FASTLED_ALLOW_INTERRUPTS 0
#define FASTLED_INTERRUPT_RETRY_COUNT 1
#define FRAMES_PER_SECOND 60
#define COOLING 55
#define SPARKING 120

#define MAX_BRIGHTNESS 255      // Thats full on, watch the power!
#define MIN_BRIGHTNESS 0        // set to a minimum of 25%

const int kelvinPin = A0;       // Analog input pin that the speed control potentiometer is attached to.
const int brightnessInPin = A1;

struct CRGB leds[NUM_LEDS];


CRGB kelvinrgbhex[] = {0xFF3800, 0xFF4700, 0xFF5300, 0xFF5D00, 0xFF6500,
                       0xFF6D00, 0xFF7300, 0xFF7900, 0xFF7E00, 0xFF8300,
                       0xFF8A12, 0xFF8E21, 0xFF932C, 0xFF9836, 0xFF9D3F,
                       0xFFA148, 0xFFA54F, 0xFFA957, 0xFFAD5E, 0xFFB165,
                       0xFFB46B, 0xFFB872, 0xFFBB78, 0xFFBE7E, 0xFFC184,
                       0xFFC489, 0xFFC78F, 0xFFC994, 0xFFCC99, 0xFFCE9F,
                       0xFFD1A3, 0xFFD3A8, 0xFFD5AD, 0xFFD7B1, 0xFFD9B6,
                       0xFFDBBA, 0xFFDDBE, 0xFFDFC2, 0xFFE1C6, 0xFFE3CA,
                       0xFFE4CE, 0xFFE6D2, 0xFFE8D5, 0xFFE9D9, 0xFFEBDC,
                       0xFFECE0, 0xFFEEE3, 0xFFEFE6, 0xFFF0E9, 0xFFF2EC,
                       0xFFF3EF, 0xFFF4F2, 0xFFF5F5, 0xFFF6F7, 0xFFF8FB,
                       0xFFF9FD, 0xFEF9FF, 0xFCF7FF, 0xF9F6FF, 0xF7F5FF,
                       0xF5F3FF, 0xF3F2FF, 0xF0F1FF, 0xEFF0FF, 0xEDEFFF,
                       0xEBEEFF, 0xE9EDFF, 0xE7ECFF, 0xE6EBFF, 0xE4EAFF,
                       0xE3E9FF, 0xE1E8FF, 0xE0E7FF, 0xDEE6FF, 0xDDE6FF,
                       0xDCE5FF, 0xDAE5FF, 0xD9E3FF, 0xD8E3FF, 0xD7E2FF,
                       0xD6E1FF, 0xD4E1FF, 0xD3E0FF, 0xD2DFFF, 0xD1DFFF,
                       0xD0DEFF, 0xCFDDFF, 0xCFDDFF, 0xCEDCFF, 0xCDDCFF,
                       0xCFDAFF, 0xCFDAFF, 0xCED9FF, 0xCDD9FF, 0xCCD8FF,
                       0xCCD8FF, 0xCBD7FF, 0xCAD7FF, 0xCAD6FF, 0xC9D6FF,
                       0xC8D5FF, 0xC8D5FF, 0xC7D4FF, 0xC6D4FF, 0xC6D4FF,
                       0xC5D3FF, 0xC5D3FF, 0xC5D2FF, 0xC4D2FF, 0xC3D2FF,
                       0xC3D1FF};



int kelvincolor[] = {1000, 1100, 1200, 1300, 1400,
                     1500, 1600, 1700, 1800, 1900,
                     2000, 2100, 2200, 2300, 2400,
                     2500, 2600, 2700, 2800, 2900,
                     3000, 3100, 3200, 3300, 3400,
                     3500, 3600, 3700, 3800, 3900,
                     4000, 4100, 4200, 4300, 4400,
                     4500, 4600, 4700, 4800, 4900,
                     5000, 5100, 5200, 5300, 5400,
                     5500, 5600, 5700, 5800, 5900,
                     6000, 6100, 6200, 6300, 6400,
                     6500, 6600, 6700, 6800, 6900,
                     7000, 7100, 7200, 7300, 7400,
                     7500, 7600, 7700, 7800, 7900,
                     8000, 8100, 8200, 8300, 8400,
                     8500, 8600, 8700, 8800, 8900,
                     9000, 9100, 9200, 9300, 9400,
                     9500, 9600, 9700, 9800, 9900,
                     10000, 10100, 10200, 10300, 10400,
                     10500, 10600, 10700, 10800, 10900,
                     11000, 11100, 11200, 11300, 11400,
                     11500, 11600, 11700, 11800, 11900,
                     12000};


void setup() {
  delay(3000); // in case we do something stupid. We dont want to get locked out.

  LEDS.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.setBrightness(MAX_BRIGHTNESS);
}

void loop() {
  // read the analog brightness value:
  //int brightValue = analogRead(redPin);            
  // map it to the range of the FastLED brightness:
  int kelvin = map(analogRead(kelvinPin), 0, 1023, 0, 112);
  int brightValue = map(analogRead(brightnessInPin), 0, 1023, 0, MAX_BRIGHTNESS);

 // FastLED.setBrightness(constrain(brightValue, MIN_BRIGHTNESS, MAX_BRIGHTNESS));
  FastLED.setBrightness(brightValue);
  
 // for(int n = 0; n < NUM_LEDS; n++)
 // {
 //  leds[n] = CRGB(redValue, greenValue, blueValue);
 // }
  fill_solid(leds, NUM_LEDS, CRGB(kelvinrgbhex[kelvin]));
  // display kelvincolor[kelvin] 
  FastLED.show();



}

Could it be that the LEDs do not respond linearly to applied voltages? Gamma correction or something like that needed?

This link has some code you could probably use:

Convert Coltemp To RGB algorithm

It may even use less space than the arrays...

is where i got the kelvin to rgb convertion :wink:

Hard to tell what the cause of your problem is, but one thing is that you cannot assume the 3 color led types will have the same luminous efficiency. You can approximate a better solution if you know the output of each led color in lumen per watt. You'll have to apply a linearization function to adjust for the different efficiencies.

@pw44 , it depends if you want something that emphasizes the color change as you change color temperature, or a realistic color. For the latter you'd really need a photospectrometer to check maybe 20 points along your curve.

@giovanniguerra, yes, it's something to be considered.

@Koraks, thank you. seams i have to dig more.