
¿Qué es un TCS34725?
El TCS34725 es un sensor de color digital que podemos emplear con un procesador como Arduino para obtener los medir los valores RGB del color de un objeto o luz.
El TCS34725 es un integrado completo que realiza un tratamiento digital de la medición de color, proporcionando los valores RGB y Clear (medición total sin filtrar). La comunicación con el sensor se realiza por I2C por lo que su lectura desde un procesador como Arduino es muy sencilla.
Incorpora un filtro de infrarrojos, lo que mejora su precisión ante el ruido del entorno. El tiempo de medición y la ganancia es ajustable por software. Dispone de una amplia sensibilidad y un amplio rango dinámico de 3.800.000:1, pudiendo funcionar incluso tras un cristal oscuro.
Podemos encontrarlo en módulos comerciales que incorporan un LED de luz neutra (4150°K) junto con un MOSFET integrado para su control, por lo que podemos controlar el encendido del LED desde el código.
Anuncio:
Además de la comunicación I2C, el TCS34725 incorpora un pin de interrupción junto con un umbral inferior y superior. Cuando el nivel de luz está fuera del rango de los umbrales, el TCS34725 genera una interrupción que permanece activa hasta que es reseteada por el controlador.
A diferencia de otros sensores de color como el popular TCS3200, que únicamente son capaces de detectar colores básicos, el TCS34725 es capaz de proporcionar una medición RGB relativamente precisa del color medido.
Por supuesto, como cualquier sensor el TCS34725 no es perfecto y tiene desviaciones típicas de cualquier sensor, por lo que no obtendréis una medida totalmente precisa. En general, es necesario calibrar el color.
El TCS34725 es un sensor relativamente moderno y uno de los mejor sensor de color disponibles en el sector doméstico (geek/maker).
Precio
Los TCS34725 son sensores baratos. Podemos encontrar módulos con el TCS34725 por unos 2,70€ en vendedores internacionales de eBay y AliExpress.
¿Cómo funciona un TCS34725?
El TCS34725 es un sensor óptico que incorpora una matriz de 3x4 fotodiodos, junto con 4 conversores analógico digital de 16bits (ADC) que realizan la medición de los fotodiodos.
La matriz de3x4 está formada por fotodiodos filtrados para rojo, verde, azul, y sin filtro (clear). Todos los sensores están filtrados para infrarrojos.
Los conversores ADC integran la medición de los fotodiodos, que es transferida a los registros internos del TCS347, que incorporan doble buffer para asegurar la integridad de os datos.
El estado del sensor y el estado de energía del sensor está controlado por una máquina de estados interna, que controla todas las funciones del TCS34725.
Esquema de montaje
La conexión de los módulos que integran el TCS34725 es sencilla, ya que la comunicación se realiza a través de I2C. La tensión de alimentación del TCS34725 es de 3.3V, pero normalmente los módulos comerciales integran una salida Vin que permite alimentar a 5V.
Por tanto, simplemente alimentamos el módulo desde Arduino mediante GND y Vin y conectamos el pin SDA y SCL de Arduino con los pines correspondientes del sensor.
El pin LED controla el encendido del LED de luz neutra integrado en el módulo. La conexión de este pin puede ser la siguiente:
- Dejar sin conectar para mantenerlo encendido continuamente.
- Conectar a GND para apagar continuamente.
- Conectar a un pin digital, para controlar su encendido con digitalWrite().
- Conectarlo al pin INT y controlar el encendido con setInterrupt() de la librería.
Vista desde Arduino, la conexión sería la siguiente,
Ejemplos de código
Para realizar la lectura del sensor TCS34725 usaremos la librería desarrollada por Adafruit, disponible en este enlace. La librería incorpora varios ejemplos de uso que conviene revisar
A continuación vamos a ver algunos ejemplos de uso del sensor TCS34725
Leer valores RGB
En este primer ejemplo, muy sencillo, leemos los valores del sensor y los mostramos por puerto serie para su visualización.
#include <Wire.h> #include "Adafruit_TCS34725.h" /* Initialise with default values (int time = 2.4ms, gain = 1x) */ // Adafruit_TCS34725 tcs = Adafruit_TCS34725(); Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_700MS, TCS34725_GAIN_1X); void setup(void) { Serial.begin(9600); if (!tcs.begin()) { Serial.println("Error al iniciar TCS34725"); while (1) delay(1000); } } void loop(void) { uint16_t r, g, b, c, colorTemp, lux; tcs.getRawData(&r, &g, &b, &c); colorTemp = tcs.calculateColorTemperature(r, g, b); lux = tcs.calculateLux(r, g, b); Serial.print("Temperatura color: "); Serial.print(colorTemp, DEC); Serial.println(" K"); Serial.print("Lux : "); Serial.println(lux, DEC); Serial.print("Rojo: "); Serial.println(r, DEC); Serial.print("Verde: "); Serial.println(g, DEC); Serial.print("Azul: "); Serial.println(b, DEC); Serial.print("Clear: "); Serial.println(c, DEC); Serial.println(" "); delay(1000); }
Clasificar colores
En el segundo ejemplo, vamos a leer los valores RGB e intentar determinar el color que estamos leyendo. Para que sea más sencillo convertimos los valores RGB a HSV con la librería ColorConverter.
Para determinar el color empleamos el Hue del color medido. Para un ajuste fino será necesario calibrar el sensor ensayando colores y ajustando los valores de los condicionales.
#include <Wire.h> #include "Adafruit_TCS34725.h" #include "RGBConverterLib.h" Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_1X); void setup() { Serial.begin(9600); if (!tcs.begin()) { Serial.println("Error al iniciar TCS34725"); while (1) delay(1000); } } void loop() { uint16_t clear, red, green, blue; tcs.setInterrupt(false); delay(60); // Cuesta 50ms capturar el color tcs.getRawData(&red, &green, &blue, &clear); tcs.setInterrupt(true); // Hacer rgb medición relativa uint32_t sum = clear; float r, g, b; r = red; r /= sum; g = green; g /= sum; b = blue; b /= sum; // Escalar rgb a bytes r *= 256; g *= 256; b *= 256; // Convertir a hue, saturation, value double hue, saturation, value; RGBConverterLib::RgbToHsv(static_cast<uint8_t>(r), static_cast<uint8_t>(g), static_cast<uint8_t>(b), hue, saturation, value); // Mostrar nombre de color printColorName(hue * 360); delay(1000); } void printColorName(double hue) { if (hue < 15) { Serial.println("Rojo"); } else if (hue < 45) { Serial.println("Naranja"); } else if (hue < 90) { Serial.println("Amarillo"); } else if (hue < 150) { Serial.println("Verde"); } else if (hue < 210) { Serial.println("Cyan"); } else if (hue < 270) { Serial.println("Azul"); } else if (hue < 330) { Serial.println("Magenta"); } else { Serial.println("Rojo"); } }
Clonar color en tira WS2812b
En el último ejemplo, vamos a usar una tira Led RGB WS2812b para "clonar" el color que leemos en el sensor de color.
El ejemplo es muy simple, por un lado leemos el color con el TCS34725. Por otro, usamos la librería Fastled para hacer un efecto estela en la tira WS2812b. La tabla de conversión gamma adapta los colores leídos a la percepción de color que tiene el ojo humano.
#include <Wire.h> #include "Adafruit_TCS34725.h" #include "FastLED.h" FASTLED_USING_NAMESPACE #define DATA_PIN 6 #define LED_TYPE WS2812 #define COLOR_ORDER GRB #define BRIGHTNESS 250 #define FRAMES_PER_SECOND 250 Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_1X); const unsigned long INTERVAL = 2000; const int NUM_LEDS = 16; CRGB leds[NUM_LEDS]; byte gammatable[256]; float r, g, b; void setup() { Serial.begin(9600); if (!tcs.begin()) { Serial.println("Error al iniciar TCS34725"); while (1) delay(1000); } delay(1000); FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS); for (int i=0; i<256; i++) { float x = i; x /= 255; x = pow(x, 2.5); x *= 255; gammatable[i] = x; } } void loop() { readColor(); calculateLeds(); FastLED.show(); FastLED.delay(1000 / FRAMES_PER_SECOND); } void readColor() { uint16_t clear, red, green, blue; tcs.setInterrupt(false); delay(60); tcs.getRawData(&red, &green, &blue, &clear); tcs.setInterrupt(true); uint32_t sum = clear; r = red; r /= sum; g = green; g /= sum; b = blue; b /= sum; r *= 256; g *= 256; b *= 256; } void calculateLeds() { fadeToBlackBy(leds, NUM_LEDS, 20); uint8_t pixel; unsigned long tCurrent = millis(); pixel = (tCurrent % INTERVAL) * NUM_LEDS / INTERVAL; leds[pixel] = CRGB(gammatable[(int)r], gammatable[(int)g], gammatable[(int)b]); }
Este es el resultado
Tutoriales de Arduino
Anuncio:
Hola Luis.
Muy interesante este sensor, y sobre todo, el vídeo "clonando" los colores leídos en una tira RGB.
Muchos saludos.
Hola Luis, muy buena la información. ¿es posible obtener una imagen gráfica como la que muestras de respuesta del color a diferentes logitudes de onda?
No, esas gráficas forman parte del datasheet. No puedes elegir la respuesta frecuencial, vienen dadas por las características internas del sensor
Hola Luis. Veo que se puede cambiar el tiempo de integración y la ganancia del sensor , ¿cuál es el interés de cambiar estos parámetros , principalemente el tiempo de integración?
El sensor tiene un array de fotosensores, que convierten la luz en una señal eléctrica. A groso modo:
- La ganancia del sensor es la relación entre la señal eléctrica y la luz recibida. Más ganancia = mayor sensibilidad a ambientes oscuros y más ruido
- El tiempo de integración es la cantidad de tiempo que el sensor captura luz. Mayor tiempo de integración = medición más lenta, mayor sensibilidad a ambientes oscuros, menor ruido.
Hola, de mucha ayuda la información. Sabes cómo puedo incluir en el codigo para clasificación de colores, el blanco y negro?
En el ejemplo segundo escribes las siguientes lineas de código:
tcs.setInterrupt(false);
delay(60); // Cuesta 50ms capturar el color
tcs.getRawData(&red, &green, &blue, &clear);
tcs.setInterrupt(true);
la primera linea , tcs.setInterrupt(false); , enciende el LED y después haces esperar al procesador 60ms , en ese tiempo el procesador no haría nada, supongo que el sensor al activar la interrupción empezará a medir .
Mi duda surge cuando vas a la librería y vas al método getRawData, después de almacenar los valores en las variables correspondientes hace un delay ¿por qué?
Hola Luis, se pueden leer los impulsos de luz de los contadores electricos con este sensor? O hay otro mas adecuado? Gracias
hola Luis, una pregunta, se pueden tener mas de un sensor de este tipo en un mismo proyecto???
Ante todo muchas gracias por el aporte. Convendria actualizar el sketch con la nueva libreria (RGBConvertColor.h). No me ha dejado compilar. Al echar un vistazo la libreria que me descargo sigue saliendo como colorconvertcolor.h en vez de rgbcolorcoverter le he cambiado el nombre). Dentro de las funciones hay una que me da fallo es la de RGBConverter::HexToRgb , ignoro como arreglarlo. Para salir del paso la he borrado y ha compilado. De nuevo muchas gracias por el aporte.
Hecho! Gracias por el aviso 😀
Gracias a ti por compartir tus conocimientos!
Hola Luis, habrá alguna manera de reducir el tiempo de medición? Desde ya muchas gracias por tu aporte.
Hola luis, con este sensor sería posible medir más colores? hablo de digamos 20 colores diferentes.