I am going to show you how you can use an RGB LED and a Cds photocell as a colour sensor for a micro-controller. I will illustrate the method to retrieve a colour using Arduino, and I will show you a how you can verify the colour being scanned with a small Processing sketch.

We will be making this colour sensor on a breadboard, but it is easily transferred onto a prototyping board, and for those who fab their own boards, this would be an awesome kit that is super cheap to throw together. I am sure it would only take about two minutes to write a gerber file for this circuit and make a nice little finished sensor.

Step 1: Gather Some Parts

For this sensor you will need
  • a breadboard (not required, but it is how I will walk you through it.)
  • an RGB LED (alternatively you could use 3 LEDs)
  • A 220 ohm resistor
  • A CdS photocell (these can be salvaged out of all kinds of things like nightlights or garden lamps)
  • An Arduino, or a clone. I am using a RBB in this example

Tools you will need
  • A computer
  • a cable to upload to your Arduino

Step 2: A Little Theory

Some of you might be wondering how a CdS photocell can detect colours. Well it is surprisingly simple and provides pretty accurate results.

We see colour as a frequency of light reflected from an object. So different colours reflect different wavelengths which our eyes then interpret as colours. (Maybe brain...I am no scientist)

A common CdS photocell has a very similar response to colour as the human eye.

Because colours absorb certain wavelengths and reflect certain wavelengths, we can use different wavelengths(colours) of light and take readings(from a sensor that has nearly human responses) and thereby make a pretty good guess at what colour the sensor is being exposed to.

Step 3: Build the Circuit

I have included both images of the breadboard arrangment, and a small diagram to show you how to wire up the sensor to the Arduino.

The circuit is really simple. First we will look at the RGB LED half of the sensor. It is simply a common cathode RGB LED connected to pins 2,3, and 4 of the Arduino with a 220 ohm resistor going out to ground. This will allow us to turn each of the LEDs within the package on and off individually when we need to.

On the other side of the circuit we have a Cds photocell being fed 5 volts from the arduino. combined with the resistor going out to ground this effectively creates a voltage divider which allows us to read a changing analog value on analog pin 0.

This sensor works great on a breadboard, but it works even better if you put it into a more permanent enclosure to minimilize ambient light interference. The photo of the light tight (ish) enclosure was used in another one of my projects and is included here only to illustrate what I meant. (Feel free to check it out though, here.)

Step 4: Code the Arduino

Open up the Arduino environment, and create a new sketch by clicking File - New. For those that don`t want to follow along, I have included the code as a text file. Copy/Paste it into a new sketch in Arduino, and you are good to go.


The beginning of a sketch is where we make our declarations, so type the following code into the environment window.
// Define colour sensor LED pins
int ledArray[] = {2,3,4};

// boolean to know if the balance has been set
boolean balanceSet = false;

//place holders for colour detected
int red = 0;
int green = 0;
int blue = 0;

//floats to hold colour arrays
float colourArray[] = {0,0,0};
float whiteArray[] = {0,0,0};
float blackArray[] = {0,0,0};

//place holder for average
int avgRead;

'//' is reserved for denoted comments, therefore you do not need the text on lines that begin with '//' for the sketch to work.

The rest of it are some names that we are giving to some placeholders, and the declarations for what kind of data they will contain.

As you can see, we start by setting up an array to hold the pin numbers. These correspond to the pins that the different colour LEDs are conected to on the Arduino.

Next we declare a Boolean value to check whether or not balancing has been performed. A Boolean value is something that returns true or false.

We go on to create some place holders for the colour values, and some arrays to use for holding the scan data and balancing the detected colour.

Although we are not finished yet, go ahead and save your sketch. Give it a name that is meaningful to you, something like coloursensor.pde maybe.


The next step in creating an Arduino sketch is to write the setup function. Setup is run when the Arduino first boots up, so this is where we tell the Arduino what how we want to use the pins and setup other features that we may need such as serial communication.

Type the following below the code that you just entered.

void setup(){
  //setup the outputs for the colour sensor
  //begin serial communication

Not much to this section. Here we are just telling the Arduino that we intend on using pins 2,3,and 4 as outputs. This is neccesary if we want to light our LEDs...and we do, if only very briefly.

The next part is to tell the Arduino that we intend to make use of the serial port, and that it should be opened and ready to communicate at the baud rate specified (in brackets).


The loop function is typically where the magic happens in an Arduino. It is the code that is run over and over again once the Arduino is booted and setup has been passed through. Put the next bit of code under your setup function.

void loop(){


Okay at first glance it looks like there really is not much there. But these are each calls to private functions. For some projects I find this type of approach works well. It makes it easier to read (I think) as each block of code is seperated with a meaningful name, and we can see what the sketch is going to do at a glance.

First it will check the balance, then it will check the colour, and then it will print the colour to the serial port so we can see the values that it read.

Let`s explore the first private function, checkBalance, and add it to our code. Type the following below your loop function.
void checkBalance(){
  //check if the balance has been set, if not, set it
  if(balanceSet == false){

As you can see, if the balanceSet value (a boolean value) is set to false, then it makes a call to a secondary function called setBalance, where we set the white and black balancing readings. This will only happen when you boot up the arduino the one time.
void setBalance(){
  //set white balance
   delay(5000);                              //delay for five seconds, this gives us time to get a white sample in front of our sensor
  //scan the white sample.
  //go through each light, get a reading, set the base reading for each colour red, green, and blue to the white array
  for(int i = 0;i<=2;i++){
     getReading(5);          //number is the number of scans to take for average, this whole function is redundant, one reading works just as well.
     whiteArray[i] = avgRead;
  //done scanning white, now it will pulse blue to tell you that it is time for the black (or grey) sample.
   //set black balance
    delay(5000);              //wait for five seconds so we can position our black sample 
  //go ahead and scan, sets the colour values for red, green, and blue when exposed to black
  for(int i = 0;i<=2;i++){
     blackArray[i] = avgRead;
     //blackArray[i] = analogRead(2);
   //set boolean value so we know that balance is set
  balanceSet = true;
  delay(5000);     //delay another 5 seconds to let us catch up

If you noticed, we made yet another call to a function getReading.  We will add that right after we put in the checkColour function.

Once our balancing numbers have been set, we go on to finally read the colour. The function is basically the same as setBalance,, with the addition of the math that balances the reading. Let`s add it now.
void checkColour(){
    for(int i = 0;i<=2;i++){
     digitalWrite(ledArray[i],HIGH);  //turn or the LED, red, green or blue depending which iteration
     delay(100);                      //delay to allow CdS to stabalize, they are slow
     getReading(5);                  //take a reading however many times
     colourArray[i] = avgRead;        //set the current colour in the array to the average reading
     float greyDiff = whiteArray[i] - blackArray[i];                    //the highest possible return minus the lowest returns the area for values in between
     colourArray[i] = (colourArray[i] - blackArray[i])/(greyDiff)*255; //the reading returned minus the lowest value divided by the possible range multiplied by 255 will give us a value roughly between 0-255 representing the value for the current reflectivity(for the colour it is exposed to) of what is being scanned
     digitalWrite(ledArray[i],LOW);   //turn off the current LED

We will also need to add our function getReading, otherwise our sketch won`t have real values. This function just allows us to take a few readings and average them out. This allows for a slightly smoother reading.
void getReading(int times){
  int reading;
  int tally=0;
  //take the reading however many times was requested and add them up
for(int i = 0;i < times;i++){
   reading = analogRead(0);
   tally = reading + tally;
//calculate the average and set it
avgRead = (tally)/times;

Now we have a colour read into our colour holding array, all we need to do now is output it to the screen. Remember that we setup serial communication back in the setup function, all we have to do now is use the serial port to send out our data. The Arduino environment includes a serial monitor, which will allow you to see the data as it is passed from the Arduino. So let`s add the last function to the sketch.
//prints the colour in the colour array, in the next step, we will send this to processing to see how good the sensor works.
void printColour(){
Serial.print("R = ");
Serial.print("G = ");
Serial.print("B = ");

This will print out some data that looks something like this
R = 231
G = 71
B = 0
which would be the equivilent to a red-orange colour.
I have left this sketch super simple. You can dress it up as you see fit. The idea is to show how to make and use the sensor, creative implementation is up to you.

Now you can save your file again and upload it to the Arduino. Your Arduino should start running the sketch, the little lights should be flickering.

The sketch is very basic. I have offered it as a building block and to show you how to use the sensor.


Step 5: Balancing the Sensor

If you remember the code from earlier, the first thing that our sketch does is check to see if the balance values have been taken. When you turn on your sensor, this will be set to false and therefore the sketch will then call for the balance values to be set.

The way we do that is simple, we just show the sensor a sample of white (white card or paper) and a sample of black (black marker on a white paper or black paper). I say paper, but the sample can be anything, as long as the first sample is white and the second is black.

Take ten seconds, and prepare a quick sample card with a white side and a black side.

You will need to have the white sample in front of the sensor when you start up the Arduino (you only have 5 seconds to get it there). Once it flashes once (That is it scanning the white colour and recording the values it recieves), you will need to replace your sample with a black  sample, you have five seconds to do that. It will flash again, wait another 5 seconds, and then start reporting.

Your readings will only be as good as your balancing values, so try and pay attention to taking the readings at roughly the same distance from the sensor. Alternating the height will certainly change the reflected light that falls back to the CdS photocell, but this is a fairly robust little setup and delivers very admiral results for the cost.

If you balanced it properly, you are now reading colours. Place things in front of the sensor and verify your output via the serial monitor in the Arduino environment. You should be getting back changing data in roughly the format I showed you above. If you are impatient you can start plugging these numbers into a colour selector (There are many free online, there is even one in the processing environment) and start entering your reading numbers and seeing what the selector shows.

Or you can follow along for one more step, where I will give you a little Processing sketch that will help you verify that your sensor is functioning well, and make it more fun to experiment with.

Step 6: Verify Colours With Processing

At this point you should have Red, Green and Blue values coming up on your screen via the Arduino serial monitor. Entering these values by hand in is tedious and slow.

Sure it proves the point, but we really need a better way to play with this don`t we.

Have no fear, I have included a small Processing sketch to get you started.

Copy and paste the code in the included text file into a new sketch in Processing. Save it as whatever you like, start up your Arduino, being sure that the Serial Monitor in the Arduino environment is no longer running, and enjoy the color changing light show.

The sketch doesn't do much, it just updates the background with the colour being sent out from the sensor. Make sure that you set the com Port correctly.

In the pictures, you can see me scanning each side of a four coloured juggling ball, and the output on the screen. 

I hope that this Instructable has proved interesting to you. If you want to have a look at one of the ways I have used this type of sensor, check out my Magical Chameleon Lamp Instructable.

Support a fellow maker, vote for me often. Share and enjoy.
<p>hey sir can u help me out </p><p>sir i m actually making a project with IR sensors so i want to know what is the throughput of </p><p>1-bluegreen </p><p>2-stonegrey colour</p><p>3-magenta colour </p><p>my main idea would be that IR sensors would send up radiation and then according to these 3 throughput it would give me the result</p><p>THANK Q SIR/MADAM IN ADVANCE </p>
<p>Thank you so much for posting this!! It works perfectly!! Exactly what I needed for my robot project!! </p>
This is excellent! <br> <br>Have you seen any problems with the red color - due to the spike in sensitivity that the LDR has?
Not so much, balancing against the white and black is important. Basically you are subtracting the reflection recieved from the black (theoretically 'no reflection') before deciding what colour you are seeing. each colour is flashed seperate and has its own balancing value. This does a fairly decent job at correction. <br>If you are having difficulty with a certain range, you can 'trick' it to perform better by changing your black balance. Might have been a good idea to add a pot for fine tuning without rescanning. Thanks for the compliment. Not much to it, throw one together and play. Cheers.
<p>I will provide a brief report of 1 &ndash; 2 pages (length for guidance only) documenting the best strategy for interfacing the colour sensor with the microprocessor. MY decision should be clearly justified the colour are red green and white microprocessor pic 18f2455 and also i will carry out design work on the code and produce a set of design notes which may include:</p><p> a flow chart of the operation of the program,</p><p> a list of the I/O pin allocations</p><p> A list of the subroutines you will use.</p><p> Pseudocode outline for your program</p><p>have you any idea or can you help me i???</p>
LEDs can be used as sensors, too.
Yes they can, but I don't think they would have the sensitivity for this. Maybe if you took a reading from a Red housing one, a green housing one, and a blue housing one(do they make those) and really padded the numbers.......hmmm, I might look into it in the future. But my gut says that it probably would not have the sensitivity of this setup.
<p>I am struggling against the LED's all alone as light sensors in a project to build a photometer at the University. I can surely tell you they aren't that sensible.</p>
<p>Hi everyone! I was thinking about a robot that can return a ball and I was looking at this to detect the ball.</p><p>My queston is, if the ball is lets say red and we're making it run on a white desk, from how far can a sensor like this detect that the color of the ball is different from the rest of the table/floor? </p><p>So that the robot can go there and &quot;take it&quot;</p>
<p>Good Afternoon,</p><p>This works only when the LEDs glow, as per the reflection but sir can you please provide a solution where in color can be detected without using LED, that is directly on seeing a colored object it should display the color on monitor.</p>
<p>Just use three photo sensors each one having a different (RGB) color filter. This will give you three independent values representing the amount of each color that is being emitted / reflected by the object. You then use those values to display the color on your screen.</p><p>Note: The colors will not be very accurately displayed because your eyes, the photo sensors, the illumination source, and the display are not very linear.</p>
<p>Good afternoon</p><p> I<br>want to know if there is color identify sensor that support android ?</p><p>like an android app can integrate with that sensor because I<br>want the voice from android app to tell what color is this</p><p>Please contact by call or whatsApp 00971 52 610 3200</p><p>Thanks</p>
<p>you can diy one ?</p><p>just add bluetooth module to this diy and connect it to your android device </p><p>----------------</p><p>you can modify this function , so that the arduino gives you the desirable response </p><p><strong>void printColour(){<br><br> Serial.print(&quot;R = &quot;);<br><br> Serial.println(int(colourArray[0]));<br><br> Serial.print(&quot;G = &quot;);<br><br> Serial.println(int(colourArray[1]));<br><br> Serial.print(&quot;B = &quot;);<br><br> Serial.println(int(colourArray[2]));<br><br> //delay(2000);<br><br> }</strong></p><p>i like using this form :D </p><p>RRR,GGG,BBB\n</p><p>modification :</p><p><strong>void printColour(){<br><br> Serial.print(int(colourArray[0]));<br><br> Serial.print(&quot;, &quot;);<br><br> Serial.print(int(colourArray[1]));<br><br> Serial.print(&quot;,&quot;);<br><br> Serial.print(int(colourArray[2]));<br></strong></p><p><strong>Serial.print(&quot;\n&quot;);<br><br> //delay(2000);<br><br> }<br></strong></p>
<p>Hi! Super cool project! I followed your instructable, uploaded my code, and &quot;balanced&quot; for white and black. However, even after balancing the serial monitor was reporting crazy values (in the thousands and negative) for each of the colors. I was wondering if anyone else had this problem or if you have any ideas of what could be going wrong. I have included a photo of my setup and the code is just the one posted. </p>
Can i detect the colour of an led with this project? Or do we need any modification help please need urgently.
<p>Good question, I'm looking to do this too so hope it can be done. My LED detection needs to be quite quick as LEDs are only on for a short time.</p>
<p>Hi,<br>This looks like a really exciting project and I'd like to ask you something.<br>I'd like know how accurate the color detection is. Sorry if this is a stupid question, I have no experience in the field. I'm a graphic designer and illustrator and lately I've been feeling a dire need for a real life color picker. A few devices like that exist already, but they all come from Kickstarter (which is okay by itself, but I avoid first generation Kickstarter gadgets because of past experiences).</p><p>So what I'd like to know is whether I can trust the color detection device to pick the color of say a person's skin and use that color in illustration work.<br></p>
<p>Not working for me, any common problems i should address?</p>
<p>Hi! I just want to say that this is one of the cleanest, most helpful instructables I've ever seen! The way you presented the code makes perfect sense, and I wish it became a standard practice for all Arduino texts. I am relatively new, and I didn't even need to build this (although I plan to!) to understand exactly how it works, thanks!!</p>
<p>good job </p>
<p>Thanks a lot.</p><p>I made a few adjustments, like a continual update in colour that was sensed by using three photocells (one for each colour). The code and explanation of it really helped a lot.</p>
<p>why not just put the call to <strong>setBalance() </strong>in startup?<br><br>Amazing project :) I'm working on a PCB for it now, so I can use this in some of my upcoming projects :D</p>
<p>How small can the object be for the photocell to detect the color? Could this model be used to detect the wavelength of something in a solution, like a protein?</p>
<p>No reason why not, as long as you can get it into a light proof box. I've seen it done before...</p>
<p>I really love this and i just tried it and works greaaat !!!! and this is very well explained, i only have one question,<br>can you explaine to me how did you find this please ? <br>c<strong>olourArray[i] = (colourArray[i] - blackArray[i])/(greyDiff)*255</strong></p>
<p>this is excelent !!!!!! and very well explained !!</p><p>I tried it and it works very good !! :D thank youu !!</p><p>does the balancing need to be done each time runing the programme ?</p>
<p>Thanks for the exerted effort ; but there is something i don't get - Excuse me i'm a beginner - ... what 's the use of the three leds ( red , green and blue ) ? iam not using RGB led ... are they indicators for the values read from the photocell depending on the colors applied and detected and though will be lightening separately ? or they are already working in the beginning of the code and we are using them for calibration ??</p>
<p>hi,</p><p>can you send me the schematic or the circuit diagram? renel14@yahoo.com</p><p>thank you.</p>
<p>It looks like the author already put the schematic in the tutorial.</p>
<p>I used this code as a general example for my color sensor. I'm still learning a few things about arduinos and coding, so I have just a few questions for curiosity.</p><p>1) Where did you derive the equation to find the actual color in the check color function?</p><p>2) Why did you use the tally in the for loop in the getreading function? why didn't you just use reading?</p><p>Thanks!! Also, great tutorial!!!</p>
<p>Hi dear, i have need of this project how can built it and i was also tried to make this type of project named {Arduino magic light with touch foil} and this named project you can search in google, but i couldn't make it. and you project is so simple so can you send me overall discriptioins of your project at bcs.waseem@yahoo.com. please</p>
<p>can u send me the more specific schematic? ive tried the schematic given but it wont work. email: farzul_92@yahoo.com</p>
If I put red in front the R value is highest, same for G and B. How do I detect black? Or white?
so that means you will use the RGB LED to detect colors. Isn't it? <br>Also your idea is an awesome one. But it will be better if it can sense colors with a white led by using the technique of the RGB combination. I am going to make one with three LDRs and a small RGB LED to show which color it is.
hi there.. im an undergrad doing a project with sensors.. and I find this very useful.. but I just wanna check is this sensor able to detect different shades of colour.. for example, blue.. can it detect different shades of blue like coral blue/navy blue/royal blue.. and for red..
Hey it is a very helpful tutorial. I too wanna make one but the color output to be in an audio form. The one like my speaking colour sensor. What should be special requirements for that?
hello..could you pls send me a schematic of this project..because i want to put a LCD to show the color that is being detected, so that i can know where should i put it
thank you for the idea!!!
My son is color blind. Often times he'll ask us what color something is. Could this help with that. Is it able to detect colors that are not real brigh, such as in clothing?
This is pretty neat! Thanks for sharing and good luck in the contest. :)
Hello, <br><br>I have a project and I need to detect White Red Blue and green colors.<br>The PIC microcontroller code is done, i just need the schematic to build my project <br>I must also use 4 sirenges (one for each color) for the color mixing part<br>I appreciate your prompt help, i need it for my project. <br> Plzzz<br><br>Thank you :D
Sounds like an interesting project, but it is well beyond the scope of this instructable.
Hello, <br><br>I have a project and I need to detect White Red Blue and green colors.<br>I must also use 4 sirenges (one for each color) <br>I appreciate your prompt help.<br><br>Thank you :D
This sensor will help you with detecting the colours.
This is a great project. I documented my results doing the same here http://uscee.wordpress.com/
Great Job!! Glad to see that everything works well. Nice documentation too.<br> Did you try out the processing sketch? It is a quicker way to see the colour.<br> I noticed that you will be working on getting an LED to light the same colour next, check out my <a href="https://www.instructables.com/id/Magical-Chameleon-Lamp/" rel="nofollow">Magical chameleon lamp</a> project if you need any pointers.<br> Cheers!
Nicely written - <br><br>I will put it together and try it, but until then - curious if know how surface finish/texture of the object being scanned effects the reading. Also, as a derivative of that question, will it sense equally well through a clear film, glass, etc?<br><br>Thanks
It should work fine through a film so long as no frequecies are being blocked. Reflectivity will play with the readings a bit.<br>Cheers.
I think it should be noted that the colors output are qualitative only. The RGB values output by this device are from it's own non-standard color space that is not the same as sRGB (i.e. the RGB displayed by a monitor). Your code also assumes that LEDs and photoresistors have linear responses which they do not. Calibration should only need to be done once, if the calibration values are stored in the EEPROM. However, it might be interesting to see what strange colors you get when you calibrate using a non-white target.
I don't claim that the values output by the sensor are the the same output as a monitor, only that it is easy to ouput the colour that the sensor 'sees' to the monitor, given that the values are in the same range. Have you tried it out? Or are you finding flaws in theory? I find that it gives quite accurate results. I.e the colours being displayed on the monitor very closely resemble the object being scanned. <br>You can certainly mess with the readings by providing a yellow sample in place of white. But that would be true of just about anything. Just try wearing a pair of yellow ski goggles around and see how effective your own colour perception becomes. <br>

About This Instructable




Bio: Dad, maker, dreamer, hacker, painter.
More by fjordcarver:Make A 2D Video Game with Unity Acoustic/Electric Cookie Tin Unitar Make a Keepsake Book of your Child's Artwork 
Add instructable to: