Arduino Color Detection using TCS3200 – TCS230 (GY-31) color sensor module + RGB project
Hello and welcome to SurtrTech, in this tutorial we’ll be using the TCS3200, TCS230 or GY-31, color sensor module with Arduino UNO board, and there will be a project using a RGB LED to reproduce the detected colors.
The module has an 8×8 photodiode array, 16 of them with a red filter, 16 with a blue one, 16 with a green one and 16 without a filter (clear), we select what filter to use and read its value, and in the code we combine them depending on the application or project.
The light is detected by the photodiodes and the output is a frequency proportional to the current flowing through the photodiodes which is related to the filter used and the object’s color detected.
-The module has (Vcc/GND) pins, they are redundant.
– S0/S1 pins control the output frequency scaling.
– S2/S3 pins control which set of photodiodes we gonna measure (Red/Green/Blue/Clear)
– Out is the output signal and LED pin controls the LEDs lights on the front.
This option permits the module to be used with different measuring techniques, and types of microcontrollers, in the tutorial and codes I kept using it at 100%, you can change it if you want, it depends just on the logic level of their pins (HIGH/LOW).
By also controlling the logic levels of S2/S3 we can select which filter or no filter to use, in the code I go through Red/Green/Blue, if your application require one or two filters only you can do it too.
For the LED pin, if it’s not connected, the LEDs will light up automatically, but if you want to turn them off you can put the LED pin to LOW.
For the Out pin, as the signal given by the sensor is a frequency, we measure the duration as they are related (Duration=1/Frequency), so the higher the frequency of a color, the lower is the duration measured, which means that the object detected has a certain color (check the video tutorial above).
Hardware and parts
We’ll be using the Arduino UNO board as usual, the RGB LED is optional and only used with the project I did, and of course I added some jump wire…
Wirings
Vcc/GND are the same chose which one you want to use, pay attention some modules have “OE” pin, leave it on LOW level otherwise it turns off the module.
Wiring 1: Basic wiring of the module
Wiring 2: Adding RGB LED for the project
Don’t forget the RGB should be connected to PWM pins and here I have a common cathode one.
Codes
Code 1:
Code 1 Is just direct wiring and reading the output signal for Red/Blue/Green, you can use it to calibrate your module, for example place some object and check the sensor values, because those values are related to the lighting conditions, exposure, and the object itself. Download the code here or check below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
/* This code works with GY-31 TCS3200 TCS230 color sensor module * It select a photodiode set and read its value (Red Set/Blue set/Green set) and displays it on the Serial monitor * Refer to http://www.surtrtech.com for more details */ #define s0 8 //Module pins wiring #define s1 9 #define s2 10 #define s3 11 #define out 12 int data=0; //This is where we're going to stock our values void setup() { pinMode(s0,OUTPUT); //pin modes pinMode(s1,OUTPUT); pinMode(s2,OUTPUT); pinMode(s3,OUTPUT); pinMode(out,INPUT); Serial.begin(9600); //intialize the serial monitor baud rate digitalWrite(s0,HIGH); //Putting S0/S1 on HIGH/HIGH levels means the output frequency scalling is at 100% (recommended) digitalWrite(s1,HIGH); //LOW/LOW is off HIGH/LOW is 20% and LOW/HIGH is 2% } void loop() //Every 2s we select a photodiodes set and read its data { digitalWrite(s2,LOW); //S2/S3 levels define which set of photodiodes we are using LOW/LOW is for RED LOW/HIGH is for Blue and HIGH/HIGH is for green digitalWrite(s3,LOW); Serial.print("Red value= "); GetData(); //Executing GetData function to get the value digitalWrite(s2,LOW); digitalWrite(s3,HIGH); Serial.print("Blue value= "); GetData(); digitalWrite(s2,HIGH); digitalWrite(s3,HIGH); Serial.print("Green value= "); GetData(); Serial.println(); delay(2000); } void GetData(){ data=pulseIn(out,LOW); //here we wait until "out" go LOW, we start measuring the duration and stops when "out" is HIGH again Serial.print(data); //it's a time duration measured, which is related to frequency as the sensor gives a frequency depending on the color Serial.print("\t"); //The higher the frequency the lower the duration delay(20); } |
Code 2:
Now we have an idea about the values for each color, we can start identifying them, the easy method is that during first tests you’ll notice that the color of the object has the lowest value, which is a duration, (higher frequency), check tests below. Download the code here or check below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
/* This code works with GY-31 TCS3200 TCS230 color sensor module * It select a photodiode set and read its value (Red Set/Blue set/Green set) and displays it on the Serial monitor * and identify if possible the color * Refer to http://www.surtrtech.com for more details */ #define s0 8 //Module pins wiring #define s1 9 #define s2 10 #define s3 11 #define out 12 int Red=0, Blue=0, Green=0; //RGB values void setup() { pinMode(s0,OUTPUT); //pin modes pinMode(s1,OUTPUT); pinMode(s2,OUTPUT); pinMode(s3,OUTPUT); pinMode(out,INPUT); Serial.begin(9600); //intialize the serial monitor baud rate digitalWrite(s0,HIGH); //Putting S0/S1 on HIGH/HIGH levels means the output frequency scalling is at 100% (recommended) digitalWrite(s1,HIGH); //LOW/LOW is off HIGH/LOW is 20% and LOW/HIGH is 2% } void loop(){ GetColors(); //Execute the GetColors function to get the value of each RGB color //Depending of the RGB values given by the sensor we can define the color and displays it on the monitor if (Red <=15 && Green <=15 && Blue <=15) //If the values are low it's likely the white color (all the colors are present) Serial.println("White"); else if (Red<Blue && Red<=Green && Red<23) //if Red value is the lowest one and smaller thant 23 it's likely Red Serial.println("Red"); else if (Blue<Green && Blue<Red && Blue<20) //Same thing for Blue Serial.println("Blue"); else if (Green<Red && Green-Blue<= 8) //Green it was a little tricky, you can do it using the same method as above (the lowest), but here I used a reflective object Serial.println("Green"); //which means the blue value is very low too, so I decided to check the difference between green and blue and see if it's acceptable else Serial.println("Unknown"); //if the color is not recognized, you can add as many as you want delay(2000); //2s delay you can modify if you want } void GetColors() { digitalWrite(s2, LOW); //S2/S3 levels define which set of photodiodes we are using LOW/LOW is for RED LOW/HIGH is for Blue and HIGH/HIGH is for green digitalWrite(s3, LOW); Red = pulseIn(out, digitalRead(out) == HIGH ? LOW : HIGH); //here we wait until "out" go LOW, we start measuring the duration and stops when "out" is HIGH again, if you have trouble with this expression check the bottom of the code delay(20); digitalWrite(s3, HIGH); //Here we select the other color (set of photodiodes) and measure the other colors value using the same techinque Blue = pulseIn(out, digitalRead(out) == HIGH ? LOW : HIGH); delay(20); digitalWrite(s2, HIGH); Green = pulseIn(out, digitalRead(out) == HIGH ? LOW : HIGH); delay(20); } //Here's an example how to understand that expression above, //""digitalRead(out) == HIGH ? LOW : HIGH"" this whole expression is either HIGH or LOW as pulseIn function requires a HIGH/LOW value on the second argument //led_Status = led_Status == HIGH ? LOW : HIGH; // //if(led_Status == HIGH) //{ //led_Status =LOW; //} //else //{ //led_Status = HIGH; //} |
Code 3:
Here we are using the RGB LED, and we try to reproduce the values of the colors given by the sensor, and most of the time it reproduce the color of the object detected, here what you should know: the min/max value given by the sensor for each color, and that it’s inverted (the lowest the value, the higher is the color).
1 |
analogWrite(LED_R,map(Red,15,60,255,0)); |
This is the function we used, so we generate a PWM signal with “analogWrite”, on the pin (LED_R) which is the Red pin for the RGB LED connected to pin D3, the value we write is proportional to “Red” value which is the Red value given by the sensor, and it has 15 as minimum and 60 as maximum (those are my proper values, try measuring your own), and this value is converted to 255-0,
so the 15 will be “equal” to 255 and 60 will be “equal” to 0
For example if the module gives us “15”, the LED_R will receive “255” value which is the highest (5V), because as said the lower the value the higher is the color)… Download the code here or check below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
/* This code works with GY-31 TCS3200 TCS230 color sensor module * It select a photodiode set and read its value (Red Set/Blue set/Green set) and reproduce the color on the RGB LED * Refer to http://www.surtrtech.com for more details */ #define s0 8 //Module pins wiring #define s1 9 #define s2 10 #define s3 11 #define out 12 #define LED_R 3 //LED pins, don't forget "pwm" #define LED_G 5 #define LED_B 6 int Red=0, Blue=0, Green=0; void setup() { pinMode(LED_R,OUTPUT); //pin modes pinMode(LED_G,OUTPUT); pinMode(LED_B,OUTPUT); pinMode(s0,OUTPUT); pinMode(s1,OUTPUT); pinMode(s2,OUTPUT); pinMode(s3,OUTPUT); pinMode(out,INPUT); Serial.begin(9600); //intialize the serial monitor baud rate digitalWrite(s0,HIGH); //Putting S0/S1 on HIGH/HIGH levels means the output frequency scalling is at 100% (recommended) digitalWrite(s1,HIGH); //LOW/LOW is off HIGH/LOW is 20% and LOW/HIGH is 2% } void loop() { GetColors(); //Execute the GetColors function analogWrite(LED_R,map(Red,15,60,255,0)); //analogWrite generates a PWM signal with 0-255 value (0 is 0V and 255 is 5V), LED_R is the pin where we are generating the signal, 15/60 are the min/max of the "Red" value, try measuring your own ones //e.g: if the "Red" value given by the sensor is 15 -> it will generate a pwm signal with 255 value on the LED_R pin same for 60->0, because the lower the value given by the sensor the higher is that color analogWrite(LED_G,map(Green,30,55,255,0)); analogWrite(LED_B,map(Blue,13,45,255,0)); } void GetColors() { digitalWrite(s2, LOW); //S2/S3 levels define which set of photodiodes we are using LOW/LOW is for RED LOW/HIGH is for Blue and HIGH/HIGH is for green digitalWrite(s3, LOW); Red = pulseIn(out, digitalRead(out) == HIGH ? LOW : HIGH); //here we wait until "out" go LOW, we start measuring the duration and stops when "out" is HIGH again, if you have trouble with this expression check the bottom of the code delay(20); digitalWrite(s3, HIGH); //Here we select the other color (set of photodiodes) and measure the other colors value using the same techinque Blue = pulseIn(out, digitalRead(out) == HIGH ? LOW : HIGH); delay(20); digitalWrite(s2, HIGH); Green = pulseIn(out, digitalRead(out) == HIGH ? LOW : HIGH); delay(20); } //Here's an example how to understand that expression above, //""digitalRead(out) == HIGH ? LOW : HIGH"" this whole expression is either HIGH or LOW as pulseIn function requires a HIGH/LOW value on the second argument //led_Status = led_Status == HIGH ? LOW : HIGH; // //if(led_Status == HIGH) //{ //led_Status =LOW; //} //else //{ //led_Status = HIGH; //} |
Tests
Test 1: Simple use and color detection
The last line shows the result when the module is exposed to the red surface, the red is the lowest value, the issue is that the surface is reflective which made the blue value low as well.
Test 2: Output the color instead of RGB values
Test 3: RGB LED to reproduce the color detected
Add-ons
- In the code 2, you can add as many colors as you want just measure their values
- Don’t change a lot the module placement and lighting when calibrating the module
- For the RGB code, the blue is very dominating, you can try to reduce it
Categories
Yassine View All
Automation and Electrical Engineer, Electronics amateur trying to share my little projects.
hi, what’s the difference tcs230and tcs 2300
TCS230 is newer, and the TCS3200/TCS3210 has two options, some have fewer photodiodes, not much big differences:
https://www.mouser.com/catalog/specsheets/TCS3200-E11.pdf
https://pdf1.alldatasheet.com/datasheet-pdf/view/202765/TAOS/TCS230.html