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



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]


17 thoughts on “TCS230/TCS3200 Sensor Calibration

  1. Sara

    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.


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


  2. Ben Lo

    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!


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


      1. Ben Lo

        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!


  3. Bastien

    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.


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


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


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


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


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


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


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