Introduction: Everything You Need to Know About Colour Sensors

This instructable describes a week-long project on colour sensors, their properties and their interaction with arduino.

The sensors we worked with included:

Sparkfun ADJD-S311-CR999 (Retired): https://www.sparkfun.com/products/retired/10701 (available in fritzing)

Adafruit TCS34725: http://www.adafruit.com/products/1334 (not available in fritzing)

DFRobot TCS3200 : http://www.dfrobot.com/wiki/index.php/TCS3200_Color_Sensor_(SKU:SEN0101) (not available in fritzing)

Out of these three our favorite is the Adafruit TCS34725 due its superior examples, tutorials and simple wiring.

STRUCTURE

1. How does it work? How do we set it up?

2. About the sensor

2.1 Calibration

2.3 Finding Code

2.4 Smallest sensable volume?

2.5 How fast can it read colour?

2.6 How far away can it read colour?

Step 1: 1. How Does It Work? How Do We Set It Up?

The light sensor works by shining a white light at an object and then recording the reflected colour. It can also record the intensity of the reflection (brightness). Through red, green and blue colour filters the photodiode converts the amount of light to current. The converter then converts the current to voltage which our arduino can read.

Different colour sensor boards connect to the arduino in different ways, the Adafruit TCS34725 connects to the arduino in this way:

5v -> VIN (red wire)

GND -> GND (black wire)

SDA -> Pin A4

SCL -> Pin A5

Note: the wiring differs slightly depending on which version of the Arduino board you've got. Info here: https://learn.adafruit.com/adafruit-color-sensors/assembly-and-wiring

It is not mandatory to use the LED that is usually built in to the breakout boards, though it gives higher fidelity. To turn this off simply ground the LED pin on the breakoutboard.

Step 2: About the Sensors

Throughout our exploration of the sensor, we can clearly see its potential application in both industrial and arty ways. Firstly, the sensors are good at distinguishing which color is present (as you would expect), but we haven't been able to get good absolute RGB from the sensor (as in, point a 0,255,0 coloured object at it, it won't give 0,255,0). It will give you a colour within the same spectrum (if you show it yellow, it will output a yellowish colour), but most sensors we found had a tendency to create very dark and "muddy" colours that are a 60/40 split between brown and the desired colour. For the best readings we also had to put the object directly on top of the sensor, which could be an issue if you want to secure it in some sort of casing.

What we have been able to get it is what I would call relative RGB, as the colour it is sensing is clearly visible by one value spiking, but it's not within the 0-255 range. So a red object might cause the red value to rise by 30, not by 255. This is clearly visible when connecting an RGB LED, it will change colour, but the colour change might not be visible, an issue is also that generally blue LEDs have a higher energy output so it might overpower.

This is clearly an issue with calibration, we found an effective way of calibrating our sensor to our needs, but this is not a reliable calibration method. Calibration is also the reason I would not recommend the sparkfun ADJD breakout board, as it constantly re-calibrates itself, which means that any values you set will be off the next time you reset the board.

Secondly, the speed and fidelity of the sensors is incredibly good. It senses very small differences in colour and reports them incredibly fast. The Adafruit sensor also came with an RGB to HEX function, which meant that outputting rough HEX values to Processing is possible. The brightness value also seemed reliable.

Step 3: 2.1 Calibration

Usually the calibration process consists of holding a white object in front of the sensor (setting the max values) and then calibrating it through whichever library and sensor combination you have. As mentioned the sparkfun ADJD sensor needed a lot of calibration, all the time.

We tried this several times, and ended up with spotty results, either we did it wrong, or the calibration code was flawed in some way.

Based on our earlier findings that the sensors are often more interested in the relative mix of RGB rather than absolute values, so our code is based on thresholds. This means that we don't so much care about the actual RGB values, more the interaction between RGB values. So what we do is reset all the values to the same base, so any difference is clearly visible.

So to calibrate our sensor we reset all the values once:

int redCal;
int greenCal;

int blueCal;

if (redCal==0){ //RUNS ONCE. MAKES CAL-VALUES THE SAME AS THE REAL SENSOR VALUE.

redCal =red;

if (greenCal==0){

greenCal =green;

(blueCal==0){

blueCal =blue;

…Our calibration method takes each value and then subtracts it with itself, then adds 100 to them.

r = red-redCal+100; //MAKES THE REAL SENSOR VALUE (0+100)

g = green-greenCal+100;

b = blue-blueCal+100;

Serial.print("\tRED:\t");

Serial.print(r);

Serial.print("\tGREEN:\t");

Serial.print(g);

Serial.print("\tBLUE :\t");

Serial.println(b);

Step 4: 2.2 Finding Code and Tutorials

The best code you can get is usually from the supplier of the breakout board.

For the adafruit one that would be:

https://learn.adafruit.com/adafruit-color-sensors/...

In terms of videos and tutorials, there are a lot of videos online that use the sensors in some way, but they usually do a poor job explaining or supplying code. Actually the quality of a lot of the videos is so low, that components and wiring is hard to make out. So what we suggest is looking for videos of other peoples project, and then trying to hack together something that works similarly:

Our favorite video of all time is still this one:

In terms of concepts:

http://www.designboom.com/design/pega-d-and-e-colo...

http://www.adafruit.com/blog/2014/10/08/interacket...

Step 5: How Fast? How Small? Distance?

How fast does the sensor register colour changes?

Datasheet says that the sensor will communicate a colour change within 2ms. We tested this by connecting the colour sensor output to a piezo which played a different tone per colour. Then we put a wheel with different colours on them and spun it.

The bottleneck was simply the piezo. The serial output would change, but it would change so quickly that the piezo didn't have time to react before the next colour change.

Video 06.10.14 12 00 49.mov from alfred on Vimeo.

How small of an object can it see?

The smallest object we could reliably sense the colour from was about 3mm.

We made a small casing for our sensor, which had a hole approximately 3mm, anything that didn't quite fit the hole didn't reliably read. The sensor itself is about 1mm x 1mm, so it could theoretically read objects that small, but in practice this wasn't reliable nor particularly practical.

How far away can it see?

About 1 cm from the hole we made in the case, so that would be about 2cm from the actual sensor. It could read some bigger things beyond this, though it was not reliable across objects.

Step 6: Concept: Indiana Jones Game

If you remember the scene in indiana jones where he steals and ancient artifact and replaces it with sand, this game is based on the same principle. The player needs to steal an object of a specific colour and replace it with an object of the same RGB value. If you don’t manage this within 500ms the red alarm LED will go off.

This code is based on finding what a specific RGB value of an object is, and then making sure that if the value is different than this value, then the LED turns on.

Video 07.10.14 16 10 43.mov from alfred on Vimeo.

Conceptually it’s like this:

READ COLOURS

if {colour is NOT THE SAME as object){

turn LED ON;}

else {

turn LED OFF;}

Real Code:

int s0=3,s1=4,s2=5,s3=6;

int flag=0;

int counter=0;

int countR=0,countG=0,countB=0;

void setup()

{

Serial.begin(9600);

pinMode(s0,OUTPUT);

pinMode(s1,OUTPUT);

pinMode(s2,OUTPUT);

pinMode(s3,OUTPUT);

pinMode(8,OUTPUT);

}

void TCS()

{

digitalWrite(s1,HIGH);

digitalWrite(s0,LOW);

flag=0;

attachInterrupt(0, ISR_INTO, CHANGE);

timer2_init();

}

void ISR_INTO()

{

counter++;

}

void timer2_init(void)

{

TCCR2A=0x00;

TCCR2B=0x07; //the clock frequency source 1024 points

TCNT2= 100; //10 ms overflow again

TIMSK2 = 0x01; //allow interrupt

}

int i=0;

ISR(TIMER2_OVF_vect)//the timer 2, 10ms interrupt overflow again. Internal overflow interrupt executive function

{

TCNT2=100;

flag++;

if(flag==1)

{

counter=0;

}

else if(flag==2)

{

digitalWrite(s2,LOW);

digitalWrite(s3,LOW);

countR=counter/1.051;

Serial.print("red=");

Serial.print(countR,DEC);

Serial.print(" l ");

digitalWrite(s2,HIGH);

digitalWrite(s3,HIGH);

}

else if(flag==3)

{

countG=counter/1.0157;

Serial.print("green=");

Serial.print(countG,DEC);

Serial.print(" l ");

digitalWrite(s2,LOW);

digitalWrite(s3,HIGH);

}

else if(flag==4)

{

countB=counter/1.114;

Serial.print("blue=");

Serial.println(countB,DEC);

digitalWrite(s2,LOW);

digitalWrite(s3,LOW);

}

else

{

flag=0;

TIMSK2 = 0x00;

}

counter=0;

delay(2);

}

void loop()

{

delay(10);

TCS();

if((countR>10)||(countG>10)||(countB>10))

{

if((countR>countG)&&(countR>countB))

{

Serial.print("red");

delay(500);

}

else if((countG>=countR)&&(countG>countB))

{

Serial.print("green");

delay(500);

}

else if((countB>countG)&&(countB>countR))

{

Serial.print("blue");

delay(500);

}

}

else

{

delay(500);

}

if (countG>3) {

digitalWrite(8,HIGH);

}

else {

digitalWrite(8,LOW);

}

}

Step 7: Concept: Paddle Game With Colours

We hooked the TCS34725 setup up to a Makey Makey which allowed us to use the input from the sensor as controls for a computer game. We quickly threw together an Arkanoid-style paddle game in Multimedia Fusion. The catch? The ball will only bounce of the paddle if they're the same color, and the ball assumes the color of the previous block it's hit. By holding up pieces of colored paper in front of the sensor you change the paddle to that color. Stressful, to say the least.

The code is included if you're curious. It's based on the ColorView! sketch from the Adafruit TCS34725 library.

Video 08.10.14 15 30 39.mov from alfred on Vimeo.

Step 8: Concept: RGB Cookbook

If you remember the scene in indiana jones where he steals and ancient artifact and replaces it with sand, this game is based on the same principle. The player needs to steal an object of a specific colour and replace it with an object of the same RGB value. If you don’t manage this within 500ms the red alarm LED will go off.

This code is based on finding what a specific RGB value of an object is, and then making sure that if the value is different than this value, then the LED turns on.

Conceptually it’s like this:

READ COLOURS

if {colour is NOT THE SAME as object){

turn LED ON;}

else {

turn LED OFF;}

Real Code:

int s0=3,s1=4,s2=5,s3=6;

int flag=0;

int counter=0;

int countR=0,countG=0,countB=0;

void setup()

{

Serial.begin(9600);

pinMode(s0,OUTPUT);

pinMode(s1,OUTPUT);

pinMode(s2,OUTPUT);

pinMode(s3,OUTPUT);

pinMode(8,OUTPUT);

}

void TCS()

{

digitalWrite(s1,HIGH);

digitalWrite(s0,LOW);

flag=0;

attachInterrupt(0, ISR_INTO, CHANGE);

timer2_init();

}

void ISR_INTO()

{

counter++;

}

void timer2_init(void)

{

TCCR2A=0x00;

TCCR2B=0x07; //the clock frequency source 1024 points

TCNT2= 100; //10 ms overflow again

TIMSK2 = 0x01; //allow interrupt

}

int i=0;

ISR(TIMER2_OVF_vect)//the timer 2, 10ms interrupt overflow again. Internal overflow interrupt executive function

{

TCNT2=100;

flag++;

if(flag==1)

{

counter=0;

}

else if(flag==2)

{

digitalWrite(s2,LOW);

digitalWrite(s3,LOW);

countR=counter/1.051;

Serial.print("red=");

Serial.print(countR,DEC);

Serial.print(" l ");

digitalWrite(s2,HIGH);

digitalWrite(s3,HIGH);

}

else if(flag==3)

{

countG=counter/1.0157;

Serial.print("green=");

Serial.print(countG,DEC);

Serial.print(" l ");

digitalWrite(s2,LOW);

digitalWrite(s3,HIGH);

}

else if(flag==4)

{

countB=counter/1.114;

Serial.print("blue=");

Serial.println(countB,DEC);

digitalWrite(s2,LOW);

digitalWrite(s3,LOW);

}

else

{

flag=0;

TIMSK2 = 0x00;

}

counter=0;

delay(2);

}

void loop()

{

delay(10);

TCS();

if((countR>10)||(countG>10)||(countB>10))

{

if((countR>countG)&&(countR>countB))

{

Serial.print("red");

delay(500);

}

else if((countG>=countR)&&(countG>countB))

{

Serial.print("green");

delay(500);

}

else if((countB>countG)&&(countB>countR))

{

Serial.print("blue");

delay(500);

}

}

else

{

delay(500);

}

if (countG>3) {

digitalWrite(8,HIGH);

}

else {

digitalWrite(8,LOW);

}

}

Attachments

Step 9: Concept: RGB Instrument

Similar to the code for the paddle game. Take a piezo and hook it up to the colour sensor. Define the colours you want to create a tone, and then create a strip of different colours and pull it in front of the sensor. If you are very musically gifted you can assign specific colours to specific tones and create a masterpiece.

Video 06.10.14 11 48 32.mov from alfred on Vimeo.