Let's Make Robots!

$2 Color Detection Sensor

Detects the color of an object
AttachmentSize
ColourSensor.pde2.78 KB

SENSOR

My original inspiration was "http://www.societyofrobots.com/sensors_color.shtml". I made this sensor one evening long ago and have been meaning to share it as a good project for beginners. Basically wire it up like in the schematic and make sure all the LEDs point in such a way that any reflecting light will hit the photo resistor (I didn't do this well enough and had to compensate in the code for it). Run the code and tweak the calibration numbers to get it to work right.

The sensor works decently well for how simple it is. It can work with a variety of materials (in the video I use cloth, plastic, paper ect.). However the range is limited about 1 inch and if the objected is too angled it may not work at all. For best results keep the sensor normal to your sample surface.

It works because an object will reflect the most color that is of the same color as an object. This is why that object appears that color to us. This means a red object will reflect more of the red light than of the green, blue or yellow LED and cause the greatest change in the photo resistor readings. We can use this to determine color.

Future improvements on the projects can include using PWM to determine the exact shade of an object. Also modulation may be possible but some other sensor other than a photo resistor must be used (photo resistors don't have the response time for it). Perhpas a TSL230 or similar.

Check that your LEDs work ;)

And here is what it looks like after battling polymorph for an hour.....

MATERIALS
1 - Photoresistor
4 - 560 ohm resistors
1 - 10k resistor
4 - LEDs (Red, Blue, Yellow, Green)

SCHEMATIC

Here is the schematic of the sensor I made.



CODE

The code bellow is the one that I was running when I made the video. It continually turns the LEDs on to sample an object and then flashes one LED once it has reached a decision. It also prints all the numbers to a serial monitor so that you can see what the sensor sees and adjust it (If your physical one is as faulty as mine was....). The .pde file is included bellow for all you Arduino lovers. Remember a small cool down time is required for the photo resistor between samples.

**Uploaded Code with the faster runtime now.

//Pins
int photoResistor = 0;

int b = 2;
int r = 3;
int g = 4;
int y = 5;

//Calibration
// AKA Terrible software solution to a hardware problem....
double bAdj = 1.0;
double rAdj = 1.02;
double gAdj = 1.0;
double yAdj = 1.17;
double ambientAdj = 1.0;

void setup()
{
  pinMode(g, OUTPUT);
  pinMode(y, OUTPUT);
  pinMode(b, OUTPUT);
  pinMode(r, OUTPUT);
  pinMode(photoResistor, OUTPUT);
  Serial.begin(9600);
}

void loop()
{  
    allOff();
    delay(100);
    asses(100,100);
}

void allOff()
{
    digitalWrite(g, LOW);
    digitalWrite(y, LOW);
    digitalWrite(r, LOW);
    digitalWrite(b, LOW);
}

void allOn()
{
    digitalWrite(g, HIGH);
    digitalWrite(y, HIGH);
    digitalWrite(r, HIGH);
    digitalWrite(b, HIGH);
}

void pulse(int colour)
{
   for(int i=0;i<3;i++)
   {
      digitalWrite(colour, HIGH);
      delay(100);
      digitalWrite(colour, LOW);
      delay(100);
   }
}
 

void asses(int colldownTime, int saturationTime)
{
 
    delay(500);
    double ambient = analogRead(photoResistor);
    Serial.print("Ambient: ");
    Serial.println(ambient*ambientAdj);
    
    digitalWrite(g, HIGH);
    delay(saturationTime);
    double green = analogRead(photoResistor);
    Serial.print("Green: ");
    Serial.println(green*gAdj);
    digitalWrite(g, LOW);
    delay(colldownTime);
    
    digitalWrite(r, HIGH);
    delay(saturationTime);
    double red = analogRead(photoResistor);
    Serial.print("Red: ");
    Serial.println(red*rAdj);
    digitalWrite(r, LOW);
    delay(colldownTime);
    
    digitalWrite(b, HIGH);
    delay(saturationTime);
    double blue = analogRead(photoResistor);
    Serial.print("Blue: ");
    Serial.println(blue*bAdj);
    digitalWrite(b, LOW);
    delay(colldownTime);
    
    digitalWrite(y, HIGH);
    delay(saturationTime);
    double yellow = analogRead(photoResistor);
    Serial.print("Yellow: ");
    Serial.println(yellow*yAdj);
    digitalWrite(y, LOW);
    delay(colldownTime);
    
    double rawData[] = {(green*gAdj), (red*rAdj), (blue*bAdj), (yellow*yAdj)};
    double maximum = ambient*ambientAdj;
    int decision;
    
    for (int i=0; i<4; i++)  
    {
       if (maximum<rawData[i])
      {
          maximum = rawData[i];
          decision = i+1;
      }
    }
         
    Serial.println("");
    
    if(decision == 0)
    {
       Serial.println("No object detected.");
       allOn();
       delay(1000);
       allOff();
    }
    else if(decision == 1)
    {
       Serial.println("I think its green.");
       pulse(g);
    }
    else if(decision == 2)
    {
       Serial.println("Looks red to me.");
       pulse(r);
    }
    else if(decision == 3)
    {
       Serial.println("Blue for sure!");
       pulse(b);
    }
    else if(decision == 4)
    {
       Serial.println("Booring old yellow.");
       pulse(y);
    }
    Serial.println("");

}


/* All my work is distributed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License or any subsiquent version of that license. Details here "http://creativecommons.org/licenses/by-nc-sa/3.0/". You don't need to give me any credit but any derivative works must remain free and open source to the community. All code, diagrams and details are provided on an "as is" basis with no expressed or implied waranties for suitability to any purpose - don't blame me if something breaks. */

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

I was asking because I think it would be cool to use it in robots while moving to analyze the floor, but with that speed it would be a bit difficult. 

Thank you for answering and even showing that in a new video :D

@ XicoMBD: I thought you already did this with a webcam and Processing?

That's true! 

But I don't like to be always dependent on a computer ;)

It is possible but you need a TSL230 or similar. Here is a guy that did just that: http://www.youtube.com/watch?v=SgAooELer_Y

Very nicely done project.  The running commentary  complements the project well.

Thanks first video upload to youtube and lmr :P