Beginner project: Color Sensing with RGB LEDs and a photocell

I’ve seen the concept art for “real world eyedroppers” several times. I haven’t noticed any of the products come to market though. It isn’t the technology stoping them, color sampling can be done a million ways. I picked one of the easiest ways and tossed something together pretty quickly.

The method I chose is outlined in fantastic detail by [Fjordcarver] on instructibles. I took his project and used the Teensy2 instead of an arduino as well as seperate red, blue, and green LEDs since I had some lying around. He includes the schematic to do exactly that, so again, credit goes to him. [Fjordcarver] also made a processing sketch to display the colors. I wanted to actually use this, so I added a tiny feature where any keystroke will copy the hexidecimal color to the clipboard. This way I can just leave the “eyedropper” running and sample things whenever I want.

import processing.serial.*;
import java.awt.datatransfer.*;
import java.awt.Toolkit;

String buff = "";
int val = 0;
int wRed, wGreen, wBlue;
String col = "ffffff";
ClipHelper cp = new ClipHelper();

Serial port;

void setup(){

 port = new Serial(this, "COM3", 9600); //remember to replace COM20 with the appropriate serial port on your computer

void draw(){
 // check for serial, and process
 while (port.available() > 0) {

void keyPressed() { cp.copyString(""+col); }
void serialEvent(int serial) {

if(serial != '\n') {
 buff += char(serial);
 else {
 int cRed = buff.indexOf("R");
 int cGreen = buff.indexOf("G");
 int cBlue = buff.indexOf("B");

if(cRed >=0){
 String val = buff.substring(cRed+3);
 wRed = Integer.parseInt(val.trim());
 if(cGreen >=0){
 String val = buff.substring(cGreen+3);
 wGreen = Integer.parseInt(val.trim());
 if(cBlue >=0){
 String val = buff.substring(cBlue+3);
 wBlue = Integer.parseInt(val.trim());
 col = hex(color(wRed, wGreen, wBlue), 6);
 buff = "";



class ClipHelper {
 Clipboard clipboard;

 ClipHelper() {

 void getClipboard () {
 // this is our simple thread that grabs the clipboard
 Thread clipThread = new Thread() {
 public void run() {
 clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();

 // start the thread as a daemon thread and wait for it to die
 if (clipboard == null) {
 try {
 catch (Exception e) {}

 void copyString (String data) {
 copyTransferableObject(new StringSelection(data));

 void copyTransferableObject (Transferable contents) {
 clipboard.setContents(contents, null);

 String pasteString () {
 String data = null;
 try {
 data = (String)pasteObject(DataFlavor.stringFlavor);
 catch (Exception e) {
 System.err.println("Error getting String from clipboard: " + e);
 return data;

 Object pasteObject (DataFlavor flavor)
 throws UnsupportedFlavorException, IOException
 Object obj = null;

 Transferable content = clipboard.getContents(null);
 if (content != null)
 obj = content.getTransferData(flavor);

 return obj;

16 thoughts on “Beginner project: Color Sensing with RGB LEDs and a photocell

  1. Interesting. Now you should do RGB to CYMK conversion and add an ink cartridge to make it cooler :P

    Isn’t it better to sample first without the LEDs on and get an “ambient luminosity” first, and then substract it? Instead of doing a calibration with a black paper?

  2. The reason why none of the devices have gone to market is that RGB sampling of real world colors isn’t an accurate way to measure color.

    It’s the difference between additive and subtractive color. For example, using red and green LEDs to measure yellow doesn’t work because the spectral output of the LEDs are so narrow that you get a gap right where your yellow should be.

    A correct way to do it is to shine a wide band light on the object, like from a tungsten halogen bulb, take the reflection and spread it apart with a prism, then measure the resulting rainbow with a line sensor and apply appropriate calibrations and calculations.

  3. Not sure what it means that these have not made it to real world. I work in printing and we use color spectrometers all the time. X-Rite offers many options and they nail colors. To improve your results you could use 5000K lighting and take the reflectiveness of the item into account. It’s also important to calibrate the monitor so it displays the color properly.

  4. Dax and Say What? make good points!

    The illuminant should have continuous spectral output. Of course, the design would require three photocells, each with a filter to pass only the R, G, or B bands or a single photocell with a selectable filter. If using multiple p-cells, they should be as close together as possible so that they all “see” the sample the same way.

    The reflectance properties of the measured sample can have a huge effect on accuracy. For this reason, using directed point-sources as an illuminant is a no-no. Surfaces with a strong spectral reflectance will measure differently than a same-color sample that has a diffuse surface reflection. So, the illuminant should be highly diffuse- ideally, a Lambertian diffusion pattern- and sized to extend beyond the measuring area, so that the sample is evenly lit from all sides.

    The white balance circuitry in digital cameras are doing something very similar to colorimetry- maybe there is some way to hack an old digicam to do this.

  5. CdS photocells are mostly sensitive to orange or yellow, less other colors.
    LED’s on the other hand can be used as photodiodes. They’re sensitive to wavelengths equal to or shorter than the predominant wavelength they emit. In other words you could make a color sensor with just LED’s.

  6. A very simple alternative is to just use a webcam and average the colors in a small area in the center.

    I’m wondering why the LEDs flash so slowly. CdS cells have a response time of less than 50ms, and LEDs practically zero, so if you count RGB+black it seems it would be possible to cycle the LEDs at 5Hz, for a better response time.

  7. ehm whats wrong of buying an usb camera ?
    And if you want specific colors precise buy a real camera ok its more expensive, but well most people have a camera.. so where is the need for this ?

    1. Cameras are quite inaccurate as far as color measurement goes, specially the cheap usb kind. They have weird color curve responses, get skewed by IR light, have different kinds of filters, both optical and in software.

      Also, with this kind of project, you can measure color in wavelengths that a normal camera wouldn’t distinguish, like IR or UV.

      1. Let’s be honest – (cheap) cameras are inaccurate just like this (cheap) colorimeter is inaccurate.

        Accurate, calibrated versions of both (plus matching monitors, printers, etc.) are equally good for their various purposes, but the average joe can’t tell the difference. In fact, having done a little printing and a fair bit of work with video cameras, most people may as well be wearing glasses made of tinted bubble-wrap for their ability to see variations/flaws/innaccuracies in display technology.

  8. Back when I used to work part time at a paint retailer while studying, I thought of doing something like this to help people identify which color code a chip of paint was. This was a constant problem as people lost the codes for stuff they bought years ago, then made a hole in the wall. It sometimes took hours to manually match the color!

    In the end I bought a broken scanner for 2$ (bad capacitor and a broken power trace to one IC). It used a bar of LEDs as a “white” light source, and worked pretty well. It might have used UV LEDs to fluoresce something, I’m not sure.

    After mapping the 6000 or so color codes in an ‘almost-euclidean’ 3-space (and using some statistics) it worked pretty well. I found you could correct in software for some of the quirks of the machine’s perception of color, and it would reliably identify which of 6000 colors was presented. I used the data to demonstrate Beer’s Law too, because it’s a wonderfully named law.

    (Yes, I know commercial solutions exist… but this one was 2$ and a lot of fun)

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s