TCS34725 Color sensor with Arduino Tutorial

A color sensor is widely used in various applications, including industrial automation, color detection in printing, and robotics. It detects the color of an object and provides an output signal that can be processed by a microcontroller. In this tutorial, we will explore how a color sensor works and how to interface it with an Arduino to create some cool projects.

What is a color sensor?

TCS34725 color sensor
TCS34725 color sensor

A color sensor detects the color of an object by analyzing the intensity of red, green, and blue (RGB) light reflected from it. It typically includes a photodetector, an optical filter, and a signal processing circuit that provides a digital or analog output representing the detected color.

There are many popular color sensors available in the market, such as TCS3200, TCS230, and TCS34725. In this tutorial, I am going to use TCS34725(more advanced and accurate) with Arduino.

TCS34725 color sensor pinout

TCS34725 Color sensor Pinout

A typical TCS34725 color sensor module consists of the following pins:

  • VIN – Power supply (3.3V to 5V)
  • GND – Ground
  • SDA – I2C data line (connects to Arduino’s A4)
  • SCL – I2C clock line (connects to Arduino’s A5)
  • LED – Controls the onboard white LED (can be connected to GND to disable)
  • INT – Interrupt output (optional, for advanced applications)

Key specifications of the color sensor

Below is a table with the specifications of the TCS34725 color sensor:

ParameterSpecification
Operational Voltage Range3.3V – 5V
Operational Current0.2 – 60 mA
Detectable ColorsRed, Green, Blue
Output TypeI2C Digital Output
IR Blocking FilterYes
White LEDIntegrated for uniform lighting
Integration TimeProgrammable (2.4 ms – 700 ms)

Construction

The TCS34725 color sensor consists of two main parts:

  1. Photodetector and IR-Blocking – The sensor has four photodiodes that measure red, green, blue, and clear (ambient) light intensity. The IR-blocking filter improves color accuracy by eliminating infrared interference.
  2. Electronic Module – The electronic module processes the detected light signals and converts them into an I2C-compatible output. It includes:
    • TCS34725 Sensor Chip – A high-sensitivity RGB color sensor with an IR filter.
    • ADC (Analog-to-Digital Converter) – Converts light intensity into digital values.
    • I2C Communication Interface – Allows easy data transmission to microcontrollers.
    • Onboard White LED – Provides a uniform light source for consistent color detection.

How does a color sensor work?

A color sensor detects and measures the intensity of red, green, and blue (RGB) light reflected from an object. It consists of a photodetector array that captures light and a white LED to ensure consistent illumination.

When light hits an object, different wavelengths are absorbed and reflected based on the object’s color. The sensor receives the reflected light and converts it into electrical signals, which are processed to determine the RGB composition.

An onboard ADC (Analog-to-Digital Converter) processes these signals and sends the data to a microcontroller, which interprets the color values. The microcontroller can then use this information to trigger specific actions, such as sorting objects by color, adjusting display settings, or controlling lighting effects.

RGB color detector project

RGB color detection using color sensor with Arduino

Now, let’s build a system where an RGB LED changes color based on the detected object color.

Components required:

  • Arduino UNO
  • TCS34725 Color Sensor Module
  • RGB LED or Individual LEDs (Red, Green, Blue)
  • Jumper Wires
  • External Power Supply (if required)

Circuit diagram:

Circuit diagram of TCS34725 color sensor with Arduino

Program

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

// Pins for RGB LEDs
#define RED_LED_PIN 3
#define GREEN_LED_PIN 5
#define BLUE_LED_PIN 6

Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X);

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

  if (!tcs.begin()) {
    Serial.println("No TCS34725 found ... check your connections");
    while (1)
      ;
  }

  // Initialize LED pins as output
  pinMode(RED_LED_PIN, OUTPUT);
  pinMode(GREEN_LED_PIN, OUTPUT);
  pinMode(BLUE_LED_PIN, OUTPUT);

  // Turn off all LEDs initially
  digitalWrite(RED_LED_PIN, LOW);
  digitalWrite(GREEN_LED_PIN, LOW);
  digitalWrite(BLUE_LED_PIN, LOW);
}

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

  // Normalize RGB values using clear channel (luminance)
  float red = r / (float)c * 255.0;
  float green = g / (float)c * 255.0;
  float blue = b / (float)c * 255.0;

  // Ensure values stay in bounds
  red = constrain(red, 0, 255);
  green = constrain(green, 0, 255);
  blue = constrain(blue, 0, 255);

  Serial.print("R:");
  Serial.print((int)red);
  Serial.print(" G:");
  Serial.print((int)green);
  Serial.print(" B:");
  Serial.println((int)blue);

  // Calculate differences between RGB values
  float diffRG = abs(red - green);
  float diffRB = abs(red - blue);
  float diffGB = abs(green - blue);

  // Turn off LEDs if differences are within the range of 30
  if (diffRG <= 50 && diffRB <= 50 && diffGB <= 50) {
    digitalWrite(RED_LED_PIN, LOW);
    digitalWrite(GREEN_LED_PIN, LOW);
    digitalWrite(BLUE_LED_PIN, LOW);
  } else {
    // Determine the dominant color and turn on the corresponding LED
    if (red > green && red > blue) {
      digitalWrite(RED_LED_PIN, HIGH);
      digitalWrite(GREEN_LED_PIN, LOW);
      digitalWrite(BLUE_LED_PIN, LOW);
    } else if (green > red && green > blue) {
      digitalWrite(RED_LED_PIN, LOW);
      digitalWrite(GREEN_LED_PIN, HIGH);
      digitalWrite(BLUE_LED_PIN, LOW);
    } else if (blue > red && blue > green) {
      digitalWrite(RED_LED_PIN, LOW);
      digitalWrite(GREEN_LED_PIN, LOW);
      digitalWrite(BLUE_LED_PIN, HIGH);
    } else {
      // If no dominant color, turn off all LEDs
      digitalWrite(RED_LED_PIN, LOW);
      digitalWrite(GREEN_LED_PIN, LOW);
      digitalWrite(BLUE_LED_PIN, LOW);
    }
  }

  delay(100);
}

Code explanation

#include <Wire.h>
#include "Adafruit_TCS34725.h"
  • Wire.h → Used for I2C communication (required for the TCS34725 sensor).
  • Adafruit_TCS34725.h → Library for interfacing with the TCS34725 color sensor.
#define RED_LED_PIN 3
#define GREEN_LED_PIN 5
#define BLUE_LED_PIN 6
  • Assigns PWM pins (3, 5, 6) for controlling Red, Green, and Blue LEDs.
Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X);
  • Initializes the TCS34725 sensor with:
    • Integration Time: 50ms (How long the sensor gathers light per reading).
    • Gain: 4X (Amplifies sensor readings for low-light conditions).
void setup() {
  Serial.begin(9600);
  • Starts serial communication at 9600 baud for debugging.
  if (!tcs.begin()) {
    Serial.println("No TCS34725 found ... check your connections");
    while (1);
  }
  • Checks if the color sensor is detected. If not, it stops execution (while(1); keeps the system in an infinite loop).
  pinMode(RED_LED_PIN, OUTPUT);
  pinMode(GREEN_LED_PIN, OUTPUT);
  pinMode(BLUE_LED_PIN, OUTPUT);
  • Sets the RGB LED pins as output.
  digitalWrite(RED_LED_PIN, LOW);
  digitalWrite(GREEN_LED_PIN, LOW);
  digitalWrite(BLUE_LED_PIN, LOW);
  • Turns off all LEDs initially.
  uint16_t r, g, b, c;
  tcs.getRawData(&r, &g, &b, &c);
  • Reads raw Red (r), Green (g), Blue (b), and Clear (c) values from the sensor.
  float red = r / (float)c * 255.0;  float green = g / (float)c * 255.0;
  float blue = b / (float)c * 255.0;
  • Normalizes the RGB values to a 0-255 range using the clear channel (c), which represents overall brightness.
  red = constrain(red, 0, 255);
  green = constrain(green, 0, 255);
  blue = constrain(blue, 0, 255);
  • Ensures RGB values stay within the valid range (0-255).
  Serial.print("R:");  Serial.print((int)red);
  Serial.print(" G:");
  Serial.print((int)green);
  Serial.print(" B:");
  Serial.println((int)blue);
  • Prints RGB values to the Serial Monitor.
float diffRG = abs(red - green);
float diffRB = abs(red - blue);
float diffGB = abs(green - blue);
  • Calculates the absolute difference between Red-Green (diffRG), Red-Blue (diffRB), and Green-Blue (diffGB).
  if (diffRG <= 50 && diffRB <= 50 && diffGB <= 50) {
    digitalWrite(RED_LED_PIN, LOW);
    digitalWrite(GREEN_LED_PIN, LOW);
    digitalWrite(BLUE_LED_PIN, LOW);
  }
  • If all RGB values are close (difference ≤ 50), it assumes a neutral color (gray/white) → Turns off all LEDs.
 if (red > green && red > blue) {
      digitalWrite(RED_LED_PIN, HIGH);
      digitalWrite(GREEN_LED_PIN, LOW);
      digitalWrite(BLUE_LED_PIN, LOW);
    } 
  • If Red is the strongest color, turn on the red LED and turn off others.
else if (green > red && green > blue) {
      digitalWrite(RED_LED_PIN, LOW);
      digitalWrite(GREEN_LED_PIN, HIGH);
      digitalWrite(BLUE_LED_PIN, LOW);
    }
  • If Green is the strongest color, turn on the green LED and turn off others.
    else if (blue > red && blue > green) {
      digitalWrite(RED_LED_PIN, LOW);
      digitalWrite(GREEN_LED_PIN, LOW);
      digitalWrite(BLUE_LED_PIN, HIGH);
    }
  • If Blue is the strongest color, turn on the blue LED and turn off others.
    else {
      digitalWrite(RED_LED_PIN, LOW);
      digitalWrite(GREEN_LED_PIN, LOW);
      digitalWrite(BLUE_LED_PIN, LOW);
    }
  • If no clear dominant color exists, turn off all LEDs.
  delay(100);
  • Waits 100ms before the next reading to avoid flickering

Visual color detection project

Detected color is being visually displayed on the laptop screen

Using the same color sensor setup with the Processing software, we will visualize the detected color on the screen. Just remove all the LEDs.

First, download the Processing software from here.

Install the software, then upload the program given below to your Arduino board.

Note: Make sure the USB cable is connected to the proper port on your laptop while running the software. Also, keep your serial monitor/plotter off.

Arduino program

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

// Pins for RGB LED
#define redpin 3
#define greenpin 5
#define bluepin 6
#define commonAnode true

byte gammatable[256];
Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X);

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

  if (!tcs.begin()) {
    Serial.println("No TCS34725 found ... check your connections");
    while (1)
      ;
  }

  // Gamma correction table
  for (int i = 0; i < 256; i++) {
    float x = i / 255.0;
    x = pow(x, 2.5);
    x *= 255.0;
    gammatable[i] = commonAnode ? 255 - x : x;
  }
}

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

  // Normalize RGB values using clear channel (luminance)
  float red = r / (float)c * 255.0;
  float green = g / (float)c * 255.0;
  float blue = b / (float)c * 255.0;

  // Ensure values stay in bounds
  red = constrain(red, 0, 255);
  green = constrain(green, 0, 255);
  blue = constrain(blue, 0, 255);

  Serial.print("R:\t");
  Serial.print((int)red);
  Serial.print("\tG:\t");
  Serial.print((int)green);
  Serial.print("\tB:\t");
  Serial.print((int)blue);
  Serial.print("\tC:\t");
  Serial.println(c);

  delay(100);
}

Next, paste this code inside this new software window and click on ‘Run’.

Processing code

import processing.serial.*;

Serial myPort;  // Serial port for communication
float red = 0, green = 0, blue = 0, clear = 0;  // RGB and clear values from Arduino

void setup() {
  size(400, 400);  // Window size
  String portName = Serial.list()[0];  // Automatically select the first available port
  myPort = new Serial(this, portName, 9600);  // Open serial port
  myPort.clear();  // Clear old data in the buffer
  myPort.bufferUntil('\n');  // Wait for a full line of data
}

void draw() {
  background(255);  // White background

  // Detect color name and adjust displayed color
  String detectedColor = detectColor(red, green, blue, clear);

  if (detectedColor.equals("No Color Detected")) {
    // Draw a red "X" for No Color Detected
    fill(255, 0, 0);  // Red color
    stroke(255, 0, 0);
    strokeWeight(8);
    line(100, 100, 300, 300);  // Diagonal line 1
    line(100, 300, 300, 100);  // Diagonal line 2
    noStroke();
  } else {
    // Set fill color based on detected color
    if (detectedColor.equals("Black")) {
      fill(0);  // Black
    } else if (detectedColor.equals("White")) {
      fill(255);  // White
    } else {
      fill(red, green, blue);  // Use detected RGB values for other colors
    }

    noStroke();
    rect(50, 50, width - 100, height - 100);  // Draw rectangle
  }

  // Display detected color name and values
  fill(0);  // Black text
  textSize(20);
  textAlign(CENTER);
  text("Detected Color: " + detectedColor, width / 2, 30);
  text("R: " + int(red) + " G: " + int(green) + " B: " + int(blue) + " C: " + int(clear), width / 2, height - 20);
}

void serialEvent(Serial myPort) {
  String data = myPort.readStringUntil('\n');  // Read Serial data
  if (data != null) {
    data = trim(data);  // Remove whitespace
    String[] values = split(data, '\t');  // Split by tab characters
    if (values.length >= 8) {  // Ensure we have R, G, B, C values
      try {
        // Parse and update RGB and clear values
        red = float(values[1]);
        green = float(values[3]);
        blue = float(values[5]);
        clear = float(values[7]);
      } catch (Exception e) {
        println("Error parsing values: " + e.getMessage());
      }
    }
  }
}

String detectColor(float r, float g, float b, float c) {
  if (c < 400) return "Black";  // Low clear value indicates black
  if (c > 1600 && abs(r - g) < 50 && abs(g - b) < 50) return "White";  // High clear, similar RGB values
  if (c > 600 && c < 1200 && abs(r - g) < 30 && abs(g - b) < 30) return "No Color Detected";  // Mid-range clear, no distinct color
  if (r > g && r > b) return "Red";
  if (g > r && g > b) return "Green";
  if (b > r && b > g) return "Blue";
  return "Unknown";
}

Photo of author

Vikas Gariyal

Electrical engineer by profession, I employ graphic design as a visual art to simplify and enhance electronic content for clarity and engagement, making complex ideas easily understandable. My work combines creativity and technology to create captivating and effective visual storytelling.

Leave a Comment