The TCS230 color sensor module

The TCS230 color detector can measure three colors plus white. The three colors are the primary colors Red, Green and Blue. Since any color can be created from different levels of these primary colors, the unit can tell you the color composition of a light source. The four LEDs are there to illuminate the subject with an even light source making it easier to get a light measurement.

Note: Light measurements should be made at about 1~3cm to get a more accurate result.

You can use the TCS230 (or newer device TCS3200 see here for differences) where you need to take action based on the color of an object. The device does react to infrared so may need an infrared filter or use the device in an enclosed space.

The TSC230 chip mounted on a breakout board.

tcs230 front view

How the TCS230 works

Instead of giving an output for each color the device outputs a single signal which is a square wave. The frequency of the square wave is proportional to the amount of light falling on a set of light detecting diodes. Since there are four different sources of information red, green, blue and clear photodiodes you would expect four outputs. Instead you control which set of diodes is connected to the output using two digital control inputs. So only one set of photodiodes is connected at a time to generate the output.

In the photo below you can see the individual red,blue,green and clear filters. It's a bit blurry - but that was a very difficult photo to get and remember each section is 120um square so each one is about the width of a hair (17-181um) [Brian ley]!

Closeup of the TCS230

tcs230 closup showing R,G,B,& clear filters

Zoomed in filters of the TCS230 from image above.

filters tcs230

In fact several photodiodes for each color are connected in parallel and these are spread evenly over the sensor surface, as you can see in the photo above, so you can obtain an average reading for each color output. For the TCS230 there are a total of 64 photodiodes. 16 have a red filter above them, 16 have a green filter, 16 have a blue filter and 16 have a clear filter.

Block Diagram showing how the Chip works

tcs230 Blockdiagram of operation

Note: There is also an output enable that tristates the output when high (OEn). This would allow you to attach several different TCS230 chips to detect colors from different parts of a machine using only one input. When using only one device set it low.

Signal output

The signal output by the TCS230 is obtained by a current to frequency converter that takes as its input the average current from the selected set of photodiodes. The idea is that you switch one set on, take a reading and then switch to the next set until all four measurements are done. The output signal is a square wave with even mark to space ratio: 50%high, 50%low.

Frequency Dividers

The square wave output by the device can also be divided down and this allows slower processors to to make measurements more easily. There is no measurement penalty as the divided down output is simply an average of the original. The only disadvantage is that because the signal is of a lower frequency you can not make measurements as quickly.

If it was important to make a light reading very fast then you would want to use a high speed processor and not divide down the output signal. You can imagine that this might become important in an industrial process measurement e.g. for measuring the state of a product e.g. you would want to quickly measure the color of an item on a conveyor belt and reject it if it as the wrong color.

Frequency outputs

The maximum full scale frequency output from the TCS230 are shown below for the scaling factors controlled by S0 and S1

Control Scaling
S0 S1 Max output frequency kHz %scale
H H 600kHz 100%
H L 120kHz 20%
L H 12kHz 2%
L S1 = L Power down Power down
Control Photodiodes
S2 S3 Selected Photodiodes
L L Red
L H Blue
H L Clear
H H Green

Note: For the TCS230, TCS3200 and TCS3210 the above parameters are identical.

Difference between TC230 and TCS3200

Specification of the TCS230 where different to TCS3200 and TCS3210

Parameter TCS230 TCS3200/[TCS3210] Units
Number of photodiodes 64 64 / [24] -
Power on current 2 (max 3) 1.4 (max 2) mA
Power down current 7 (max 15) 0.1 (max 0.1) uA
min operating temp. 0 -40 °C

Note: Typical values are shown above.

From the above table you can see that the TCS3200 and TCS3210 have been optimized for low power operation and also for operation below 0°C.

TCS230 Circuit Layout

Figure 1 : Fritzing Layout for the TCS230 or TCS3200 breakout board
tcs230 connections to Arduino
View larger image here.

How to use the TCS230

On an arduino the easiest way to use the TCS230 is to use the pulseIn() function, first setting the dividers to output the lowest frequency.

Software Library and versions

Arduino IDE Version

Version : 1.8.3


None used: Just use the function pulseIn.

Example Sketch for Arduino UNO

Hitting any key will both show you the current sensor readings (RGB) and try to detect the current color. Current colors are stored in two arrays:

  • int RGB[[NUMCOL][3]
  • char colname[NUMCOL][11]

The RGB array holds the color values to be found while the colname array holds the text you want to display for the corresponding RBG value.

Warning: When you first use the code, the colors will NOT be detected correctly since your lighting setup and detection objects will be different to mine. Follow the calibration process below.

TCS230 Calibration

The sensor is very sensitive to any changes in light and in practice that means any slight distance changes from the sensor to the object will cause a different reading. Additionally any ambient light changes will also cause a different reading.

So to make accurate (repeatable) readings you need to control two elements:

  • Ambient light.
  • Distance to object.

To calibrate the sensor, push the sensor down onto colored paper as even a small adjustment fails since the sensor is extremely sensitive.

Set the serial monitor to 115200 Baud and push the sensor down and hit the 'Enter' key in the serial monitor input field. This will then show you the current RGB values. Copy these values into the RBG array and set the equivalent colname text. Recompile (or add some different colored objects). Recompile and check that the 'color' is found.

Now you can test the 'objects' with the code now reporting the color of the object.

Click in the code below to copy it to the clipboard.

// Detect colors using TCS230.

// Arduino uno pins for control of TCS230
#define TCS320_OE 7
#define TCS320_S0 10
#define TCS320_S1 11
#define TCS320_S2 2
#define TCS320_S3 3
#define TCS320_OUT 4

#define variance 50  // Acceptable detection error 2%.

#define SEL_RED  \
#define SEL_GREEN \
#define SEL_BLUE \
#define SEL_CLEAR \

#define TWO_PER \

#define debug(a) Serial.println((a));

#define NUMCOL 5

// int RGB[NUMCOL][3]; // Five colors with 3 elements.
// Array of NUMCOL strings len 10. 11 for null.
// char colname[NUMCOL][11];

// Typical values for 2% dividers (set variance to 50).
int RGB[NUMCOL][3]={

char colname[NUMCOL][11]={

void setup() {



   digitalWrite(TCS320_OE,LOW); // On always.

   Serial.println("TCS230 color detector");

unsigned long get_TCS230_reading(void) {
  unsigned long val;
  val = pulseIn(TCS320_OUT,HIGH,20000); // 2000us=2ms  2Hz min.
  return val;

static int clr,red,green,blue;

uint16_t detect(void) {
   unsigned long val;

    red = val = get_TCS230_reading();
    Serial.print("RED: "); Serial.print(val);

    green = val = get_TCS230_reading();
    Serial.print(" GREEN: "); Serial.print(val);

    blue = val = get_TCS230_reading();
    Serial.print(" BLUE: "); Serial.print(val);

    Serial.print(" \n");

int withinEQ(int c, int xl, int xh) {
   if (c>=xl && c<=xh) return 1;
   return 0;

// Compare a value to a value and variance.
int compare(int c, int v, int err) {
int xh=v+err, xl=v-err;
   if (withinEQ(c,xl,xh)) return 1;
   return 0;

void loop() {
uint8_t chr,i,fnd;

   if (Serial.available()>0) {

      chr =; // Consume.

      // Find color match.
      for (i=0;i<NUMCOL;i++) {
         if ( compare(red,RGB[i][0],variance) &&
              compare(green,RGB[i][1],variance) &&
            ) { // Found
              Serial.print("Col is :");
      if (!fnd) Serial.println("NOT Found");

Why does the code use 2% dividers?

You can choose to use raw 100%, 20% or 2% output and most other code examples use 20%.

The function used to measure the output of the chip is pulseIn, which is accurate to 4us, so to get maximum accuracy we need an output that is big enough compared to the accuracy of pulseIn.

The following data is taken from my setup which is probably an average lighting setup in an office. These are provided to show the typical minimum and maximum periods in microseconds that are available for measurement using the pulseIn function.

The question to be answered is:What effect does changing the divider output from the TCS230 have on the input periods to be measured.

Typical output for 2% dividers:






The maximum and minimum periods from the above measurements are:

1199us and 188us

Here the frequencies involved are :

1.0/1199e-6 = 834Hz to 1.0/188e-6 = 5319Hz (5.3kHz). (max is 12kHz - T=83us).

Typical values for 20% dividers:






The maximum and minimum periods from the above measurements are:

119us and 18us.

Here the frequencies involved are :

1.0/119e-6 = 8403Hz to 1.0/18e-6 = 55555Hz (55kHz). (max is 120kHz - T=8.3us).

Typical values for raw output

The quoted max frequency is 600kHz - not measured. The period will be 1.6us.


For the 20% dividers you are getting close to the measurement capability of pulseIn which is 4us i.e the minimum period measured was 18us and that is only -5 counts of pulseIn data. So that measurement is getting close to being too small and therefore less accurate i.e. the difference between colors will need to be larger to register a difference in the chip output = less sensitive.

The periods for 100% output will be even smaller (1.0/600e3 = 1.6us) and that would not be measurable using an Arduino Atmega328p microcontroller .

When the 2% dividers are used the program can make the most accurate period measurement since the periods output by the chip are long compared to the pulseIn accuracy of 4us. i.e the lowest period measured was 188us for these dividers ( ~48 periods of 4us ) compared to 18us ( ~5 periods of 4us ) for the 20% dividers.

Warning: The light detector is extremely sensitive so although you can get maximum accuracy the periods measured will change a lot depending on the lighting conditions and object distance. That is why the variable 'variance' allows you to specify an error value around each RBG center point for reliable color detection.

Details on Color Detection

The spectral response of the photodiodes is interesting in that all the photodiodes react to infrared light (periods above 700nm). When you add in the green and blue filters, each response shows two peaks one in the visible spectrum and one in the infrared spectrum. So when you use the TCS230 or TCS3200 (same photodiodes) for measuring red, green, blue or white light you will be actually gathering an infrared response as well. So this is definitely not the same response as your eye's response to light.

The question is: Does that really matter? ...and the answer is: It depends!

If your project is trying to measure a response that is as close as possible to a human eye response then yes it does matter. If on the other hand, the project is sorting items based on color, and is used in a well defined environment, (not changing between florescent and incandescent bulbs) then no, it does not matter.

As long as the detector is enclosed in a defined environment then it will always operate the same way i.e. within a machine closed in, with its own LED light source; The output of the detector will generate the same measurement results (however, consider aeging and temperature effects).

Note:The TCS230/3200 detector is extremely sensitive so even changing the distance of the object to the sensor will change the measured colors -depending on ambient light conditions - so removing infrared detection may not solve detection problems anyway.

In the data sheet for the TCS230 there are two spectral diagrams: copied below . In addition I have added the color spectrum chart from wikipedia that shows a human eye response.

It is important to note that the color detection of the photodiodes themselves is affected by infrared and to get a better result that is not affected by infrared you have to use an infrared filter.

Color Wavelength (nm)
Red 700 ~ 635
Green 560 ~ 520
Blue 490 ~ 450

This is the response of the TCS230 with no infrared filter on the left and with an infrared filter on the right.

tcs230 spectral response and response with IR               filter

[Source: the TAOS datasheet].

On the left you can see that the Green response has two peaks (~550nm and ~830nm) , the Blue response has two peaks (~470nm and ~800nm) and the Red response goes from 600nm to 1100nm. The maximum response you really want is from 450nm to 700nm, since the 700nm wavelength is the maximum your eye can detect . This means any infrared radiation that your eye can not see will affect Red, Green and Blue readings unless an IR filter is used.

Filters suggested by TAOS are:

  • Schott BG18
  • Schott BG39
  • Hoya CM500

When you use an IR filter(right hand diagram above) the filter smoothly chops out wavelengths above 700nm and there is only one peak response per type of photodiode. The response is far more similar to the human eye response shown below.

human colour eye response to light


The only trouble with those Hoya or Schott filters is tha they cost a lot more than the sensor itself; You can find a cheap IR filter on ebay by searching for X2 ir-cut CS lens mount.

Conclusion about TCS230 Color Detection

The best way to get a more accurate color detection, that more closely matches the human eye response, is to use an infrared filter in front of the the sensor. Note that this also applies to the TSC3200 and TCS3210 as these also employ similar photodiodes that have similar response curves.

However you can still use the devices without an IR filter and will still get color results as long as the lighting conditions and distance from the object are kept constant.

New! Comments

Have your say about what you just read! Leave me a comment in the box below.

Privacy Policy | Contact | About Me

Site Map | Terms of Use

Subscribe to the MicroZine Newsletter and collect your free microcontroller Ebooks, download project code and more...

Visit our Facebook Page:

   Click Here

Recent Articles

  1. [Arduino Tutorial] : How to use the 74HC595 shift register with shiftOut().

    The Essential Guide to the 74HC595; What it is and how you can easily use one in any of your projects.

    Read more

  2. How to use a DS18B20 on the Arduino for easy temperature measurement

    How to Easily Use the DS18B20 Maxim One-Wire thermometer with Arduino example code showing external or parasitic power modes.

    Read more

  3. Secrets of Arduino millis: How it works and how to use it.

    How to use Arduino millis() to make delays, one-shots and simple schedulers plus simple analysis of arduino millis() code; Find out how it works.

    Read more

  4. The TCS230 Color Sensing Chip: How it works and how to use it.

    How to use the TCS230 (/TCS3200) Color detector chip and easily add it to any of your projects.

    Read more

  5. Pic Programmer Types

    Which pic programmer do you need? This page discusses PIC programmers and gives some essential information on choosing or building your own programmer.

    Read more

  6. Arduino Pulsein: an easy way to measure pulse periods in microseconds.

    learn how to use Arduino pulseIn and pulseInLong to get the most accurate pulse measurement on an Arduino.

    Read more

Readers Comments

"I wanted to thank
you so so so much
for all the information
you have provided in
your site it's


- Ranish Pottath

"This site really is
the best and my favorite.
I find here many useful
projects and tips."

- Milan


"Awesome site,
very, very easy and nice
to navigate!"

- Matt

Learn Microcontrollers

"Interested in

Sign up for The
Free 7 day guide:


"I am a newbie to PIC
and I wanted to say
 how great your
site has been for me."

- Dave


"Your site is a great
and perfect work.

- Suresh


"I couldn't find the correct
words to define
yourweb site.

Very useful, uncovered,
honest and clear.

Thanks so much for
your time and works.

- Anon

Back to Top