Introduction: Arduino Color Recognition
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:
- Arduino board: https://amzn.to/2DLjxR2
- Breadboard: https://amzn.to/2RYqiSK
- Jumper wires: https://amzn.to/2RYqiSK
- Male-female wires: https://amzn.to/2RYqiSK
- Color sensor: https://amzn.to/2RYqiSK
- RGB LED (common anode): https://amzn.to/2RYqiSK
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:
- Connect your board and open the serial monitor
- Aim the sensor at something white about 1" away
- Wait for the serial monitor to say "next"
- Aim the sensor at something black at the same distance
- 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