Posted by Lon Glazner on 14th Aug 2018
Sensing color with the Arduino and the TCS34725 is a pretty straight forward exercise. The TCS34725 is an IC manufactured by AMS (previously Taos). It packages color sensing analog-to-digital converters for clear, red, green, and blue color sensing into a tiny 6 pin package. The TCS34725 implements an I2C interface to configure settings and reading the color values.
In the photo above you can see a prototype of our BM017 color sensor module. We’ve included a white LED on the module that allows you to illuminate the object whose color you are sensing.
Here’s an image of the senor measuring a blue sheet of paper.
Our first application with this sensor simply configures the TCS34725 and
reads each color value one time per second. Following that there’s a simple
comparison of the red, green, and blue values to see which value is larger. The
largest value is assumed to be the color present. Here are some points of
interest from the work I did that might help you during implementation.
1. Red is the color most easily measured. Green and blue are closer in
value and can be indistinguishable if the color sample is too far from the
sensor.
2. Since the sensor may be close to the object it is sampling we
added a white LED to our module to allow illumination of the sample.
3. The
TCS34725 operates at 2.7V-3.6V. The Arduino at 5V. So our module also has a
voltage level converter on the I2C pins allowing both devices to see the voltage
they operate at.
4. The Arduino code uses the wire library with the SDA and
SCL pins associated with A4 and A5 respectively.
5. The ATime setting in the
TCS34725 determines the resolution of the color measurement. I have mine set
for 16-bit values, and I think the integration (measurement) time is about
600mS.
This module will be available for resale in about 6 weeks. I’ll place the
schematic on our web site at some point in the next few weeks. In the mean time
here’s a screen capture.
The Arduino code will set the TCS34725 up for operation and check that it is
connected to the I2C lines on power up. Then it will read the color registers
and try to determine which color is dominant. If you enable the Serial Monitor
it will display the color it sees as red, green, or blue. If you want to see
the raw measurements you can comment in that portion of the code and it will
send the data to the Serial Monitor.
Here is the code I used for simple color comparisons.
/* BM017_Arduino_color_sensing: This program interfaces to the AMS TCS34725 color light to digital converter IC. It uses the Arduino I2C interface. Schematics associated with the BM017 module may be used for hardware wiring information. See the user datasheet at <a href="http://www.solutions-cubed.com">www.solutions-cubed.com</a> for additional information. */ #include <Wire.h> #include <Math.h> byte i2cWriteBuffer[10]; byte i2cReadBuffer[10]; #define SensorAddressWrite 0x29 // #define SensorAddressRead 0x29 // #define EnableAddress 0xa0 // register address + command bits #define ATimeAddress 0xa1 // register address + command bits #define WTimeAddress 0xa3 // register address + command bits #define ConfigAddress 0xad // register address + command bits #define ControlAddress 0xaf // register address + command bits #define IDAddress 0xb2 // register address + command bits #define ColorAddress 0xb4 // register address + command bits /* Send register address and the byte value you want to write the magnetometer and loads the destination register with the value you send */ void Writei2cRegisters(byte numberbytes, byte command) { byte i = 0; Wire.beginTransmission(SensorAddressWrite); // Send address with Write bit set Wire.write(command); // Send command, normally the register address for (i=0;i<numberbytes;i++) // Send data Wire.write(i2cWriteBuffer[i]); Wire.endTransmission(); delayMicroseconds(100); // allow some time for bus to settle } /* Send register address to this function and it returns byte value for the magnetometer register's contents */ byte Readi2cRegisters(int numberbytes, byte command) { byte i = 0; Wire.beginTransmission(SensorAddressWrite); // Write address of read to sensor Wire.write(command); Wire.endTransmission(); delayMicroseconds(100); // allow some time for bus to settle Wire.requestFrom(SensorAddressRead,numberbytes); // read data for(i=0;i<numberbytes;i++) i2cReadBuffer[i] = Wire.read(); Wire.endTransmission(); delayMicroseconds(100); // allow some time for bus to settle } void init_TCS34725(void) { i2cWriteBuffer[0] = 0x10; Writei2cRegisters(1,ATimeAddress); // RGBC timing is 256 - contents x 2.4mS = i2cWriteBuffer[0] = 0x00; Writei2cRegisters(1,ConfigAddress); // Can be used to change the wait time i2cWriteBuffer[0] = 0x00; Writei2cRegisters(1,ControlAddress); // RGBC gain control i2cWriteBuffer[0] = 0x03; Writei2cRegisters(1,EnableAddress); // enable ADs and oscillator for sensor } void get_TCS34725ID(void) { Readi2cRegisters(1,IDAddress); if (i2cReadBuffer[0] = 0x44) Serial.println("TCS34725 is present"); else Serial.println("TCS34725 not responding"); } /* Reads the register values for clear, red, green, and blue. */ void get_Colors(void) { unsigned int clear_color = 0; unsigned int red_color = 0; unsigned int green_color = 0; unsigned int blue_color = 0; Readi2cRegisters(8,ColorAddress); clear_color = (unsigned int)(i2cReadBuffer[1]<<8) + (unsigned int)i2cReadBuffer[0]; red_color = (unsigned int)(i2cReadBuffer[3]<<8) + (unsigned int)i2cReadBuffer[2]; green_color = (unsigned int)(i2cReadBuffer[5]<<8) + (unsigned int)i2cReadBuffer[4]; blue_color = (unsigned int)(i2cReadBuffer[7]<<8) + (unsigned int)i2cReadBuffer[6]; // send register values to the serial monitor /* Serial.print("clear color="); Serial.print(clear_color, DEC); Serial.print(" red color="); Serial.print(red_color, DEC); Serial.print(" green color="); Serial.print(green_color, DEC); Serial.print(" blue color="); Serial.println(blue_color, DEC); */ // Basic RGB color differentiation can be accomplished by comparing the values and the largest reading will be // the prominent color if((red_color>blue_color) && (red_color>green_color)) Serial.println("detecting red"); else if((green_color>blue_color) && (green_color>red_color)) Serial.println("detecting green"); else if((blue_color>red_color) && (blue_color>green_color)) Serial.println("detecting blue"); else Serial.println("color not detectable"); } void setup() { Wire.begin(); Serial.begin(9600); // start serial for output init_TCS34725(); get_TCS34725ID(); // get the device ID, this is just a test to see if we're connected } void loop() { get_Colors(); delay(1000); }
I’m in the process of adding the BM017 Color Sensor to our web site. This breakout module is based on the TCS34725 by AMS (formerly Taos). You can use it to detect red, green, blue, and clear color values from object in front of the sensor. I covered basic use of the sensor [...]
Atmel’s Studio 7 (Atmel is now owned by Microchip) allows you to import Arduino sketches and debug them. This brings the Arduino into the realm of a professional design engineer tool. Getting an Arduino to the point of debuggin’ its firmware is a pretty easy process, but does take several steps. Here are some [...]
PID motor control with an Arduino can be accomplished using simple firmware. In this example we use our Firstbot Arduino-Compatible controller to implement a PID based position controller using analog feedback and a potentiometer for control. This is similar in operation to a hobby servo, but the potentiometer provides the control signal instead of a [...]