Arduino library · Sensors

Adafruit TCS34725: red, green, blue and clear counts

The TCS34725 is an RGB color sensor with a fourth, unfiltered clear channel, usually sold on a breakout with a white LED beside it to light whatever it is pointed at. Adafruit’s library talks to it at 0x29 and returns four 16-bit counts per reading.

Built in on Mokxi: #include <Adafruit_TCS34725.h> and it builds, with nothing to install. Free, and no account needed.

What Adafruit TCS34725 does

Two settings decide what those counts mean. The integration time, from 2.4 ms to around 700 ms, is how long the chip gathers light before it reports, and the gain multiplies the result by 1, 4, 16 or 60. A short time and low gain suit a bright scene; a dark object needs more of both. Push too far and the counts pin at the top, so keep an eye on the clear channel.

Raw counts depend on how bright the light is as much as on the color. Sorting projects divide each of red, green and blue by their total, which gives shares that hold steady as brightness changes, and compare those with a table of known colors. The color sorter below does exactly that before swinging its servo to a bin. calculateLux() and calculateColorTemperature_dn40() turn the same counts into lux and kelvin, and the clear-channel interrupt with its persistence is simulated as well.

Library Manager nameAdafruit TCS34725
AuthorAdafruit
Include#include <Adafruit_TCS34725.h>
Boardsevery board Mokxi compiles for but ATtiny85
In the simulatorSimulated: it runs against the part the way it does on the bench.
Parts it drivesColor sensor, TCS34725

Install it

It builds on every board Mokxi compiles for but ATtiny85.

In Mokxi it is built in: #include <Adafruit_TCS34725.h> and the sketch compiles, with no download, no zip and no Library Manager.

On a real board, install "Adafruit TCS34725" by Adafruit from the Arduino IDE’s Library Manager (Sketch, Include Library, Manage Libraries), or add Adafruit TCS34725 to lib_deps in PlatformIO. Mokxi follows the calls of release 1.4.4, so a sketch written here builds there too.

The calls you will use

In the order a sketch meets them.

Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X)

Creates the driver with an integration time and a gain. With no arguments it uses 2.4 ms and 1x, which reads close to zero indoors.

tcs.begin()

Reads the ID register, applies the settings and starts the color cycles. Returns false when nothing answers at 0x29.

tcs.getRawData(&r, &g, &b, &c)

The four counts as uint16_t. It then waits one integration time, so a long setting slows loop() by that much.

uint16_t r, g, b, c;
tcs.getRawData(&r, &g, &b, &c);

tcs.calculateColorTemperature_dn40(r, g, b, c)

Correlated color temperature in kelvin from all four counts. calculateColorTemperature(r, g, b) is the older three-count method.

tcs.calculateLux(r, g, b)

An estimate of illuminance in lux worked out from the three color counts.

tcs.setGain(TCS34725_GAIN_16X)

Changes the gain while running; setIntegrationTime(TCS34725_INTEGRATIONTIME_154MS) does the same for the time. Auto-ranging code steps these up or down from the clear count.

tcs.getRGB(&red, &green, &blue)

Each channel as a share of the clear count scaled to 0 to 255, as floats, ready to drive an RGB LED.

tcs.setInterrupt(true)

Enables the clear-channel interrupt. setIntLimits(low, high) sets the window it watches, and clearInterrupt() releases the INT pin after it fires.

Example: Color sorter

On the Arduino Uno R3. It runs in the browser exactly as printed.

sketch.ino · Arduino Uno R3
// Color sorter: a TCS34725 looks at the candy in front of it and a servo
// swings the chute to that color's bin, as in the candy and bead sorters
// people build.
//
//   TCS34725   SDA -> A4   SCL -> A5   VIN -> 5 V   GND -> GND   (LED left high: lit)
//   servo      signal -> 9   red -> 5 V   brown -> GND
//
// The sensor gives four counts: red, green, blue and clear. Their shares of
// the total say what color it is whatever the brightness, so the sketch
// compares them with a table of the six colors it knows, measured once with
// the LED on, and picks the nearest. A low clear count is an empty chute.
//
// In the simulator the sorter's feed disc brings the candies one at a time:
// watch the chute move, and the candy land in its bin.

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

Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X);
Servo chute;

const int SERVO_PIN = 9;
const uint16_t EMPTY_BELOW = 1500;  // clear count of the empty chute

struct Reference {
  const char *name;
  uint16_t red, green, blue;  // shares of the total, in thousandths
  uint8_t angle;              // where the chute points for this bin
};

const Reference COLORS[] = {
  {"red", 647, 203, 148, 15},
  {"orange", 566, 342, 90, 45},
  {"yellow", 475, 431, 92, 75},
  {"green", 192, 524, 283, 105},
  {"blue", 137, 313, 549, 135},
  {"purple", 324, 243, 431, 165},
};
const uint8_t COUNT = sizeof(COLORS) / sizeof(COLORS[0]);

int8_t last = -2;

void setup() {
  Serial.begin(9600);
  chute.attach(SERVO_PIN);
  chute.write(90);
  if (!tcs.begin()) {
    Serial.println("No TCS34725 found ... check your connections");
    while (1) delay(10);
  }
  Serial.println("Color sorter ready");
}

// The nearest color in the table, or -1 for an empty chute.
int8_t classify(uint16_t r, uint16_t g, uint16_t b, uint16_t c) {
  if (c < EMPTY_BELOW) return -1;
  uint32_t total = (uint32_t)r + g + b;
  int32_t rs = (uint32_t)r * 1000 / total;
  int32_t gs = (uint32_t)g * 1000 / total;
  int32_t bs = (uint32_t)b * 1000 / total;
  int8_t best = 0;
  int32_t bestDistance = 0x7fffffff;
  for (uint8_t i = 0; i < COUNT; i++) {
    int32_t dr = rs - COLORS[i].red;
    int32_t dg = gs - COLORS[i].green;
    int32_t db = bs - COLORS[i].blue;
    int32_t d = dr * dr + dg * dg + db * db;
    if (d < bestDistance) {
      bestDistance = d;
      best = i;
    }
  }
  return best;
}

void loop() {
  uint16_t r, g, b, c;
  tcs.getRawData(&r, &g, &b, &c);
  int8_t color = classify(r, g, b, c);
  if (color == last) return;
  last = color;
  if (color < 0) {
    Serial.println("chute empty");
    return;
  }
  Serial.print(COLORS[color].name);
  Serial.print(" -> bin ");
  Serial.print(color + 1);
  Serial.print("  (R ");
  Serial.print(r);
  Serial.print(" G ");
  Serial.print(g);
  Serial.print(" B ");
  Serial.print(b);
  Serial.print(" C ");
  Serial.print(c);
  Serial.println(")");
  chute.write(COLORS[color].angle);
  delay(300);
}

Open it in the editor, wired and ready to run · Color sorter: the project page

Common errors and how to fix them

No TCS34725 found ... check your connections

begin() saw no reply or the wrong ID at 0x29. Check the bus wiring, and that no other device on the same wires uses 0x29, such as a VL53L0X or VL53L1X distance sensor.

All four counts read 0 or close to it

The default constructor uses 2.4 ms at 1x, far too little for a room. Pass a longer time and more gain, as the sorter does with 50 ms and 4x, and make sure the LED is lit.

Every object is classified as the same color

The counts are probably saturated, typically from the LED at close range with a high gain. Lower the gain or the time until the clear count stays well below 65535, then measure the color table again.

Colors change when the room lights change

Raw counts mix brightness into color. Divide red, green and blue by their sum and compare those shares, with the sensor’s own LED doing the lighting.

Questions and answers

What is the clear channel for?

It sees all visible light with no color filter, so it measures brightness. The sorter uses a low clear count to tell an empty chute from a candy.

Which integration time should I start with?

The tutorial’s 50 ms at 4x is a fair start under the module’s LED. Lengthen it for dark objects and shorten it if the clear count nears the top.

Projects that use Adafruit TCS34725

Built-in projects that include it. Each page has the full sketch and opens in the editor, already wired.

Try Adafruit TCS34725 without installing anything

Open the example, change the sketch, and keep your version in a free account.