The TCS230 (and equivalent TCS3200) sensor can be easily purchased mounted on any number of inexpensive breakout boards, similar in design to that shown in the photo. These boards extend the package connections to header pins, and integrate LEDs for illumination of the target object. These sensors work well to recognize color but they need to be calibrated. An Arduino library for this sensor can be found at my Arduino Library site and elsewhere.

The output from the sensor is a square wave (50% duty cycle) with frequency (*f _{O}*) directly proportional to light intensity:

where *f _{O}* is the output frequency;

*f*is the output frequency for dark condition (when

_{D}*Ee*= 0);

*Re*is the device responsivity for a given wavelength of light in kHz/(mW/cm

^{2});

*Ee*is the incident irradiance in mW/cm

^{2}.

*f _{D}* is an output frequency resulting from leakage currents. As shown in the equation above, this frequency represents a light-independent term in the total output frequency

*f*. At very low light levels (dark colors), this dark frequency can be a significant portion of

_{O}*f*. The dark frequency is also temperature dependent.

_{O}As *f _{O}* is directly proportional to frequency, it is possible to map between the frequency and RGB color value (0-255 for each of R, G and B) using linear interpolation.

Two points on the RGB line are well determined – pure Black (RGB 0, 0, 0) and pure White (255, 255, 255). The values returned by the sensor can be read using easily obtainable color swatches:

- A black color card gives us the dark condition constant
*f*. This is the origin (zero value) for the RGB straight line conversion._{D} - A white color card gives us the extreme RGB point
*f*, also known as white balance. Knowing_{W}*f*, this value can be used to scale all intermediate frequencies to a corresponding RGB value._{D}

The proportional relationship is expressed by the standard straight line equation *y = mx + b* where

*y*is the reading obtained (in our case*f*)_{O}*x*is the normalised RGB value*b*is the value of*y*when*x*is 0 (in our case*f*)_{D}*m*is the slope, or proportionality constant, of the line (in our case [*f*–_{W}*f*]/255)._{D}

The resulting equation is

or, rearranging to give us the desired RGB value

### References

Yurish, Sergey Y 2005, ‘Intelligent Opto Sensors Interfacing Based on Universal Frequency-to-Digital Converter’, *Sensors & Transducers Magazine (S&T e-Digest)*, Vol.56, Issue 6, June 2005, pp.326-334. [PDF Link]

TAOS Inc 2003, ‘TCS230 Programmable Color Light-to-Frequency Converter’, Product Datasheet TAOS046 – February 2003. [PDF Link]

Poynton, Charles 2005, ‘Sensing Color with the TAOS TCS230’, *TAOS Inc.*, 2005-05-17. [PDF Link]

Sir I need help. I couldn’t find the output pin in TCS3200 library where should I connect OE and OUT pin of TCS3200. Help would be really appreciated.

LikeLike

As per the documentation and the README file on the distribution dite:

“IMPORTANT NOTE

This library has a dependency on the FreqCount library for frequency counting (https://github.com/PaulStoffregen/FreqCount).

Please read the setup information in the FreqCount header file or its distribution web site. The type of Arduino that you are running will determine which pin should be used for connecting to the sensor’s output pin. This is the most commonly asked question once the library is downloaded, so read the documentation and avoid frustration!”

The OE may not need to be connected. Again, read the documentation that comes with the library.

LikeLike

Refer to https://arduinoplusplus.wordpress.com/2017/04/14/parola-a-to-z-adapting-for-different-hardware/ or read the documentation with the MD-MAX72xx library.

LikeLike

Hello Sir, i’ve tried to use the method with Black and White cards. I’m get of these value

int Br=414; int Bg=550; int Bb=166; int Wr=43; int Wg=40; int Wb=14, and my formula in arduino boards is int R=abs(255*(frequency-Br)/(Wr-Br)); int G=abs(255*(frequency-Bg)/(Wg-Bg)); int B=abs(255*(frequency-Bb)/(Wb-Bb)).

After the calibration is finished, i’ve tested the black and white card again, its show black value as (15 6 8), it’s normal and deserved value. However, it shows abnormal for the white card value as (79 4 176). The RGB value of white is proposed to be 255,255,255. I can’t figure out what’s the problem and any help will be appreciated, Thanks!

LikeLike

Try making the variables uint32_t (long) so that they don’t overflow and see if that makes a difference. Also, are you shrouding the sensor? External light may be affecting the readings. After calibration black should be much closer to (0,0,0) as well as white closer to (255,255,255)

LikeLike

Hello sir, the problem is solved, int r = pulseIn(sensorOut, LOW);

// Printing the value on the serial monitor

long R1=r-Br;

long R2=255*R1;

long R3=(Wr-Br);

long R=abs(R2/R3);

The above problem can calculate the exact value, it seems the problem come from calculation method in C++, I don’t know why they cannot combine in a formula as long R=abs(255*(r-Br)/(Wr-Br). But, still can solve the problem for calibration of color sensor, Thanks!

LikeLike

Hi marco_c,

Why do you multiply the fraction by 256, instead of multiplying it by 255 ?

if you compute the following worst case, you get x = 256 (byte overflow)

with F0 = Fw; Fd = 0.

LikeLike

In practice Fd will never be zero as the sensor will always have leakage currents. However, I do take your point and it does seem that 255 should be used as the multiplier as the Fo will range between 0 and 255, so the scaled value cannot ever be bigger than 255. I’ll update the text and check the library. Thanks for pointing that out.

LikeLike

Hello Marco_c,

I would like to know if you use your library TCS230 TCS3200 RGB Color Sensor Library is possible to use with other sensors as TCS3414 or TCS34725. At the same time I would like if you have experience with some of this sensor and for you point of view which is better.

Thank lyou very much for you answers and for you work.

LikeLike

The two sensors you quote have I2C interfaces, so they communicate with the Arduino in a fundamentally different way and the current library will not work. The note on calibration may still be relevant, but as I have not used these at all I cannot really comment. I do note the Adafruit web site says the 34725 is the best sensor at the moment.

LikeLike

Thank your for you answer. Do you planning update you library to works with these sensors?

Thanks

LikeLike

No plans to upgrade/make a new library at this stage.

LikeLike

We are able to make the whole setup work by following your advise. And also figure out the codes as well as the write up… Thank you very much sir. Really a great help 🙂 God bless.

LikeLike

Ok sir. but we are just trying to figure out the output of the calibration, because we try the code many times and all we get back is (0,0,0). Does it really work that way? what is its expected output? thank you! 🙂

LikeLike

The expected output is numbers that you are then able to pass through to the calibration setting function, as per the code itself.

The usual cause of the issue you see is people not connecting the frequency to the correct pin on the Arduino (read the documentation for the FreqCount Library). If you search for the MD_TCS230 library on the Arduino.cc forum you will find my responses to others, which I will not repeat here.

LikeLike

Hello sir, this post became very helpful for our project. I just want to know if you have a basis for this formula, like a published study? we would really appreciate if you can enlighten us about this matter.. and also sir a more detailed explanation about your calibration example code in the library.. thank you very much sir.

LikeLike

No published study. Just reading the datasheet, some additional material from the web, and and engineering, computer science and mathematics degree. The calibration example is really very simple and you should be able to understand it by reading the code – all it does is collect the information required to work out the calibration factors.

LikeLike