Philips Hue Lights – Popular XY Color Values

You can use these tables to find the Hue CIE colorspace XY coordinates for popular HTML color codes. This is useful if you’re changing light colors via the API. See the footnote below to learn how I calculated these values.

Note: Some colors fall outside of the addressable Hue color space. In those cases, I just used the closest match.

Color HTML / CSS
Color Name
Hex Code
#RRGGBB
Decimal Code
(R,G,B)
Hue XY
  lightsalmon #FFA07A rgb(255,160,122) (0.5015,0.3530)
  salmon #FA8072 rgb(250,128,114) (0.5347,0.3256)
  darksalmon #E9967A rgb(233,150,122) (0.4849,0.3476)
  lightcoral #F08080 rgb(240,128,128) (0.5065,0.3145)
  indianred #CD5C5C rgb(205,92,92) (0.5475,0.3113)
  crimson #DC143C rgb(220,20,60) (0.6435.0.3045)
  firebrick #B22222 rgb(178,34,34) (0.6554,0.3111)
  red #FF0000 rgb(255,0,0) (0.675,0.322)
  darkred #8B0000 rgb(139,0,0) (0.675,0.322)


Orange colors

Color HTML / CSS
Color Name
Hex Code
#RRGGBB
Decimal Code
(R,G,B)
Hue XY
  coral #FF7F50 rgb(255,127,80) (0.5754,0.3480)
  tomato #FF6347 rgb(255,99,71) (0.6111,0.3260)
  orangered #FF4500 rgb(255,69,0) (0.6725,0.3230)
  gold #FFD700 rgb(255,215,0) (0.4852,0.4619)
  orange #FFA500 rgb(255,165,0) (0.5567,0.4091)
  darkorange #FF8C00 rgb(255,140,0) (0.5921,0.3830)


Yellow colors

Color HTML / CSS
Color Name
Hex Code
#RRGGBB
Decimal Code
(R,G,B)
Hue XY
  lightyellow #FFFFE0 rgb(255,255,224) (0.3435,0.3612)
  lemonchiffon #FFFACD rgb(255,250,205) (0.3594,0.3756)
  lightgoldenrodyellow #FAFAD2 rgb(250,250,210) (0.3502,0.3715)
  papayawhip #FFEFD5 rgb(255,239,213) (0.3598,0.3546)
  moccasin #FFE4B5 rgb(255,228,181) (0.3913,0.3755)
  peachpuff #FFDAB9 rgb(255,218,185) (0.3948,0.3597)
  palegoldenrod #EEE8AA rgb(238,232,170) (0.3762,0.3978)
  khaki #F0E68C rgb(240,230,140) (0.4023,0.4267)
  darkkhaki #BDB76B rgb(189,183,107) (0.4019,0.4324)
  yellow #FFFF00 rgb(255,255,0) (0.4325,0.5007)


Green colors

Color HTML / CSS
Color Name
Hex Code
#RRGGBB
Decimal Code
(R,G,B)
Hue XY
  lawngreen #7CFC00 rgb(124,252,0) (0.4091,0.518)
  chartreuse #7FFF00 rgb(127,255,0) (0.4091,0.518)
  limegreen #32CD32 rgb(50,205,50) (0.4091,0.518)
  lime #00FF00 rgb(0.255.0) (0.4091,0.518)
  forestgreen #228B22 rgb(34,139,34) (0.4091,0.518)
  green #008000 rgb(0,128,0) (0.4091,0.518)
  darkgreen #006400 rgb(0,100,0) (0.4091,0.518)
  greenyellow #ADFF2F rgb(173,255,47) (0.4091,0.518)
  yellowgreen #9ACD32 rgb(154,205,50) (0.4091,0.518)
  springgreen #00FF7F rgb(0,255,127) (0.3883,0.4771)
  mediumspringgreen #00FA9A rgb(0,250,154) (0.3620,0.4250)
  lightgreen #90EE90 rgb(144,238,144) (0.3673,0.4356)
  palegreen #98FB98 rgb(152,251,152) (0.3674,0.4358)
  darkseagreen #8FBC8F rgb(143,188,143) (0.3423,0.3862)
  mediumseagreen #3CB371 rgb(60,179,113) (0.3584,0.4180)
  seagreen #2E8B57 rgb(46,139,87) (0.3580,0.4172)
  olive #808000 rgb(128,128,0) (0.4325,0.5007)
  darkolivegreen #556B2F rgb(85,107,47) (0.3886,0.4776)
  olivedrab #6B8E23 rgb(107,142,35) (0.4091,0.518)


Cyan colors

Color HTML / CSS
Color Name
Hex Code
#RRGGBB
Decimal Code
(R,G,B)
Hue XY
  lightcyan #E0FFFF rgb(224,255,255) (0.3096,0.3216)
  cyan #00FFFF rgb(0,255,255) (0.2857,0.2744)
  aqua #00FFFF rgb(0,255,255) (0.2857,0.2744)
  aquamarine #7FFFD4 rgb(127,255,212) (0.3230,0.3480)
  mediumaquamarine #66CDAA rgb(102,205,170) (0.3231,0.3483)
  paleturquoise #AFEEEE rgb(175,238,238) (0.3032,0.3090)
  turquoise #40E0D0 rgb(64,224,208) (0.3005,0.3036)
  mediumturquoise #48D1CC rgb(72,209,204) (0.2937,0.2902)
  darkturquoise #00CED1 rgb(0,206,209) (0.2834,0.2698)
  lightseagreen #20B2AA rgb(32,178,170) (0.2944,0.2916)
  cadetblue #5F9EA0 rgb(95,158,160) (0.2963,0.2953)
  darkcyan #008B8B rgb(0,139,139) (0.2857,0.2744)
  teal #008080 rgb(0,128,128) (0.2857,0.2744)


Blue colors

Color HTML / CSS
Color Name
Hex Code
#RRGGBB
Decimal Code
(R,G,B)
Hue XY
  powderblue #B0E0E6 rgb(176,224,230) (0.3015,0.3057)
  lightblue #ADD8E6 rgb(173,216,230) (0.2969,0.2964)
  lightskyblue #87CEFA rgb(135,206,250) (0.2706,0.2447)
  skyblue #87CEEB rgb(135,206,235) (0.2788,0.2630)
  deepskyblue #00BFFF rgb(0,191,255) (0.2425,0.1892)
  lightsteelblue #B0C4DE rgb(176,196,222) (0.2926,0.2880)
  dodgerblue #1E90FF rgb(30,144,255) (0.2124,0.1297)
  cornflowerblue #6495ED rgb(100,149,237) (0.2355,0.1753)
  steelblue #4682B4 rgb(70,130,180) (0.2491,0.2021)
  royalblue #4169E1 rgb(65,105,225) (0.2051,0.1152)
  blue #0000FF rgb(0,0,255) (0.167,0.04)
  mediumblue #0000CD rgb(0,0,205) (0.167,0.04)
  darkblue #00008B rgb(0,0,139) (0.167,0.04)
  navy #000080 rgb(0,0,128) (0.167,0.04)
  midnightblue #191970 rgb(25,25,112) (0.1821,0.0698)
  mediumslateblue #7B68EE rgb(123,104,238) (0.2186,0.1419)
  slateblue #6A5ACD rgb(106,90,205) (0.2198,0.1443)
  darkslateblue #483D8B rgb(72,61,139) (0.2235,0.1502)

Purple colors

Color HTML / CSS
 Color Name
Hex Code
 #RRGGBB
Decimal Code
(R,G,B)
Hue XY
  lavender #E6E6FA rgb(230,230,250) (0.3085,0.3071)
  thistle #D8BFD8 rgb(216,191,216) (0.3342,0.2970)
  plum #DDA0DD rgb(221,160,221) (0.3495,0.2545)
  violet #EE82EE rgb(238,130,238) (0.3645,0.2128)
  orchid #DA70D6 rgb(218,112,214) (0.3716,0.2102)
  fuchsia #FF00FF rgb(255,0,255) (0.3826,0.1597)
  magenta #FF00FF rgb(255,0,255) (0.3826,0.1597)
  mediumorchid #BA55D3 rgb(186,85,211) (0.3362,0.1743)
  mediumpurple #9370DB rgb(147,112,219) (0.2629,0.1772)
  blueviolet #8A2BE2 rgb(138,43,226) (0.2524,0.1062)
  darkviolet #9400D3 rgb(148,0,211) (0.2852,0.1086)
  darkorchid #9932CC rgb(153,50,204) (0.2986,0.1335)
  darkmagenta #8B008B rgb(139,0,139) (0.3826,0.1597)
  purple #800080 rgb(128,0,128) (0.3826,0.1597)
  indigo #4B0082 rgb(75,0,130) (0.2485,0.0917)


Pink colors

Color HTML / CSS
Color Name
Hex Code
#RRGGBB
Decimal Code
(R,G,B)
Hue XY
  pink #FFC0CB rgb(255,192,203) (0.3947,0.3114)
  lightpink #FFB6C1 rgb(255,182,193) (0.4105,0.3102)
  hotpink #FF69B4 rgb(255,105,180) (0.4691,0.2468)
  deeppink #FF1493 rgb(255,20,147) (0.5388,0.2464)
  palevioletred #DB7093 rgb(219,112,147) (0.4657,0.2773)
  mediumvioletred #C71585 rgb(199,21,133) (0.4997,0.2247)


White colors

Color HTML / CSS
Color Name
Hex Code
#RRGGBB
Decimal Code
(R,G,B)
Hue XY
  white #FFFFFF rgb(255,255,255) (0.3227,0.3290)
  snow #FFFAFA rgb(255,250,250) (0.3280,0.3286)
  honeydew #F0FFF0 rgb(240,255,240) (0.3210,0.3441)
  mintcream #F5FFFA rgb(245,255,250) (0.3162,0.3346)
  azure #F0FFFF rgb(240,255,255) (0.3125,0.3274)
  aliceblue #F0F8FF rgb(240,248,255) (0.3098,0.3220)
  ghostwhite #F8F8FF rgb(248,248,255) (0.3098,0.3220)
  whitesmoke #F5F5F5 rgb(245,245,245) (0.3227,0.3290)
  seashell #FFF5EE rgb(255,245,238) (0.3385,0.3353)
  beige #F5F5DC rgb(245,245,220) (0.3401,0.3559)
  oldlace #FDF5E6 rgb(253,245,230) (0.3377,0.3376)
  floralwhite #FFFAF0 rgb(255,250,240) (0.3349,0.3388)
  ivory #FFFFF0 rgb(255,255,240) (0.3327,0.3444)
  antiquewhite #FAEBD7 rgb(250,235,215) (0.3546,0.3488)
  linen #FAF0E6 rgb(250,240,230) (0.3410,0.3386)
  lavenderblush #FFF0F5 rgb(255,240,245) (0.3357,0.3226)
  mistyrose #FFE4E1 rgb(255,228,225) (0.4212,0.1823)

Calculating Hue Values

Colors get complicated…

Philips says In their own words, that when working with their API, that “colors get complicated”. This is certainly true, as there are a lot of different ways to represent a color space and quantify a color point of light.

Philips uses the CIE color space to represent the available colors for Hue bulbs. The three triangles outline the colors which hue can address.

The Lights API specifies three different parameters that you can set a color: xy, color temperature (ct) or hue and saturation (hs). I’ve worked with all three and found that using the xy parameter is the most intuitive. It’s easy to picture how the values relate to a specific color and the API only requires a single field to be updated.

As you can see in the diagram above, it’s straight forward to get an idea of what xy value to use for a color – just look for where the two points intersect on the diagram. For example, “xy”:[0.675,0.322] is red.

What’s not intuitive, is if you have an exact color in mind – perhaps an RGB or hex color value and you need to know what the corresponding hue xy value would be. I was surprised that this mapping was not available in the API documentation – or essentially anywhere.

To build my own table and calculate the xy values from the html hex codes, I used this excellent tool from github: hue-python-rgb-converter. There’s some fancy math happening under the covers and this does the conversion seamlessly.

Here’s a quick script that I put togher below that uses the library. All you need to do is pull down the converter from git, unpack and then run from the hue-python-rgb-converter-master folder passing a hex color code as a value.

#!/usr/bin/python
from rgbxy import Converter
import sys
val = sys.argv[1]
print val
converter = Converter()
xy = converter.hex_to_xy(val)
print xy

If you found this post useful, I’d be very grateful if you’d help it spread the word by emailing it to a friend, or sharing on Twitter or Facebook. Thank you!

Connecting a Matrix Orbital Display to a Raspberry Pi

If you’ve ever wondered how to connect a Matrix Orbital display to your Raspberry Pi, then this is the post for you. No more sleepless nights.

I’m a big fan of the Matrix Orbital vacuum fluorescent displays because they have a really cool retro vibe and I use them in a lot of projects. Connecting to a Pi is a snap because of the board’s architecture.

You have multiple options depending on the board – either I2C, serial or USB. In this post I’m going to focus specifically on serial and I2C because these are available on the less expensive older boards – which I typically buy.

These instructions should work with any older VK204-25 board. See this link for the VK-204 technical manuals.

The image on the right shows the back of the display module with the DB9 (serial) connector on the left and the 4 pin I2C connector (white) on the right.

Matrix Orbital VK204-25 Display
Matrix Orbital VK204-25 DB9 (left) and I2C (right)

I2C

To connect via I2C you’ll need to first enable the interface on the Pi. This is done via raspi-config which can be run in a terminal window:

sudo raspi-config

In the raspi-config user interface navigate to Interfacing Options >> I2C and answer the question "Would you like the ARM I2C interface to be enabled?" with <Yes>. After the next reboot user pi will be able to use the I2C bus without root privileges.

When connecting the display, you’ll need to find the correct GPIO pins depending on the version Pi you’re using. Needed are SCL, SDA , 5V and ground. Note: For this example I’ll be connecting to an older Pi (model B) that has a 26 pin header. More recent Pis will have a different GPIO configuration – make sure to read the documentation.

Behind the display on the lower right, there’s a white colored 4 pin connector. The ground is the pin furthest to the right and labeled on the PCB. The correct connections are: Pin1 5VDC, Pin2 SCL, Pin3 SDA and Pin4 Ground.

Run the following command from your Pi in a terminal to confirm that you have it wired up correctly:

i2cdetect -y 1

This will return a hex address that’s needed when sending commands to the display.

Serial (DB9)

For an alternative serial connection, there’s a DB9 port on the lower right of the display. See the diagrams to the right for the pin orientation and how to connect. You’ll be using the same 5v and ground connections as the I2C setup, but you’ll also need to connect the Pi TX pin to the DB9 pin 3, the Pi RX pin to DB9 pin 2, and a ground to DB9 pin 5.

Raspberry Pi Model B using I2C
Rasbperry Pi Model B using DB9 (Serial)
LCD DB9 Pin Orientation

These two options cover everything needed for connecting the display. The only gotcha is that some of the older boards might require jumper changes or even soldering some pull up resistors depending on the chosen communication method. I would recommend reading the documentation carefully as these requirements can be different depending on the board version.

Hopefully you found this post helpful. Check out my engineering posts for other useful how-tos.

Driving Matrix Orbital LCD Displays with Python

Admittedly, this post is even more “techie” than my last one on hardware RNGs. I feel compelled to deliver the same public service announcement: If learning how to use python to drive a Matrix Orbital display is not your cup of tea, this might be a hard pass. Otherwise, read on if you’re technically curious. If I can save one person hours of work, then the effort was well worth it.

I’m a big fan of the Matrix Orbital VK204-25 LCD module and have used it in a bunch of projects. It’s an older device, but you can’t beat how good the throwback vacuum fluorescent display looks when you want a retro type aesthetic.

A new module can be expensive, however, you can find older ones relatively cheap on eBay if you keep your eyes open.

The older boards communicated over either I2C or RS232. I prefer using I2C as my projects typically use Raspberry Pis, and the GPIO includes native support. I’m not going to spend any time here on how to connect the module to a Pi as Adafruit has a wonderful in-depth tutorial on interfacing Pis with I2C components.

When I first started using these displays I was surprised (and frustrated) that there were limited python libraries available for driving the display over I2C. I eventually decided to hack together my own since the command structure is well documented and easy to implement with python’s smbus module. You can find my code here.

Usage is straight forward. Characters to display on the LCD are chosen by using the correct binary or hex value. The Matrix Orbital documentation includes a matrix that maps each ASCII character to the appropriate hex code.

The script takes a single word as input, iterates over each character in the word to find the corresponding hex value and then sends the display command using the board’s bus address.

In addition to the character mappings, the script includes a few basic commands that can turn the display on or off or clear any text.

Here are a few usage examples. First, turning on the display:

orbitalWrite.on_display(busAddr)

busAddr is the I2C address for the board. You can determine this on a Raspberry Pi by using the i2cdetect command as discussed here. If my board was addressed using 0x28 I would issue the following:

orbitalWrite.on_display(0x28)

Here the script will use the busAddr, send 0xFE (a code prefix that indicates a control command is being issued), and then send the hex value for the command itself. In the above case 0x42, which means turn on the display.

Here’s how to write single or multiple words to the display:

orbitalWrite.write_display(busAddr,wordDisp)

busAddr is the board I2C address and wordDisp is the word to display. For example:

orbitalWrite.write_display(0x28,some words here)

Behind the scenes, the script will iterate through each letter (including spaces) and send each character individually to the display.

Just for fun, I included a timer as part of the character display function so that there’s a slight pause of random length before writing. The effect is like an old style typewriter.

That’s it! If you have a Matrix Orbital display and use my code, drop me a line and let me know about your project.

Getting Random with REST

Public service announcement: This is going to be a “techie” post.

If interfacing with hardware random number generators via REST API is not your thing, you might want to pass on this one.

Over the years, I’ve built a number of devices that investigate the influence of intention on random events. These will undoubtedly be topics for future posts, but suffice to say, all required the use of a hardware based random number generator.

I’ve tried several different hardware RNGs, and have even built my own, but the two I like the best are the OneRNG and TrueRNG devices pictured to the right.

OneRNG Hardware Random Number Generator
TrueRNG Hardware Random Number Generator

They both work well with linux and SBCs like a RaspberryPi or BeagleBone. They also both use an avalanche effect from a diode circuit to generate the random noise. The data fills the entropy pool of the operating system and can be accessed (in linux) via /dev/random or /dev/urandom.

I haven’t done any analysis to see which has a higher bit rate, but both are sufficient for my purposes. I would give OneRNG a slight edge in that the hardware and software are open and fully published. Also, I find the onboard LED highly convenient as it can be used to test whether it’s operating properly. Otherwise, there’s no easy way to verify you’re getting output from the hardware versus the OS pseudo-random number generator.

RNG server using OneRNG in the Enigmatic lab

Both have thorough documentation on how to set up on a linux based system, but where I found info scarce is how to query the device to get a random number in the format that I wanted. Output is a stream of binary data by default, but for my purposes I need string representations of integers and floats.

After much Googling, I put together a solid setup for returning an integer within a set range (like between 1-100) and a float between 0 and 1. I wanted to share as a time saver for anyone interested.

Here’s the command I run from the linux CLI to get an integer within a range of 100 and 1000:

echo $(( 100+(`od -An -N2 -i /dev/random` )%(1000-100+1)))
decker@sonoya:~/scripts# echo $(( 100+(`od -An -N2 -i /dev/random` )%(1000-100+1)))
312

To change the range, substitute the two ‘100’ occurrences with a value for the low end and substitute ‘1000’ for the high end.

Here’s the code to get a single float value between 0 and 1:

(printf '%.19f\n' "0x0.$(od -N 8 -An -tx1 /dev/random | tr -d ' ')")
decker@sonoya:~/scripts# (printf '%.19f\n' "0x0.$(od -N 8 -An -tx1 /dev/random | tr -d ' ')")
0.6726632392320606169

Both these commands are useful in a quick linux shell script, but I also needed a more flexible way to get random numbers from different programing languages and from remote hosts.

Python Flask to the rescue! Flask is useful to setup quick python server with REST endpoints, perfect for my use case.

Before I share my code, a warning or two:

First, I’m not a programmer. I hack together quick scripts to get what I need done, there are probably (definitely) more elegant ways to accomplish this. Second, I’m running my flask server as root and using python to call a shell script that executes OS commands. Don’t do this in a production or public facing environment!

You can find the code at my github repository below. You will need to install flask prior to running.

https://github.com/deckerEnigmatic/rngRESTServer/tree/master

When you run the script you should see output like the below. This will create a server running on the local machine using TCP port 5000.

root@sonoya:~/scripts/rngrestserver# ./rngrestserver.py
 * Serving Flask app "rngrestserver" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

I have this running on a Raspberry Pi in my lab and use it to serve random numbers to remote hosts. A remote client can request a random number by hitting the correct REST endpoint with the appropriate parameters. Here’s the usage below:

Endpoint to request a random number within a range:

http://192.168.1.133:5000/rangeInt/1/100

Output is JSON key value pair. In this case a single integer between 1 and 100.

http://192.168.1.133:5000/rangeFloat

Output is a JSON key value pair returning a float.

If you work with hardware based RNGs I hope you found this post helpful. I spent some “quality” time learning cryptic shell commands to get the output in the format I needed. If you use any of my code, reach out and let me know!