Color Detection Using Puck's Built-In LEDs

Posted on
  • I had a need to detect color. There are several boards available to detect color, but none of them work that great. I decided to see if the Puck's built-in red, green and blue LEDs (LED1, LED2, and LED3) could be used to detect color, and it works surprisingly well, so I wanted to share.

    Here is the simple approach I tested with:

    colors = {};
    function learnColor(colorName){
      var ledData = [analogRead(LED1),analogRead(LED2),analo­gRead(LED3)];
      colors[colorName] = ledData;
    function whichColor(){
      var closestColor = null;
      var closestLQD = null;
      var ledData = [analogRead(LED1),analogRead(LED2),analo­gRead(LED3)];
      for(var colorName in colors){
        var colorLEDData = colors[colorName];
        var dr = ledData[0] - colorLEDData[0];
        var dg = ledData[1] - colorLEDData[1];
        var db = ledData[2] - colorLEDData[2];
        var leastSquares = dr*dr+dg*dg+db*db;
        if(closestLQD === null || leastSquares<closestLQD){
          closestColor = colorName;
          closestLQD = leastSquares;
      return closestColor;

    There is a learnColor() function and a whichColor() function. Press the top of the puck against a color source and call learnColor(colorName) and pass in the name of that color. It works best with back illumination. I'm using my MacBook's screen with the following image:

    I went ahead and called learnColor("red") while holding the puck against the red, and then called learnColor("green") against the green, etc..

    Now when I hold the the puck against one of the four color patches at random and call whichColor(), it returns the correct color 100% of the time. Pretty cool!

    Now, this is VERY primitive at the moment. This is testing the exact same colors I trained on. But, with some additional work, I believe it would be possible to color balance and allow the training to generalize more. Also, currently, retraining on the same colorName will override the old data, but it's possible to average or otherwise accumulate the training data. Many more improvements can obviously be made.

    This is just a starting point, but it is already very useful. I'm using it as a UI input device where a young student can hold a puck against different patches on a screen to make different input choices. It's working great at the moment for this purpose.

    I should note that to get good readings, it's best to place the top face of the puck consistently flat against the display, and touching the display. I've tried it both with and without the white silicone case. It works better without the case.

  • That's awesome! Thanks!

    I use analogRead on the red LED for Puck.light(), but I never considered that you could actually read a colour value from all 3!

    I wonder whether it's worth trying to extend Puck.light or add a new function to read 3 colour channels?

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview

Color Detection Using Puck's Built-In LEDs

Posted by Avatar for jijidad @jijidad