Working with "heating" and "cooling" light colors

by


Posted on


Working with

Coloring your house with light is just a thing that is a matter of taste. Some like deep red, others like light purple or green. There are two things where most interior designers agree too: The so called warm colors like orange, red and yellow mixed can give a cozier warmer feeling, while the cool colors like light purple, blueish and i think also green, can give a cooler and more spacious feeling. Well, this is a conclusion when i read about house lighting. So, what next?

I did some testing myself and i must say, in my opinion it’s quite true. At my family’s place we have some “warm” colored walls, and big warm colored curtains. During the day our main living room well, looks the size it just has. But in the evening or at night i tested with different light colors.

First, i took some led bulbs, with a warm color, let’s say about 2700 kelvins, almost like these “flame colored” bulbs. These bulbs are our standard bulbs we have lit every evening/night. When looking at the living room, and walking in and out i took some glimps and tried to measure the room. My first thought was: “Well ok, it’s normal like always”. After changing the light bulbs with a more “cooler” color about i think a little bit less then 5500 kelvins (it was just almost absolute white to the eye, little bit blueish). My room did looked more spacious! Keeping thinking of it, is my mind playing tricks because i read about it, or is lighting really playing with our minds?

Besides having the optical illusion of having a larger or smaller room by light, the light colors can also influence (as opposed and said) give us a warmer or colder feeling of our surroundings, not as absolute as said, but i think you get the point, and also where i’m trying to get to. A warm colored light then should theoretically give us a warmer feeling and a cold colored light should give us a cooler feeling. So, in the summer when it is about 22 degrees (Celsius) in the evening and we have a cool color light, it should not feel as 22 degrees but lower. And in the winter, when it’s about 4 or minus 5 degrees (i stay at Celsius) a warmer color should give us a warmer feeling. And the latter is what we want in domotica/home automation, right? We want to save heating costs in the winter, so turning down the heat by 1 and maybe 2 degrees, can already save money. But, we then have to be influenced by light, and not the temperature we see at our thermostat.

For the people who would also like to experiment with the above, i wrote a couple of functions in the server where can be played with. Although the functions now have fixed values, like everything that’s 15 degrees or below is a light color value of 2700K, between 15 and 27 degrees i map these values between 2700K and 27000K, and everything which is 27 degrees or higher thus is 27000 kelvins. I Have tested it with a BlinkM device, and with modified red values it quite came to life. The colors did came close to kelvins values.

So for further references when the download comes available, the functions are (class is subject to change, as well is the long used for kelvins values, as this is a test class):

float[] rgb = ColorImpl.tempToRgb(Double temp);
float[]hsb = ColorImpl.tempToHsb(Double temp);
long kelvins = ColorImpl.getKelvinFromTemp(Double temp);
float[] rgb = ColorImpl.kelvinToRgb(long kelvins);
float[] hsb = ColorImpl.kelvinToHsb(long kelvins);
float[] abc = ColorImpl.kelvinToColor(long kelvins, String colorType); ///Where colorType = ["rgb"|"hsb"] 

To use it with a device, we use the following (shortened code, there is more data to handle coming from the I2C device, and this is also just test code):

@Override
public void handleData(String input, Object object) {
/* We are using the object for the data. This object is a byte array with "Command/address" specific data specified in the input parameter */
byte[] byteArray = (byte[])object;
NumberFormat formatter;
try {
String[] data = input.split(":");
switch(data[0]){
case "0x01": /* temp reading comming from I2C chip memory address 0x01, we know the returned value from the chip is a float.*/
temp = MiscImpl.byteArrayToFloat(byteArray);
formatter = new DecimalFormat("##0.00;-#0.00"); /* range for the tmp36 temp sensor is -40 to +125 */
storeCmdSet("values", "0x01", formatter.format(temp)); /* "values" is the group id from xml, command returned is 0x01, value is the temp */
if(tmpToLight==true){ /* should the LED strip follow the temperature? */
float[] rgb = ColorImpl.tempToRgb(String.valueOf(temp));
if (devicePower==true) dispatchToDriver(":WRITE:0x09:"+(int)rgb[0]+","+(int)rgb[1]+","+(int)rgb[2]+"");
}
storeDataHistory(data[0], Double.parseDouble(formatter.format(temp))); /* Store the data for (for example) graph plotting in the clients */
notifyClients(); /* Let the clients know the new value coming from the device. */
break;
}
} catch (IndexOutOfBoundsException ex){
LOG.error("Illegal return type");
} catch (Exception ex){
LOG.warn("Unsupported return set: {}", ex.getMessage());
}

Just use the tempToRgb or tempToHsb functions if you do’t need any modifications and are happy with the default values. Use the other functions if you want to modify the return values.

For the people who are interested in the java temperature/kelvins to RGB or HSB code, here is the code, the map code is coming from an other class, so you have to modify it in the getKelvinFromTemp function.

/**
* Returns the mapped range from lower bound to higher bound.
* Calculation result 60 = map(6, 0, 10, 0, 100);
* @param curValue The known value between minCurValue and maxCurvalue
* @param minCurValue The minimum value of the lower bound range range
* @param maxCurValue The maximum value of the lower bound range
* @param minValue The minimum value of the higher bound range
* @param maxValue The maximum value of the higher bound range
* @return The calculated value between minValue and maxValue
*/
public static double map(double curValue, double minCurValue, double maxCurValue, double minValue, double maxValue){
return (curValue-minCurValue)/(maxCurValue-minCurValue) * (maxValue-minValue) + minValue;
}

/**
* Return the kelvins from a given temperature
* @param temp
* @return The mapped kelvin value (may not be as exact as the real kelvins scale)
*/
public static long getKelvinFromTemp(String temp){
double iTemp = Double.parseDouble(temp);
long kelvin = 0;
if(iTemp<=15){
kelvin = 2700;
} else if(iTemp>=15 && iTemp <= 27){
kelvin = (int)MathImpl.map(iTemp, 15, 27, 2700, 27000);
} else {
kelvin = 27000;
}
return kelvin;
}

/**
* Calculate th HSB based on Kelvin degrees (reasonable OK between the 1000 and 40000).
* @param kelvin Kelvin value
* @param colorType
* @return Array[0]=H, Array[1]=S and Array[2]=B when colorType hsb otherwise rgb
*/
public static float[] kelvinToColor(long kelvin, String colorType){
double tmpCalc;
double r;
double g;
double b;
float[] hsbvals = null;

if(kelvin>40000) kelvin = 40000;
if(kelvin<1000) kelvin = 1000;

kelvin = kelvin / 100;

/* red */
if(kelvin<= 66){
r = 255;
} else {
tmpCalc = kelvin - 60;
tmpCalc = 329.698727446 * Math.pow(tmpCalc,-0.1332047592);
r = tmpCalc;
if(r<0) r = 0;
if(r>255) r = 255;
}
/* green */
if(kelvin <= 66){
tmpCalc = kelvin;
tmpCalc = 99.4708025861 * Math.log(tmpCalc) - 161.1195681661;
g = tmpCalc;
if(g<0) g = 0;
if(g>255) g = 255;
} else {
tmpCalc = kelvin - 60;
tmpCalc = 288.1221695283 * Math.pow(tmpCalc,-0.0755148492);
g = tmpCalc;
if(g<0) g = 0;
if(g>255) g = 255;
}
/* blue */
if(kelvin >= 66){
b = 255;
} else if(kelvin <= 19){
b = 0;
} else {
tmpCalc = kelvin - 10;
tmpCalc = 138.5177312231 * Math.log(tmpCalc) - 305.0447927307;
b = tmpCalc;
if(b < 0) b = 0;
if(b > 255) b = 255;
}
switch(colorType){
case "hsb":
return java.awt.Color.RGBtoHSB((int)r, (int)g, (int)b, hsbvals);
default:
float[] rgb = new float[3];
rgb[0] = (int)r;
rgb[1] = (int)g;
rgb[2] = (int)b;
return rgb;
}

Resources used for this:
How to Convert Temperature (K) to RGB: Algorithm and Sample Code
BlinkM
WikiPedia Color Temperature

(I just noticed i used kelvin instead of kelvins)

Let me know if this was useful for you, or if something is in error.
With many thanks of course to the original author of the algorithm.

Latest news/blog

Friends of PiDome

Hubbit.nl
Webshop of the most prominent dutch tech magazines
UniPi.technology
Home-automation hardware manufacturer
Atlassian
Products for teams, from startup to enterprise
RFXCOM
Affordable 433Mhz RF transceivers

Latest added technology

  • SMS
  • Z-Wave
  • PushBullet
  • PlugWise
  • MQTT

Some project stats

Open Hub project report for PiDome Platform

Other

Official NLJUG Member