Colour sensors need steady light and distance. Shield the sensor and use its own LED.
What the message means
The sensor measures reflected light. Ambient light and changes in distance change all channels, so the same colour reads differently.
Fix it in this order
- Fix the sensor at a set distance from the surface.
- Shield it with a small black tube to block ambient light.
- Use the on-board LED and keep it on during readings.
- Set the integration time and gain so the clear channel does not saturate.
- Calibrate with a white card and normalise the channels.
- Compare ratios, such as red over clear, not raw counts.
Why it happens
The TCS34725 reports red, green, blue and clear counts that depend on how much light reaches it, so a change in distance or room lighting scales every channel. Integration time and gain trade sensitivity against saturation: a longer time or a higher gain gives bigger counts, and a clear channel stuck at its maximum means you have gone too far. Ratios such as red divided by clear are far more stable than raw counts because the scaling cancels out.
Calibrate by measuring a white card at your working distance and dividing each channel by its white reading. Keep that distance and the LED state the same for every later reading.
If you see this, do this
| You see | Do this |
|---|---|
| Readings change with the room light | Shield and use the LED. |
| Clear channel stuck at maximum | Lower the gain. |
Related
line sensor calibration, I2C scan.
Last reviewed: November 2026. These are the usual causes and the order that finds them fastest. Test on your own board; clones and cables differ.
Why this happens
The TCS34725 counts light through four filtered photodiodes: red, green, blue and an unfiltered clear channel. A count is proportional to the light that falls on the chip. Anything that changes the light, such as the distance to the surface, the angle, a shadow or the room lamps, scales all four numbers up or down together. So a green card read at 5 mm and at 15 mm gives very different counts although it is the same colour.
The chip integrates light over a set time. A count cannot be larger than the integration time allows: the datasheet gives the maximum as 1024 counts per integration cycle, limited to 65535. At 24 ms (10 cycles) that is 10240. If the clear channel sits at that value, the reading is clipped and the colour ratios are no longer valid.
How to confirm the cause
- Print r, g, b and c every 200 ms with the sensor over a fixed card. Move the sensor a few millimetres away. If all four fall together, distance is the main variable.
- Cover the sensor and card with a dark tube and repeat. If the spread of readings shrinks, room light was the problem.
- Check the clear channel against the maximum for your integration time. If it is at or near the maximum, lower the gain or the time.
- Divide each of r, g, b by c and print the three ratios. If the ratios hold steady while the raw counts move, the sensor is working and only the scaling is varying.
- Switch the on-board LED on and off. If the ratios shift a lot, the LED is lighting the target unevenly or is being switched inconsistently.
Worked example
This uses the Adafruit TCS34725 library. It reads raw values and prints the ratio of each colour to the clear channel. For example, raw counts of 12000 red and 30000 clear give 0.40. If the lamp doubles the light, the counts become 24000 and 60000, and the ratio stays at 0.40.
#include <Wire.h>
#include <Adafruit_TCS34725.h>
Adafruit_TCS34725 tcs(TCS34725_INTEGRATIONTIME_154MS, TCS34725_GAIN_4X);
void setup() {
Serial.begin(115200);
if (!tcs.begin()) { Serial.println("sensor not found"); while (1); }
}
void loop() {
uint16_t r, g, b, c;
tcs.getRawData(&r, &g, &b, &c);
if (c == 0) return;
Serial.print((float)r / c); Serial.print(' ');
Serial.print((float)g / c); Serial.print(' ');
Serial.println((float)b / c);
delay(200);
}Common mistakes
- Comparing raw counts taken at different distances.
- Changing integration time or gain between the calibration and the readings.
- Leaving the sensor open to window light and then wondering why the result changes with the time of day.
- Using a glossy target, where reflections change with angle.
- Ignoring a clear channel that is stuck at its maximum.
If this did not fix it
- The I2C connection: loose wires or the wrong address give odd values or none at all.
- The LED pin of the module, which may be left floating or switched by your code at the wrong time.
- The surface itself. Shiny or textured surfaces reflect differently, so calibrate on the material you will really read.