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

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

Library

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  \
   digitalWrite(TCS320_S2,LOW);digitalWrite(TCS320_S3,LOW)
#define SEL_GREEN \
   digitalWrite(TCS320_S2,HIGH);digitalWrite(TCS320_S3,HIGH)
#define SEL_BLUE \
   digitalWrite(TCS320_S2,LOW);digitalWrite(TCS320_S3,HIGH)
#define SEL_CLEAR \
   digitalWrite(TCS320_S2,HIGH);digitalWrite(TCS320_S3,LOW)

#define TWO_PER \
   digitalWrite(TCS320_S0,LOW);digitalWrite(TCS320_S1,HIGH);

#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]={
   {248,647,393},
   {188,261,265},
   {404,710,546},
   {506,493,304},
   {930,1199,837},
};

char colname[NUMCOL][11]={
"red",
"yellow",
"brown",
"blue",
"black",
};

////////////////////////////////////////////////////////////////
void setup() {

   pinMode(TCS320_OE,OUTPUT);
   pinMode(TCS320_S0,OUTPUT);
   pinMode(TCS320_S1,OUTPUT);
   pinMode(TCS320_S2,OUTPUT);
   pinMode(TCS320_S3,OUTPUT);
   pinMode(TCS320_OUT,INPUT);

   TWO_PER;

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

   Serial.begin(115200);
   Serial.println("TCS230 color detector");
}

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

static int clr,red,green,blue;

////////////////////////////////////////////////////////////////
uint16_t detect(void) {
   unsigned long val;

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

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

    SEL_BLUE;
    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 = Serial.read(); // Consume.

      // Find color match.
      detect();
      fnd=0;
      for (i=0;i<NUMCOL;i++) {
         if ( compare(red,RGB[i][0],variance) &&
              compare(green,RGB[i][1],variance) &&
              compare(blue,RGB[i][2],variance)
            ) { // Found
              Serial.print("Col is :");
              Serial.println(colname[i]);
              fnd=1;
              break;
            }
      }
      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 main mechanism to detect color is pulseIn which is accurate to 4us so it makes sense to get maximum accuracy and that means providing a maximum period output so that you can measure as many 4us periods as possible. That means using the maximum divider output and therefore using a 2% output means maximum accuracy (when using pulseIn).

Typical output for 2% dividers:

{248,647,393},

{188,261,265},

{404,710,546},

{506,493,304},

{930,1199,837}

So the frequencies involved are

1.0/1199e-6 = 834Hz to 1.0/248e-6 = 4032Hz (4kHz). (max is 12kHz).

Typical values for 20% dividers:

{18,26,26},

{48,47,30},

{40,69,54},

{27,71,43},

{92,119,83}

Here the frequencies involved are :

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

For the 20% dividers you are getting close to the measurement capability of pulseIn which is 4us.

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 are long compared to the pulseIn accuracy of 4us..

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. If however it is used in different ambient lighting conditions then the output of the detector will change affecting the measurement results.

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.

copied below in addition I have added the color spectrum chart from wikipedia.

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

[source https://en.wikipedia.org/wiki/Color]

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



Visit our Facebook Page:

   Click Here



Recent Articles

  1. 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

  2. Arduino millis

    How to use Arduino millis() for delays but still make the processor do work - Stop using delay()

    Read more

  3. [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

  4. 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

  5. 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

  6. Multiple MCP23017 Interrupt tutorial for operating multiple interrupts from multiple MCP23017s.

    This MCP23017 Interrupt tutorial shows you how to connect interrupt outputs from several MCP23017s to a single microcontroller interrupt pin.

    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

SUPERB and FANTASTIC."

- Ranish Pottath

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

- Milan

bursach<at>gmail.com<

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


- Matt
matt_tr<at>
wolf359.cjb.net


Learn Microcontrollers

"Interested in
Microcontrollers?"

Sign up for The
Free 7 day guide:

FREE GUIDE : CLICK HERE


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


- Dave

de_scott<at>bellsouth.net

"Your site is a great
and perfect work.
congratulations."


- Suresh

integratredinfosys<at>
yahoo.com

"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.
Regards."


- Anon

Back to Top