Detecting LED colour

Hi all

I have been trying to detect the colour of an RGB led without much success.
I did try an Adafruit TCS34725 colour sensor but it was far from reliable.

My project covers over a status LED that shows red, blue, violet, yellow etc.
I need to replicate that LED on a separate front panel. I had hoped to do it with a simple light pipe, but it is just a bit too far away.

I cannot get into the device I am reading the LED from, so not sure on the best way to do this.

The TCS34725 was VERY temperamental. I did spend ages tinkering with adjusting the code for eye-recognized gamma color etc, but that didn't help.

Wondered if anyone had any other suggestions for sensors?

ooh... just had a thought... Fibre optics? (instead of a light pipe)

fiber coud possibly work if you just want a visual clue and don't need to instrument the information conveyed by the LED

when you played with the TCS34725, did you try to put a diffuser on top of the LED (like a piece of tracing paper) to prevent the sensor to be directly exposed to the embeded three RGB leds ?

Oh yea... many hours playing with filters, diffusers etc. I found the slightest bit of leaked light played havoc as well.

I designed a TPU 'glove' that sat over the top with a opal diffuser inside.... but I just could not get it to detect correctly.

I say that... maybe it was detecting correctly, but I was feeding that info into a program then asking it then replicate the led colour on another RGB LED. That just didn't work.

I found that certain colours basically didn't have enough 'differential' in values to make it viable to show all the colours. I can't remember what colours were the issue... but their detected values were only 2 or 3 apart and that made it very unreliable.

I am now thinking of maybe simple is best... a length of fibre pipe with a nice panel mounted end cap.

it works better on M&Ms :slight_smile:
image

the thing is that the LED might be using PWM to drive the three built-in RGB leds. You don't see that with your naked eye but the on-off cycle might be enough to mislead the sensor.

Some sensor boards even include an illuminating led.


Of course that would also be an issue if you have that.

The sensor is probably meant for detecting "passive" objects (reflective) rather than light emitting

1 Like

How far?
I've seen a light pipe on a printer that was close to a 1 foot long.

I turned the onboard LED off. That definitely made a difference, but not enough.
The other issue with the solid light pipe is it's not a straight route, so I think fibre optic might work better... if it transmits enough light.

I think it's possibly the driving signal as well. I did use various diffusers hoping that would over come that (not sure how!).
The sensor certainly does work better at detecting passive colours, and that is what I think it's meant for.

I did think of trying 3x photocells, each covered with a red, green and blue filter onto 3x analogue inputs. But not sure that would work at all and it's getting a bit involved then.

Might try that just out of interest.

You can buy flexable light pipes with bezels attached on one end

Funny! Fibre optics are used for laser burning and cutting. So, I guess they transmit light pretty well.

lol... Yes I realise that! It's a 10mm diameter indicator. So a .075mm or 1mm fibre will significantly reduce the output at the other end... I imagine.

Maybe I should let the LED indicator shine up up a sort of 'tube' and hit a 45 degree white plane.
Then try reading the colour off that with the TCS34725 set up at 45 degrees to the direct light.

There goes my evening....

Why so small? At one time I had several armored fiber optic cables about 3 ft. long. The fiber inside was about 1/4 inch in diameter. They transmitted plenty of light. I don't recall where they came from, but were stuff auctioned off when I closed my company. See what you can find.

Well its quite a tight fitting area. I could get away with 1/4". Failing that, I can bundle more than one fibre.
Plus the new indicator doesn't need to be 10mm. 3mm would probably be fine.

OK... Well kinda works...

I have a ATTINY1604, connected to a 74HC4051 that is multiplexing the SDA of 5x VEML6040 colour sensors.
They all share the same SCL.

Ticking along fine using the VEML6040 Library.

Currently, I am just spitting out the values read by the sensors to an RGBW strip (5 leds).
I have not done any dialling in on that yet, so the colours are not correct.

The quickest I can read the sensors appears to be 80ms. I have upped the timing to 100ms.

Unfortunately. the LED it is monitoring can flash at a rate of around 500ms (on for 500ms, off for 500ms). So there is a chance that the 'flash' gets missed.

Didn't really think it would be an issue, but I didn't realise the LEDS I am monitoring might flash quite so fast.

The test code is awful... but it works in principle.

There is some remnants of the OLED I had connected to check the values returned from the sensors.

#include "Wire.h"
#include "veml6040.h"                                                                        // Colour sensor library
#include <Adafruit_NeoPixel.h>
#include <U8x8lib.h>

U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE, /* clock=*/ SCL, /* data=*/ SDA);   // pin remapping with ESP8266 HW I2C

#ifdef __AVR__
#include <avr/power.h>
#endif

VEML6040 RGBWSensor;

#define RGBWpin   0                                                                          // This is pin 2 on the IC
#define NUMPIXELS 2
Adafruit_NeoPixel strip(NUMPIXELS, RGBWpin, NEO_GRBW + NEO_KHZ800);                          // Might be NEO_GRBW / NEO_RGBW      NEO_KHZ800 / NEO_KHZ400

#define addA      1                                                                          // This is pin 3 on the IC    4051 Multiplexer
#define addB      2                                                                          // This is pin 4 on the IC
#define addC      3                                                                          // This is pin 5 on the IC
#define Led       8                                                                          // This is pin 11 on the IC.   LED is just for debugging

byte red = 0;
byte green = 0;
byte blue = 0;
byte white = 0;

byte sensor_number = 1;

unsigned long CurrentMillis;
unsigned long getcolourMillis;
unsigned long updateMillis;

//---------------------------------------------------------------------------------------------------
void setup() {
  pinMode (Led, OUTPUT);
  pinMode (addA, OUTPUT);
  pinMode (addB, OUTPUT);
  pinMode (addC, OUTPUT);

  Serial.begin(115200);                                                                          // TX = Pin 5 (Pin 7 on the IC)    RX = Pin 4 (Pin 6 on the IC)   This is Comms to the Teensy 4.1
  Wire.begin();                                                                                  // SCL = Pin 7 (Pin 9 on the IC)    SDA = Pin 6 (Pin 8 on the IC)

  digitalWrite(Led, HIGH);                                                                       // Turn on LED at boot
  delay(500);

  digitalWrite(addA, LOW);                                                                       // Set inital 4051 Multiplexer address 0 (Sensor 1)
  digitalWrite(addB, LOW);
  digitalWrite(addC, LOW);

  u8x8.begin();                                                                                  // Start text library
  u8x8.setFont(u8x8_font_8x13_1x2_f);                                                            // Set font
  u8x8.setCursor(0, 1);
  u8x8.print("SYSTEM ONLINE...");

  delay(800);

  u8x8.clearDisplay();

  if (!RGBWSensor.begin()) {
    digitalWrite(Led, LOW);                                                                      // Turn the Led off again if the sensor is not detected
    u8x8.setCursor(0, 1);
    u8x8.print("VEML6040 ERROR");
    while (1) {}
  }

  //RGBWSensor.setConfiguration(VEML6040_IT_320MS + VEML6040_AF_AUTO + VEML6040_SD_ENABLE);      // Sampling every 320ms 
  RGBWSensor.setConfiguration(VEML6040_IT_80MS + VEML6040_AF_AUTO + VEML6040_SD_ENABLE);         // Sampling every 80ms

  //RGBWSensor.setConfiguration(VEML6040_IT_80MS + VEML6040_TRIG_ENABLE + VEML6040_AF_FORCE + VEML6040_SD_ENABLE);              // Don't know what AF_FORCE mode means
  
  delay(1500);

  strip.begin();
  strip.show();                                                                                  // This clears the LEDS
  strip.setBrightness(100);

}

//====================================================================================================
void loop() {

  CurrentMillis = millis();

  if (CurrentMillis - getcolourMillis > 100) {
    getcolourMillis = CurrentMillis;

    red = RGBWSensor.getRed();
    green = RGBWSensor.getGreen();
    blue = RGBWSensor.getBlue();
    white = RGBWSensor.getWhite();
 
    strip.setPixelColor((sensor_number - 1), strip.Color(red, green, blue, white));                  // LED 0 is the first LED address
    //strip.clear();
    strip.show();

    sensor_number++;                                                                                 // Change to the next sensor
    if (sensor_number > 5) {
      sensor_number = 1;
    }

    if (sensor_number == 1) {
      digitalWrite(addA, LOW);                                                                       // Set 4051 Multiplexer address 0 (Sensor 1)
      digitalWrite(addB, LOW);
      digitalWrite(addC, LOW);
    }

    if (sensor_number == 2) {
      digitalWrite(addA, HIGH);                                                                      // Set 4051 Multiplexer address 1 (Sensor 2)
      digitalWrite(addB, LOW);
      digitalWrite(addC, LOW);
    }

    if (sensor_number == 3) {
      digitalWrite(addA, LOW);                                                                       // Set 4051 Multiplexer address 2 (Sensor 3)
      digitalWrite(addB, HIGH);
      digitalWrite(addC, LOW);
    }

    if (sensor_number == 4) {
      digitalWrite(addA, HIGH);                                                                      // Set 4051 Multiplexer address 3 (Sensor 4)
      digitalWrite(addB, HIGH);
      digitalWrite(addC, LOW);
    }

    if (sensor_number == 5) {
      digitalWrite(addA, LOW);                                                                       // Set 4051 Multiplexer address 4 (Sensor 5)
      digitalWrite(addB, LOW);
      digitalWrite(addC, HIGH);
    }

    delay(50);
  }

}

Any ideas on this?

Don't think you can have software I2C, so not sure how I can make this work now.
Certainly not running 5x processors for 5x sensors. Massively overkill.

I'll mark this as solved (although it isn't). I have abandoned the colour detectors.
It's getting too complicated to achieve what a light pipe can do.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.