Language: EN

arduino-sensor-color-rgb-tcs34725

Measure RGB values with Arduino and TCS34725 color sensor

What is a TCS34725?

The TCS34725 is a digital color sensor that we can use with a processor like Arduino to measure the RGB values of the color of an object or light.

The TCS34725 is a complete integrated circuit that performs digital processing of color measurement, providing RGB and Clear values (unfiltered total measurement). Communication with the sensor is done via I2C, so its reading from a processor like Arduino is very simple.

It incorporates an infrared filter, which improves its accuracy in the presence of environmental noise. The measurement time and gain are adjustable by software. It has a wide sensitivity and a wide dynamic range of 3,800,000:1, and can even operate behind dark glass.

We can find it in commercial modules that incorporate a neutral light LED (4150°K) along with an integrated MOSFET for its control, so we can control the LED activation from the code.

In addition to I2C communication, the TCS34725 incorporates an interrupt pin along with a lower and upper threshold. When the light level is outside the threshold range, the TCS34725 generates an interrupt that remains active until it is reset by the controller.

Unlike other color sensors like the popular TCS3200, which are only capable of detecting basic colors, the TCS34725 is capable of providing a relatively accurate RGB measurement of the color being measured.

Of course, like any sensor, the TCS34725 is not perfect and has typical deviations of any sensor, so you will not get a completely accurate measurement. In general, color calibration is necessary.

The TCS34725 is a relatively modern sensor and one of the best color sensors available in the home (geek/maker) sector.

Price

TCS34725 sensors are cheap. We can find modules with the TCS34725 for around 2.70€ on international sellers on eBay and AliExpress.

arduino-tcs34725-componente

How does a TCS34725 work?

The TCS34725 is an optical sensor that incorporates a matrix of 3x4 photodiodes, along with 4 16-bit analog-to-digital converters (ADC) that perform the measurement of the photodiodes.

arduino-tcs34725-interior

The 3x4 matrix is formed by photodiodes filtered for red, green, blue, and unfiltered (clear). All sensors are filtered for infrared.

arduino-tcs34725-funcionamiento

The ADC converters integrate the measurement of the photodiodes, which is transferred to the internal registers of the TCS347, which incorporate a double buffer to ensure the integrity of the data.

rduino-tcs34725-microscopio

The state of the sensor and the sensor power state are controlled by an internal state machine, which controls all the functions of the TCS34725.

Assembly diagram

The connection of the modules that integrate the TCS34725 is simple, as communication is done through I2C. The TCS34725 power supply voltage is 3.3V, but commercial modules normally integrate a Vin output that allows for 5V power supply.

Therefore, we simply power the module from Arduino using GND and Vin and connect the SDA and SCL pins of Arduino with the corresponding pins of the sensor.

arduino-tcs34725-esquema

The LED pin controls the activation of the neutral light LED integrated in the module. The connection of this pin can be as follows:

  • Leave unconnected to keep it continuously on.
  • Connect to GND to turn off continuously.
  • Connect to a digital pin, to control its activation with digitalWrite().
  • Connect to the INT pin and control the activation with setInterrupt() from the library.

Viewed from Arduino, the connection would be as follows,

arduino-tcs34725-conexion

Code examples

To read the TCS34725 sensor, we will use the library developed by Adafruit, available at this link. The library incorporates several usage examples that are worth reviewing.

Next, we will see some usage examples of the TCS34725 sensor.

Read RGB values

In this first, very simple example, we read the sensor values and display them via serial port for visualization.

#include <Wire.h>
#include "Adafruit_TCS34725.h"
   
/* Initialise with default values (int time = 2.4ms, gain = 1x) */
// Adafruit_TCS34725 tcs = Adafruit_TCS34725();

Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_700MS, TCS34725_GAIN_1X);

void setup(void) {
  Serial.begin(9600);
  
  if (!tcs.begin()) 
  {
    Serial.println("Error al iniciar TCS34725");
    while (1) delay(1000);
  }

}

void loop(void) {
  uint16_t r, g, b, c, colorTemp, lux;
  
  tcs.getRawData(&r, &g, &b, &c);
  colorTemp = tcs.calculateColorTemperature(r, g, b);
  lux = tcs.calculateLux(r, g, b);
  
  Serial.print("Temperatura color: "); Serial.print(colorTemp, DEC); Serial.println(" K");
  Serial.print("Lux : "); Serial.println(lux, DEC);
  Serial.print("Rojo: "); Serial.println(r, DEC);
  Serial.print("Verde: "); Serial.println(g, DEC);
  Serial.print("Azul: "); Serial.println(b, DEC);
  Serial.print("Clear: "); Serial.println(c, DEC);
  Serial.println(" ");
  delay(1000);
}

Classify colors

In the second example, we will read the RGB values and try to determine the color we are reading. To make it easier, we convert the RGB values to HSV with the ColorConverter library.

To determine the color, we use the Hue of the measured color. For fine-tuning, it will be necessary to calibrate the sensor by testing colors and adjusting the conditional values.

#include <Wire.h>
#include "Adafruit_TCS34725.h"
#include "RGBConverterLib.h"

Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_1X);

void setup()
{
  Serial.begin(9600);

  if (!tcs.begin())
  {
    Serial.println("Error al iniciar TCS34725");
    while (1) delay(1000);
  }
}

void loop()
{
  uint16_t clear, red, green, blue;

  tcs.setInterrupt(false);
  delay(60); // Takes 50ms to capture the color
  tcs.getRawData(&red, &green, &blue, &clear);
  tcs.setInterrupt(true);

  // Make rgb measurement relative
  uint32_t sum = clear;
  float r, g, b;
  r = red; r /= sum;
  g = green; g /= sum;
  b = blue; b /= sum;

  // Scale rgb to bytes
  r *= 256; g *= 256; b *= 256;

  // Convert to hue, saturation, value
  double hue, saturation, value;
  RGBConverterLib::RgbToHsv(static_cast<uint8_t>(r), static_cast<uint8_t>(g), static_cast<uint8_t>(b), hue, saturation, value);

  // Show color name
  printColorName(hue * 360);

  delay(1000);
}

void printColorName(double hue)
{
  if (hue < 15)
  {
    Serial.println("Red");
  }
  else if (hue < 45)
  {
    Serial.println("Orange");
  }
  else if (hue < 90)
  {
    Serial.println("Yellow");
  }
  else if (hue < 150)
  {
    Serial.println("Green");
  }
  else if (hue < 210)
  {
    Serial.println("Cyan");
  }
  else if (hue < 270)
  {
    Serial.println("Blue");
  }
  else if (hue < 330)
  {
    Serial.println("Magenta");
  }
  else
  {
    Serial.println("Red");
  }
}

Clone color on WS2812b strip

In the last example, we will use an RGB LED WS2812b strip to “clone” the color we read on the color sensor.

The example is very simple, on one hand we read the color with the TCS34725. On the other, we use the Fastled library to create a trail effect on the WS2812b strip. The gamma conversion table adapts the colors read to the color perception of the human eye.

#include <Wire.h>
#include "Adafruit_TCS34725.h"
#include "FastLED.h"
FASTLED_USING_NAMESPACE


#define DATA_PIN    6

#define LED_TYPE    WS2812

#define COLOR_ORDER GRB

#define BRIGHTNESS    250

#define FRAMES_PER_SECOND 250

Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_1X);

const unsigned long INTERVAL = 2000;
const int NUM_LEDS = 16;
CRGB leds[NUM_LEDS];

byte gammatable[256];

float r, g, b;

void setup()
{
  Serial.begin(9600);

  if (!tcs.begin())
  {
    Serial.println("Error al iniciar TCS34725");
    while (1) delay(1000);
  }
  
  delay(1000);
  FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);
  for (int i=0; i<256; i++)
  {
      float x = i;
      x /= 255;
      x = pow(x, 2.5);
      x *= 255;
      gammatable[i] = x;  
  }
}

void loop()
{
  readColor();
  calculateLeds(); 
  FastLED.show();
  FastLED.delay(1000 / FRAMES_PER_SECOND);
}

void readColor()
{
  uint16_t clear, red, green, blue;

  tcs.setInterrupt(false);
  delay(60);
  tcs.getRawData(&red, &green, &blue, &clear);
  tcs.setInterrupt(true);

  uint32_t sum = clear;
  r = red; r /= sum;
  g = green; g /= sum;
  b = blue; b /= sum;

  r *= 256;
  g *= 256;
  b *= 256;
}

void calculateLeds()
{
  fadeToBlackBy(leds, NUM_LEDS, 20);

  uint8_t pixel;
  unsigned long tCurrent = millis();
  pixel = (tCurrent % INTERVAL) * NUM_LEDS / INTERVAL;
  leds[pixel] = CRGB(gammatable[(int)r], gammatable[(int)g], gammatable[(int)b]);
}

This is the result

Download the code

All the code from this post is available for download on Github. github-full