Arduino - TCS3200D/TCS230 Color Sensor

This tutorial demonstrates interfacing a TCS3200D/TCS230 color recognition sensor with Arduino to measure and identify RGB values from various objects. You'll master sensor calibration techniques and color detection programming.

Topics covered:

Arduino with TCS3200D TCS230 color recognition sensor module tutorial

About TCS3200D/TCS230 Color Sensor

Built around an 8x8 photodiode array, the TCS3200D/TCS230 identifies colors through specialized optical filtering. The 64-diode grid includes 16 red-filtered photodiodes, 16 green-filtered units, 16 blue-filtered sensors, and 16 unfiltered (clear) photodiodes. Color detection occurs by switching between filter types and analyzing the square-wave frequency output that represents light intensity.

Integrated white LEDs on most modules provide consistent target illumination, ensuring stable measurements across varying ambient conditions and improving low-light performance.

Pinout

Connection pins on the TCS3200D/TCS230 module include:

  • VCC pin: Power supply connection (+5V).
  • GND pin: Ground connection (0V).
  • S0, S1 pins: Frequency scaling control inputs.
  • S2, S3 pins: Color filter selection inputs.
  • OUT pin: Frequency output (square wave).
  • OE pin: Output enable control (active when LOW). Most commercial modules internally ground this pin, eliminating external wiring. If not pre-connected, tie it to GND manually.
TCS3200 TCS230 color sensor module pinout diagram showing VCC GND S0 S1 S2 S3 OUT pins

How It Works

Operating the sensor requires configuring two key parameters: the active color channel and signal strength. Control pin pairs manage these settings:

Output scaling via S0 and S1:

  • Both LOW: Power-down mode
  • S0 LOW, S1 HIGH: 2% frequency scaling
  • S0 HIGH, S1 LOW: 20% frequency scaling
  • Both HIGH: Full 100% scaling

Filter selection via S2 and S3:

  • Both LOW: Red channel active
  • S2 LOW, S3 HIGH: Blue channel active
  • S2 HIGH, S3 LOW: Clear channel (unfiltered)
  • Both HIGH: Green channel active

The OUT pin generates square-wave signals ranging from approximately 2 Hz to 500 kHz. Higher frequencies indicate stronger light intensity for the selected channel. Measuring pulse width with pulseIn() provides the inverse relationship—shorter pulses mean brighter colors. Post-calibration conversion yields standard RGB values.

Maximizing Reading Accuracy

  • Maintain 1-3 cm distance between sensor and target, keeping positioning consistent.
  • Activate onboard white LEDs for uniform lighting conditions.
  • Minimize ambient light interference by shielding the sensor for improved precision.

Wiring Diagram

Connection schematic for TCS3200 color sensor and Arduino:

TCS3200 Color SensorArduino
VCC5V
GNDGND
S0Pin 4
S1Pin 3
S2Pin 6
S3Pin 5
OUTPin 7
Arduino and TCS3200 color sensor wiring diagram showing connection between pins

This image is created using Fritzing. Click to enlarge image

Arduino Code - Sensor Calibration via Pulse Width

Environmental calibration proves essential because raw sensor output varies with multiple factors: onboard LED intensity, target distance, surface reflection properties, and surrounding illumination. Consider these variables as measurement interference. Calibration quantifies this interference by establishing minimum and maximum boundaries for each color channel, enabling accurate conversion to the standard 0–255 RGB scale for your specific setup.

/* * Created by ArduinoGetStarted.com * * This example code is in the public domain * * Tutorial page: https://arduinogetstarted.com/tutorials/arduino-tcs3200d-tcs230-color-sensor */ // Define color sensor pins #define PIN_S0 4 #define PIN_S1 3 #define PIN_S2 6 #define PIN_S3 5 #define PIN_sensorOut 7 // Variables for Color Pulse Width Measurements int redPW = 0; int greenPW = 0; int bluePW = 0; // Variables to track min and max pulse widths for calibration int redMin = 10000, redMax = 0; int greenMin = 10000, greenMax = 0; int blueMin = 10000, blueMax = 0; void setup() { // Set S0 - S3 as outputs pinMode(PIN_S0, OUTPUT); pinMode(PIN_S1, OUTPUT); pinMode(PIN_S2, OUTPUT); pinMode(PIN_S3, OUTPUT); // Set Pulse Width scaling to 20% digitalWrite(PIN_S0, HIGH); digitalWrite(PIN_S1, LOW); // Set Sensor output as input pinMode(PIN_sensorOut, INPUT); // Setup Serial Monitor Serial.begin(9600); Serial.println("=== TCS3200 Calibration ==="); Serial.println("Point the sensor at different objects (white, black, colors)."); Serial.println("Min and Max values are tracked automatically."); Serial.println("When values look stable, note them down for the next code."); Serial.println("------------------------------------------"); } void loop() { // Read Red Pulse Width redPW = getRedPW(); // Delay to stabilize sensor delay(200); // Read Green Pulse Width greenPW = getGreenPW(); // Delay to stabilize sensor delay(200); // Read Blue Pulse Width bluePW = getBluePW(); // Delay to stabilize sensor delay(200); // Update min and max values if (redPW < redMin) redMin = redPW; if (redPW > redMax) redMax = redPW; if (greenPW < greenMin) greenMin = greenPW; if (greenPW > greenMax) greenMax = greenPW; if (bluePW < blueMin) blueMin = bluePW; if (bluePW > blueMax) blueMax = bluePW; // Print the pulse width values with min/max Serial.print("Red PW = "); Serial.print(redPW); Serial.print(" - Green PW = "); Serial.print(greenPW); Serial.print(" - Blue PW = "); Serial.println(bluePW); Serial.print(" Min -> R:"); Serial.print(redMin); Serial.print(" G:"); Serial.print(greenMin); Serial.print(" B:"); Serial.println(blueMin); Serial.print(" Max -> R:"); Serial.print(redMax); Serial.print(" G:"); Serial.print(greenMax); Serial.print(" B:"); Serial.println(blueMax); Serial.println("------------------------------------------"); delay(1000); } // Function to read Red Pulse Widths int getRedPW() { // Set sensor to read Red only digitalWrite(PIN_S2, LOW); digitalWrite(PIN_S3, LOW); // Read the Pulse Width int PW = pulseIn(PIN_sensorOut, LOW); // Return the value return PW; } // Function to read Green Pulse Widths int getGreenPW() { // Set sensor to read Green only digitalWrite(PIN_S2, HIGH); digitalWrite(PIN_S3, HIGH); // Read the Pulse Width int PW = pulseIn(PIN_sensorOut, LOW); // Return the value return PW; } // Function to read Blue Pulse Widths int getBluePW() { // Set sensor to read Blue only digitalWrite(PIN_S2, LOW); digitalWrite(PIN_S3, HIGH); // Read the Pulse Width int PW = pulseIn(PIN_sensorOut, LOW); // Return the value return PW; }

Quick Steps

  • Open the calibration code in Arduino IDE
  • Upload to your Arduino board using the Upload button
  • Launch Serial Monitor to view live readings with Min/Max tracking
  • Scan various objects with the sensor: white surfaces (paper), black items, plus assorted colored objects
  • Observe automatic Min/Max value updates as extremes are recorded
  • When numbers stabilize (typically 10-20 seconds), record all six calibration constants
COM6
Send
=== TCS3200 Calibration === Point the sensor at different objects (white, black, colors). Min and Max values are tracked automatically. When values look stable, note them down for the next code. ------------------------------------------ Red PW = 42 - Green PW = 55 - Blue PW = 60 Min -> R:42 G:55 B:60 Max -> R:42 G:55 B:60 ------------------------------------------ Red PW = 210 - Green PW = 185 - Blue PW = 172 Min -> R:42 G:55 B:60 Max -> R:210 G:185 B:172 ------------------------------------------ Red PW = 44 - Green PW = 57 - Blue PW = 61 Min -> R:42 G:55 B:60 Max -> R:210 G:185 B:172 ------------------------------------------
Autoscroll Show timestamp
Clear output
9600 baud  
Newline  

For example, from the output above, your calibration values would be:

  • RedMin = 42, redMax = 210
  • GreenMin = 55, greenMax = 185
  • BlueMin = 60, blueMax = 172

Arduino Code - Reading RGB Color Values

/* * Created by ArduinoGetStarted.com * * This example code is in the public domain * * Tutorial page: https://arduinogetstarted.com/tutorials/arduino-tcs3200d-tcs230-color-sensor */ // Define color sensor pins #define PIN_S0 4 #define PIN_S1 3 #define PIN_S2 6 #define PIN_S3 5 #define PIN_sensorOut 7 // Calibration Values // Replace these values with your actual calibration data from the previous step int redMin = 0; // Red minimum pulse width int redMax = 0; // Red maximum pulse width int greenMin = 0; // Green minimum pulse width int greenMax = 0; // Green maximum pulse width int blueMin = 0; // Blue minimum pulse width int blueMax = 0; // Blue maximum pulse width // Variables for Color Pulse Width Measurements int redPW = 0; int greenPW = 0; int bluePW = 0; // Variables for final Color values int redValue; int greenValue; int blueValue; void setup() { // Set S0 - S3 as outputs pinMode(PIN_S0, OUTPUT); pinMode(PIN_S1, OUTPUT); pinMode(PIN_S2, OUTPUT); pinMode(PIN_S3, OUTPUT); // Set Pulse Width scaling to 20% digitalWrite(PIN_S0, HIGH); digitalWrite(PIN_S1, LOW); // Set Sensor output as input pinMode(PIN_sensorOut, INPUT); // Setup Serial Monitor Serial.begin(9600); } void loop() { // Read Red value redPW = getRedPW(); // Map to value from 0-255 redValue = map(redPW, redMin, redMax, 255, 0); // Delay to stabilize sensor delay(200); // Read Green value greenPW = getGreenPW(); // Map to value from 0-255 greenValue = map(greenPW, greenMin, greenMax, 255, 0); // Delay to stabilize sensor delay(200); // Read Blue value bluePW = getBluePW(); // Map to value from 0-255 blueValue = map(bluePW, blueMin, blueMax, 255, 0); // Delay to stabilize sensor delay(200); // Print output to Serial Monitor Serial.print("Red = "); Serial.print(redValue); Serial.print(" - Green = "); Serial.print(greenValue); Serial.print(" - Blue = "); Serial.println(blueValue); } // Function to read Red Pulse Widths int getRedPW() { // Set sensor to read Red only digitalWrite(PIN_S2, LOW); digitalWrite(PIN_S3, LOW); // Read the Pulse Width int PW = pulseIn(PIN_sensorOut, LOW); // Return the value return PW; } // Function to read Green Pulse Widths int getGreenPW() { // Set sensor to read Green only digitalWrite(PIN_S2, HIGH); digitalWrite(PIN_S3, HIGH); // Read the Pulse Width int PW = pulseIn(PIN_sensorOut, LOW); // Return the value return PW; } // Function to read Blue Pulse Widths int getBluePW() { // Set sensor to read Blue only digitalWrite(PIN_S2, LOW); digitalWrite(PIN_S3, HIGH); // Read the Pulse Width int PW = pulseIn(PIN_sensorOut, LOW); // Return the value return PW; }

Quick Steps

  • Locate the calibration variable declarations near the code beginning:
int redMin = 0; // Red minimum pulse width int redMax = 0; // Red maximum pulse width int greenMin = 0; // Green minimum pulse width int greenMax = 0; // Green maximum pulse width int blueMin = 0; // Blue minimum pulse width int blueMax = 0; // Blue maximum pulse width
  • Update ALL six zero values using calibration data from the previous exercise. Example transformation (using calibration results redMin = 42, redMax = 210, greenMin = 55, greenMax = 185, blueMin = 60, blueMax = 172):
int redMin = 42; int redMax = 210; int greenMin = 55; int greenMax = 185; int blueMin = 60; int blueMax = 172;
  • Upload the modified code to Arduino
  • Position a colored target before the sensor
  • Monitor RGB output in Serial Monitor
COM6
Send
Red = 210 - Green = 35 - Blue = 20 Red = 25 - Green = 200 - Blue = 40 Red = 30 - Green = 45 - Blue = 215
Autoscroll Show timestamp
Clear output
9600 baud  
Newline  

The RGB values are now mapped to the standard 0-255 range. Lower pulse widths (more light) produce higher RGB values, and higher pulse widths (less light) produce lower RGB values.

Applications

Now that you can read RGB values, you can build projects like:

  • Color sorter: Sort objects by color (red, green, blue)
  • Color matching game: Check if two objects are the same color
  • Line follower robot: Follow colored lines on the floor
  • Quality control: Detect defective products by color
  • Color-activated alarm: Trigger a buzzer or LED when a specific color is detected

Video Tutorial

We are considering to make the video tutorials. If you think the video tutorials are essential, please subscribe to our YouTube channel to give us motivation for making the videos.

The Best Arduino Starter Kit

See Also

※ OUR MESSAGES