Introduction: Arduino Color Recognition

About: I am here to share what I make. Hopefully, you can learn from watching what I have done and even improve upon it. As an Amazon Associate I earn from qualifying purchases.

This project uses a TCS230 color sensor I ordered from Amazon. It uses both "passive" and "active" color recognition: Passive recognition goes straight to an RGB LED. Active recognition is processed by the Arduino to output a specific color.

According to a similar product's datasheet,

In the TCS3200, the light-to-frequency converter reads an 8 × 8 array of photodiodes. Sixteen photodiodes have blue filters, 16 photodiodes have green filters, 16 photodiodes have red filters, and 16 photodiodes are clear with no filters. The four types (colors) of photodiodes are interdigitated to minimize the effect of non-uniformity of incident irradiance. All photodiodes of the same color are connected in parallel. Pins S2 and S3 are used to select which group of photodiodes (red, green, blue, clear) are active.

Materials needed:

Step 1: Circuit

Construct a circuit as shown above:

  • Sensor S0 to D2
  • Sensor S1 to D3
  • Sensor S2 to D4
  • Sensor S3 to D5
  • Sensor out to D6
  • Red LED to D7
  • Green LED to D8
  • Blue LED to D9

Step 2: Code

Upload the following code in the IDE:

//Arduino pins:
#define S0 2
#define S1 3
#define S2 4
#define S3 5
#define sensorOut 6
#define redLED 7
#define greenLED 8
#define blueLED 9
//Output from the sensor:
int redFrequency = 0;
int greenFrequency = 0;
int blueFrequency = 0;
//Formatted color values:
int redColor = 0;
int greenColor = 0;
int blueColor = 0;
//Values used for calibration
int redMin;
int redMax;
int greenMin;
int greenMax;
int blueMin;
int blueMax;
int color = 0;
void setup() {
 //Declarations:
 pinMode(S0, OUTPUT);
 pinMode(S1, OUTPUT);
 pinMode(S2, OUTPUT);
 pinMode(S3, OUTPUT);
 pinMode(redLED, OUTPUT);
 pinMode(greenLED, OUTPUT);
 pinMode(blueLED, OUTPUT);
 pinMode(13, OUTPUT);
 pinMode(sensorOut, INPUT);
 // Set frequency scaling to 20%:
 digitalWrite(S0, HIGH);
 digitalWrite(S1, LOW);
 Serial.begin(9600);//begin serial communication
 calibrate();//calibrate sensor (look at serial monitor)
}
void loop() {
 readColor();//read sensor
 decideColor();//format color values
 printColor();//print values
}
void decideColor() {//format color values
 //Limit possible values:
 redColor = constrain(redColor, 0, 255);
 greenColor = constrain(greenColor, 0, 255);
 blueColor = constrain(blueColor, 0, 255);
 //find brightest color:
 int maxVal = max(redColor, blueColor);
 maxVal = max(maxVal, greenColor);
 //map new values
 redColor = map(redColor, 0, maxVal, 0, 255);
 greenColor = map(greenColor, 0, maxVal, 0, 255);
 blueColor = map(blueColor, 0, maxVal, 0, 255);
 redColor = constrain(redColor, 0, 255);
 greenColor = constrain(greenColor, 0, 255);
 blueColor = constrain(blueColor, 0, 255);
 //light led
 analogWrite(redLED, redColor);
 analogWrite(greenLED, greenColor);
 analogWrite(blueLED, blueColor);
 //decide which color is present (you may need to change some values here):
 if (redColor > 250 && greenColor > 250 && blueColor > 250) {
   color = 1;//white
 }
 else if (redColor < 25 && greenColor < 25 && blueColor < 25) {
   color = 2;//black
 }
 else if (redColor > 200 &&  greenColor > 200 && blueColor < 100) {
   color = 4;//yellow
 }
 else if (redColor > 200 &&  greenColor > 25 /*&& blueColor < 100*/) {
   color = 3;//orange
 }
 else if (redColor > 200 &&  greenColor < 100 && blueColor > 200) {
   color = 5;//purple
 }
 else if (redColor > 250 && greenColor < 200 && blueColor < 200) {
   color = 6;//red
 }
 else if (redColor < 200 && greenColor > 250 && blueColor < 200) {
   color = 7;//green
 }
 else if (redColor < 200 /*&& greenColor < 200*/ && blueColor > 250) {
   color = 8;//blue
 }
 else {
   color = 0;//unknown
 }
}
void calibrate() {
 Serial.println("Calibrating...");
 Serial.println("White");//aim sensor at something white
 //set calibration values:
 digitalWrite(13, HIGH);
 delay(2000);
 digitalWrite(S2, LOW);
 digitalWrite(S3, LOW);
 redMin = pulseIn(sensorOut, LOW);
 delay(100);
 digitalWrite(S2, HIGH);
 digitalWrite(S3, HIGH);
 greenMin = pulseIn(sensorOut, LOW);
 delay(100);
 digitalWrite(S2, LOW);
 digitalWrite(S3, HIGH);
 blueMin = pulseIn(sensorOut, LOW);
 delay(100);
 Serial.println("next...");//aim sensor at something black
 digitalWrite(13, LOW);
 delay(2000);
 Serial.println("Black");
 //set calibration values:
 digitalWrite(13, HIGH);
 delay(2000);
 digitalWrite(S2, LOW);
 digitalWrite(S3, LOW);
 redMax = pulseIn(sensorOut, LOW);
 delay(100);
 digitalWrite(S2, HIGH);
 digitalWrite(S3, HIGH);
 greenMax = pulseIn(sensorOut, LOW);
 delay(100);
 digitalWrite(S2, LOW);
 digitalWrite(S3, HIGH);
 blueMax = pulseIn(sensorOut, LOW);
 delay(100);
 Serial.println("Done calibrating.");
 digitalWrite(13, LOW);
}
void printColor() {//print data
 Serial.print("R = ");
 Serial.print(redColor);
 Serial.print(" G = ");
 Serial.print(greenColor);
 Serial.print(" B = ");
 Serial.print(blueColor);
 Serial.print(" Color: ");
 switch (color) {
   case 1: Serial.println("WHITE"); break;
   case 2: Serial.println("BLACK"); break;
   case 3: Serial.println("ORANGE"); break;
   case 4: Serial.println("YELLOW"); break;
   case 5: Serial.println("PURPLE"); break;
   case 6: Serial.println("RED"); break;
   case 7: Serial.println("GREEN"); break;
   case 8: Serial.println("BLUE"); break;
   default: Serial.println("unknown"); break;
 }
}
void readColor() {//get data from sensor
 //red:
 digitalWrite(S2, LOW);
 digitalWrite(S3, LOW);
 redFrequency = pulseIn(sensorOut, LOW);
 redColor = map(redFrequency, redMin, redMax, 255, 0);
 delay(100);
 //green:
 digitalWrite(S2, HIGH);
 digitalWrite(S3, HIGH);
 greenFrequency = pulseIn(sensorOut, LOW);
 greenColor = map(greenFrequency, greenMin, greenMax, 255, 0);
 delay(100);
 //blue:
 digitalWrite(S2, LOW);
 digitalWrite(S3, HIGH);
 blueFrequency = pulseIn(sensorOut, LOW);
 blueColor = map(blueFrequency, blueMin, blueMax, 255, 0);
 delay(100);
}

Step 3: Calibration

in the function

 void decideColor()

you may need to edit the values in this section:

if (redColor > 250 && greenColor > 250 && blueColor > 250) {
   color = 1;//white
 }
 else if (...) {

For example, you may need to change

redColor > 250 

to

redColor > 230

and so on. However, this part of the code is only used for "active" color detection (as opposed to passive), so you may comment it out entirely if you want to.

Step 4: How to Use

Once you are ready to use the sensor, you need to go through the initial calibration:

  1. Connect your board and open the serial monitor
  2. Aim the sensor at something white about 1" away
  3. Wait for the serial monitor to say "next"
  4. Aim the sensor at something black at the same distance
  5. Wait for the serial monitor to say "done calibrating"

Now the sensor should be calibrated and you are ready to use it:

  • Passive detection: Simply point it at something and the LED should change to match the detected color
  • Active detection: open the serial monitor and watch for the sensor values to come in. To the right of these is a section that says ____ detected. If these colors seem inaccurate, remember to adjust the values discussed step 3