Arduino Color Sensor




Introduction: Arduino Color Sensor

Here we will be learning how to make a color sensor. my model consists of three cardboard compartments containing an LED - one red, one blue, and one green - and an OP550B phototransistor. The LED's shine simultaneously on a solid colored card. The phototransistors are connected to an Arduino Uno, which converts the relative amounts of measured reflected light of each color into RGB components which are used to light an RGB LED the same color as the card.

Video of it working:

Step 1: Materials

To make this color sensor, you will need:

* Red LED
* Green LED
* Blue LED
* 3 phototransistors - I used OP550B's, but others could be used.
* 6 220 ohm resistors
* 3 10k ohm resistors
* Cardboard or some other divider to separate the LED's
* Breadboard or circuit board and soldering materials
* wires
* Arduino and usb cord
* Computer
* Electrical tape
* Cards of various colors - I used index cards covered in electrical tape of different colors.

Step 2: Step 1: Create the Circuit Board

* See attached circuit diagram
* Make sure to leave enough room to superimpose the dividers - in my case a compartmentalized cardboard box - later.

Step 3: Step 2: Make the Light-Proof Box and Cards

A. Cut thin strips of cardboard just big enough to form a box enclosing the 3 LEDs and Phototransistors
B. Attach the outer box to the circuit board. I used a hot glue gun to do this, but clay or another opaque, malleable substance would be more effective for keeping light out.
C. Cut two more thin strips of cardboard the same height as the outer box, and just long enough to fit snugly inside the box.
D. Attach these inside the box to separate the three LED/transistor pairs. I taped the sides and bottom of the inner strips to the inside sides of the box with white electrical tape.
E. Cover the bottom of the circuit board with electrical tape to prevent outside light from getting through the holes in the circuit board.
F. Enclose the RGB LED in a light proof material like electrical tape to prevent it from interfering with measurements (see diagram).
G. Cover the sides of the box with electrical tape to reduce outside light interference.
H. Cut out several squares of index card big enough to cover the box. Cover each side with a single color of electrical tape.

Step 4: Step 3: Write Code

Here is my Arduino code. You will need to calibrate the const values based on how much light is in the room - comment out the indicated portion of the loop() method and note the RGB values it displays for different colored cards. Store those RGB values in the ICOLOR const int[]'s at the beginning of the script. If you did a good job of light-proofing the box, the same RGB values should work with various levels of background light.

/**Runs a color sensor on the Arduino
* Start the program while showing it the white card. When the RGB LED turns off,
* switch (quickly) to the black card. After the RGB LED flashes white, it is ready.
//pin identifiers
int blue = A2;
int green = A1;
int red = A0;
int redOut = 9;
int greenOut = 10;
int blueOut = 11;
//counts the number of loops - used to time events
int count = 0;
//stores the current RGB input
int out[3];
//ICOLOR = RGB input from transistor that is that color.
//COLOR = RGB output to make RGB LED show that color
int IWHITE[3] = {175,48,455}; int WHITE[3] = {224,226,243};
int IBLACK[3] = {42,5,20}; int OFF[3] = {0,0,0};
int IRED[3] = {145,15,38}; int RED[3] = {200,0,0};
int IYELLOW[3] = {175,40,60}; int YELLOW[3] = {255,150,0};
int IMAGENTA[3] = {150,16,83}; int MAGENTA[3] = {200,0,200};
int IBLUE[3] = {57,7,160}; int BLUE[3] = {0,0,200};
int IGREEN[3] = {41,6,50}; int GREEN[3] = {0,200,0};
int NONE[3];
//[0] of these is the min, [1] is the max.
int redConvert[2];
int greenConvert[2];
int blueConvert[2];

//reads in the current color
int* readColor(){
  int ret[3];
  ret[0] = analogRead(red);
  ret[1] = analogRead(green);
  ret[2] = analogRead(blue);
  return ret;

//checks that each element in color1 is within dev of
//the corresponding element in refColor
boolean inRange(int color1[], int refColor[], int dev){
  return (abs(color1[0] - refColor[0]) <= dev) &&
  abs(color1[1] - refColor[1]) <= dev &&
  abs(color1[2] - refColor[2]) <= dev;

//sets the RGB LED color
void setColor(int color[]){
  analogWrite(redOut, color[0]);
  analogWrite(greenOut, color[1]);
  analogWrite(blueOut, color[2]);

//determines values for black and white
void calibrate(){
  int redSum = 0;
  int greenSum = 0;
  int blueSum = 0;
  for(int i = 1; i <= 5; i++){
    redSum += analogRead(red);
    greenSum += analogRead(green);
    blueSum += analogRead(blue);
  int whiteCal[3] = {redSum/5,greenSum/5,blueSum/5};
  redSum = blueSum = greenSum = 0;
  Serial.print("white Cal (RGB): ");
  Serial.print(" ");
  Serial.print(" ");
  Serial.println("insert black card");
    Serial.print("red green blue: ");
    Serial.print(" ");
    Serial.print(" ");
  Serial.println("new card detected - I hope it's black");
  for(int i = 1; i <= 5; i++){
    redSum += analogRead(red);
    greenSum += analogRead(green);
    blueSum += analogRead(blue);
  int blackCal[3] = {redSum/5,greenSum/5,blueSum/5};
  Serial.print("black Cal (RGB): ");
  Serial.print(" ");
  Serial.print(" ");
  //calculate conversion functions
  redConvert[0] = blackCal[0];
  redConvert[1] = whiteCal[0];
  greenConvert[0] = blackCal[1];
  greenConvert[1] = whiteCal[1];
  blueConvert[0] = blackCal[2];
  blueConvert[1] = whiteCal[2];

//runs calibration routine and turns the light white before
//starting loop
void setup(){

void loop(){
  //reads in new values
  out[0] = analogRead(red);//0-1024
  out[1] = analogRead(green);
  out[2] = analogRead(blue);

//update RGB LED and print output less frequently
  if(count % 5000 == 0){
    Serial.print("red green blue: ");
    Serial.print(" ");
    Serial.print(" ");

//comment out the rest of this loop to just display values and not use the RGB LED
    else if(inRange(out,IRED,10)){
    else if(inRange(out,IBLUE,10)){
    else if(inRange(out,IYELLOW,10)){
    else if(inRange(out,IMAGENTA,10)){
    else if(inRange(out,IGREEN,10)){
    else setColor(OFF);

Step 5: Step 4: It Should Work!

Thanks for reading!

Video of it working:

1 Person Made This Project!


  • Leather Challenge

    Leather Challenge
  • Build a Tool Contest

    Build a Tool Contest
  • Digital Fabrication Student Design Challenge

    Digital Fabrication Student Design Challenge


your circuit diagram is not at all clear , and also i m using 2n5777 phototransistors which are 3terminal transistors , i connected the base with ground as usual , i m facing a problem while calibrating the whole device , every time it shows either 655,655,655 or 0,0,0 .

and i tried altering the codes a bit but that didn't helped me either , so i am hoping that if you could help me resolve this problem .

can you please get in touch ( , i want to discuss more things on Arduino .

the overall project was quite nice actually :)


7 years ago

Love this project! Working on it right now. This is my very first Arduino project and I am a bit clueless to say the least. Do you have an image of the bottom of the board so I can see the connections more clearly? Thanks!


7 years ago on Introduction

while for different color values...we are getting almost same values on the serial monitor...what could be the problm apart from the insulation


9 years ago on Introduction

I Have just one question.
Of what use is comparing colors to some one who is color blind like I am,
if you don't tell me what colors i am looking at ???


Reply 9 years ago on Introduction

Hi anoniemouse,

I had not considered that use case. If you add the following code to the setColor function, it should print the name of the color in addition to changing the color of the RGB LED. I haven't tested this code (I don't currently have access to the Arduino), but it compiles. Does this help? Thanks for your interest!

if (color == WHITE) {
  } else if (color == RED) {
  } else if (color == YELLOW) {
  } else if (color == MAGENTA) {
  } else if (color == BLUE) {
  } else if (color == GREEN) {
  } else {
    Serial.print("BLACK OR OFF OR UNREADABLE");


9 years ago on Introduction

Could you upload your video again, please?

When I turn on the program and show the white card, the RGB flashes a couple of colours but it does not turn off for me to switch to the black card. Any ideas? Also-to clarify, is the last section of the code required only if we want to adjust the RGB values? If we want to use the same values you wrote, then we should just keep that part of the code commented out, correct?


Reply 9 years ago on Introduction

Hi arnabc,

I re-uploaded the video. Did you get it working? Let me know if you have any more questions. Good luck!


Reply 9 years ago on Introduction

Sorry about the video - I deleted my Google Plus account a few weeks after I uploaded that video, and I didn't realize that would also delete my Youtube videos. I don't have the video with me now, but I should be able to re-upload it later this week.

This part is explained in the missing video. Sorry for the inconvenience.:
To do exactly what I did with the code as-is, you should have the white card showing when you start the program. The RGB LED should flash red, then green, then blue, then white for a longer time than the colors. After no more than about 2 seconds, the light should turn off. After it detects that the white card is no longer there, it should wait for 5 seconds (while you switch to the black card) and then do calculations based on the black card. After that finishes, the LED should turn white. When the LED turns white after being off, it is ready to read cards.

Did you set OFF to {0,0,0}? Can you post any serial output from when you tried to run it?

The last section of the code (from "//comment out the rest of this loop to just display values and not use the RGB LED" to the end of the if/else block) is the part that makes the RGB LED respond to the card changing. If you comment it out, it will dump RGB values to the serial output, and the LED will stay white. Is this the block of code you are referring to? None of it is commented out in the code I posted.

To generate the numbers I used, I ran the program with that code commented out and looked at the serial output when I showed it different cards. I noted the RGB values and the variation for each color card, and hard coded the average RGB values as the values in the ICOLOR arrays. So, to calibrate it for your cards/your background lighting, you should do the same. If you want to use the same values I wrote, you should not comment anything out. Does that answer your question?