Arduino software

TCS230/TCS3200 Sensor Calibration

Click to Enlarge
Click to Enlarge

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 (fO) directly proportional to light intensity:


where fO is the output frequency; fD is the output frequency for dark condition (when Ee = 0); Re is the device responsivity for a given wavelength of light in kHz/(mW/cm2); Ee is the incident irradiance in mW/cm2.

fD 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 fO. At very low light levels (dark colors), this dark frequency can be a significant portion of fO. The dark frequency is also temperature dependent.

As fO 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 fD. This is the origin (zero value) for the RGB straight line conversion.
  • A white color card gives us the extreme RGB point fW, also known as white balance. Knowing fD, this value can be used to scale all intermediate frequencies to a corresponding RGB value.

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

  • y is the reading obtained (in our case fO)
  • x is the normalised RGB value
  • b is the value of y when x is 0 (in our case fD)
  • m is the slope, or proportionality constant, of the line (in our case [fWfD]/255).

The resulting equation is


or, rearranging to give us the desired RGB value



More information on this later posting here.


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]

23 replies on “TCS230/TCS3200 Sensor Calibration”

Hi, kindly tell why TCS3200 sensor values fluctuate too fast. In each iteration , it will give different frequency? pulsein() function returns frequency of red, green and blue color while map() function also returns frequency? or corresponding R, G, B value?


It is not clear what you are asking here. Are you using the library and there is a fault? Or are you asking how to use the sensor without the library? In either case the first thing would be to make sure that the wiring is correct. The examples that come with the library all work, so that should be your starting point.


A few centimeters at best. It all depends on how the sensor is set up and how much ambient light there is leaking into the detection area. The further away and the more light, the less accurate the sensor becomes.



Need advise – I’m trying to differentiate blobs of same color on denims (Blue and Black), tried using UV light, visible range spectrum and IR, with not much success, I’m using convex lense, and the distance from the sensor to the target is around 50 – 60mm – color temperature exceed 5500degKelvin, and the denim is moving on a conveyor, I’ve included hoods and no ambient light is falling on the lense target area, tried just setting blue filter on the sensor(S2,S3).

Would be thankful. if you can suggest better way to achieve the above.

Thanks in advance,



I assume that because you are asking the setup is not working.

* The distance could be an issue for this type of sensor. If too much ambient is reflected back into the sensor, then it will “wash out” the colour. As the difference between blue and black is not that big, it could be enough to make it not work properly. Try putting the sensor closer (at least as an experiment) and check if that even works.
* If you are using a short sensing time then this will make the results less reliable. Most reliable at 1 second and then gets progressively less so under that number. No additional reliability above 1 second sampling time.
* Have you tried using the other color filters? It maybe that a bigger difference results with those.


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.


As per the documentation and the README file on the distribution dite:
This library has a dependency on the FreqCount library for frequency counting (

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.


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!


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)


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!

Liked by 1 person

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.


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.


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.


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.


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 forum you will find my responses to others, which I will not repeat here.


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.


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.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s