TCS230 Colour Sensor and MD - TCS230 Library
TCS230 Colour Sensor and MD - TCS230 Library
1|Page
Functional Description
Digital inputs and digital output allow direct interface to a microcontroller or other logic
circuitry.
Output enable (/OE) places the output in the high-impedance state for multiple-unit sharing of a
microcontroller input line.
The output is a square wave (50% duty cycle) with frequency (fO) directly proportional to light
intensity (irradiance).
The full-scale output frequency can be scaled by one of three preset values and off, via two
control input pins (S0, S1 ).
Four types of photodiodes - Red, Green, Blue and Clear (no filter) - are pin-selectable (S2, S3 ) to
read the individual components of the color detected.
2|Page
Using Breakout Boards
The OE line is driven HIGH by external circuitry – this creates a short circuit between GND and
the output of the driving circuit!
Multiple sensors need to be connected to the same OUT, as the OUT lines cannot be switched
into high impedance mode.
Restoring normal function to the OE input is possible by cutting a track on the PCB. This is found
between resistors R5 and R8, highlighted by the circle in . This may be different for other boards, so it is
wise to follow the connections to make sure the correct track is cut.
Another modification to make the device readings consistent and repeatable is to shroud the sensor.
This can be made from black card, wrapped and taped to the breakout board. The shroud eliminates
stray light and ensures all the reflected light goes back to the sensor - use black so that the light
reflected back into the sensor does not include color components originating from the shroud. My setup
is shown in above.
3|Page
Interpreting Sensor Data
The output 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/cm 2); 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
x ( fW f D )
fO fD
25 5
4|Page
Implementing a System
Measuring Frequency
The sensor’s output is a square wave with 50% duty cycle (on/off equal amounts) with frequency
directly proportional to light intensity, so accurately measuring the frequency is a fundamental
requirement of any implementation.
To measure frequency we need to measure the number of cycles in a fixed time period. The number of
cycles in 1 second is measured in Hz. As long as the system is able to sample cycle transitions at a rate at
least twice the expected frequency, we can be assured of an accurate reading. This rate should be easily
achievable with an Arduino based implementation, even at 100% frequency scale.
Output scaling can be used to increase the resolution for a given clock rate or to maximize resolution as
the light input changes.
The MD_TCS230 library uses a timer interrupt for the gate interval. If another interrupt is running, or
interrupts are disabled by the main program, response to the timer could be delayed. That will lengthen
the gate interval, perhaps leading to counting more cycles. The next gate interval will be shorter (if
normal interrupt response occurs), so a corresponding decrease will occur in the next measurement.
This mechanism is implemented in the FreqCount library.
The longer the time period allowed for reading a value, the higher the accuracy. The library is set to use
1000ms, giving a value in Hz, as the basis of measurement. A divisor is applied to the time and the
resulting count is multiplied by the divisor. Shorter sampling times are possible when the color
differences between samples are more distinct. Higher resolution is obtained using a lower time divisor.
There is no additional benefit counting cycles beyond 1000ms using this method.
Sensor Calibration
To calibrate the sensors, we need to measure the raw data that is returned with black and white test
cards and then use that data to scale subsequent readings to an RGB value.
It is not necessary to calibrate the sensor every time it is used. Calibration can be done separately from
the application, and the constants determined during testing applied to the sensor from the code
running the final application. Care should be taken to calibrate the sensor in a position that closely
approximates final conditions.
References
TAOS Inc, “TCS230 Programmable Color Light-to-Frequency Converter”, TAOS046, February 2003.
Charles Poynton, “Sensing Color with the TAOS TCS230”, TAOS Inc, 17 May 2005.
5|Page
Paul J Stoffregen, “FreqCount Library”, http://www.pjrc.com/teensy/td_libs_FreqCount.html,accessed
18 February 2013.
Initialising
MD_TCS230(uint8_t s2, uint8_t s3);
MD_TCS230(uint8_t s2, uint8_t s3, uint8_t oe);
MD_TCS230(uint8_t s2, uint8_t s3, uint8_t s0, uint8_t s1);
MD_TCS230(uint8_t s2, uint8_t s3, uint8_t s0, uint8_t s1, uint8_t oe);
Various forms of the constructor for this class. The parameters are all the Arduino pin numbers used to
control the nominated pins on the TCS230. The form used will depend on the configuration of the
hardware connections to the Arduino. At a minimum S2 and S3 are required for color filter selection.
begin()
Initialise the object. The object needs to initialise itself using Arduino libraries and so cannot be
completely initialised in the constructor. Should be done once for every object created.
Reading Data
read()
Start a read cycle from the Sensor. The function will coordinate enabling the sensor, selecting the right
filters in sequence and calling the FreqCount library to obtain a full color reading.
available()
Determine when a sensor read has completed. The method will return true when a value is ready for
processing, at which time a call to getRGB() or getRaw() will retrieve the data for the calling program.
getRGB(colorData *rgb)
Get the last read sensor data in RGB format into the structure *rgb. The elements of RGB are retrieved
using value[TCS230_RGB_R], value[TCS230_RGB_G] and value[TCS230_RGB_B] for the Red, Green and
Blue elements, respectively.
getRaw(sensorData *d)
Get the last read sensor data as raw counts into the structure *d. The elements may be retrieved using
value[TCS230_RGB_R], value[TCS230_RGB_G] and value[TCS230_RGB_B] for the Red, Green and Blue
elements, respectively.
This function is most useful in obtaining calibration data that to be passed back to the setDarkCal() and
setWhiteCal() methods. To improve accuracy in the calibration, the data may be averaged over several
readings before setting the calibration data.
6|Page
setSampling(uint8_t t)
Set the sampling period divisor. The library is set for a maximum of 1000ms for a sample (divisor = 1).
Higher divisors create shorter sample times (eg, 5 = 200ms, 10 = 100ms, 100 = 10ms). Shorter samples
are less accurate and only recommended when the range of colors to be detected are highly separated
on the RGB color chart. The ‘right’ value for the divisor is dependent on the application. The default
value is 10 (100ms sample).
readSingle()
Initiate a blocking read of from the sensor. The method returns the raw data read from the sensor as a
uint32_t, normalised to a value in Hz, once the read cycle is completed. How long this takes is
determined by the sampling period. The calling program is responsible for enabling the device and
setting the appropriate color filter.
setDarkCal(sensorData *d)
Set the dark calibration data. The information is retrieved using a call to getRaw().
setWhiteCal(sensorData *d)
Set the white balance calibration data. The information is retrieved using a call to getRaw().
Miscellaneous
setFilter(uint8_t f)
setFrequency(uint8_t f)
setEnable(bool t)
If the OE pin is defined, setting the OE pin to the appropriate HIGH/LOW conditions. This is
preferred mode as the high impedance mode can be used for OUT signal isolation.
If the SO and S1 pins are defined, setting the output frequency to the value set by the
setFrequency() method or to TCS230_FREQ_OFF.
No action is taken if none of OE, S0 and S1 is defined.
7|Page