Loading...
Pages: [1]   Go Down
Author Topic: Help With TCS3200 Color Sensor (Understanding Output)  (Read 459 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello, I am using a version of the code posted below to read colors then ultimately match them. However, I am not sure what the output (white, red, green, blue) are. I would expect that the RGB values be between 0 and 255, or [0,1] but that is not the case. I have reviewed alot of information on the Parallax and TAOS site.  I am sure I’m missing something quite elementary but I can’t seem to put it all together. What is the correct way to interpet the output from this sensor? How should they be normalized? Any help would be great

Code:
/*

Eecher's TCS3200 program
adapted from code found at reibot.org

*/

int S0 = 8;//pinB
int S1 = 9;//pinA
int S2 = 12;//pinE
int S3 = 11;//pinF
int taosOutPin = 10;//pinC
int LED = 13;//pinD

void setup() {
TCS3200setup();
Serial.begin(115200);
Serial.print("\n\n\nready\n\n\n");
delay(100);
}

// primary loop takes color readings from all four channels and displays the raw values once per second.  What you might wish to do with those values is up to you...
void loop() {

detectColor(taosOutPin);
Serial.print("\n\n\n");
delay(1000);

}

int detectColor(int taosOutPin){

float white = colorRead(taosOutPin,0,1);
float red = colorRead(taosOutPin,1,1);
float blue = colorRead(taosOutPin,2,1);
float green = colorRead(taosOutPin,3,1);

Serial.print("white ");
Serial.println(white);

Serial.print("red ");
Serial.println(red);

Serial.print("blue ");
Serial.println(blue);

Serial.print("green ");
Serial.println(green);

}

/*
This section will return the pulseIn reading of the selected color. 
It will turn on the sensor at the start taosMode(1), and it will power off the sensor at the end taosMode(0)
color codes: 0=white, 1=red, 2=blue, 3=green
if LEDstate is 0, LED will be off. 1 and the LED will be on.
taosOutPin is the ouput pin of the TCS3200.
*/

float colorRead(int taosOutPin, int color, boolean LEDstate){
 
//turn on sensor and use highest frequency/sensitivity setting
taosMode(1);

//setting for a delay to let the sensor sit for a moment before taking a reading.
int sensorDelay = 100;

//set the S2 and S3 pins to select the color to be sensed
if(color == 0){//white
digitalWrite(S3, LOW); //S3
digitalWrite(S2, HIGH); //S2
// Serial.print(" w");
}

else if(color == 1){//red
digitalWrite(S3, LOW); //S3
digitalWrite(S2, LOW); //S2
// Serial.print(" r");
}

else if(color == 2){//blue
digitalWrite(S3, HIGH); //S3
digitalWrite(S2, LOW); //S2
// Serial.print(" b");
}

else if(color == 3){//green
digitalWrite(S3, HIGH); //S3
digitalWrite(S2, HIGH); //S2
// Serial.print(" g");
}

// create a var where the pulse reading from sensor will go
float readPulse;

//  turn LEDs on or off, as directed by the LEDstate var
if(LEDstate == 0){
    digitalWrite(LED, LOW);
}
if(LEDstate == 1){
    digitalWrite(LED, HIGH);
}

// wait a bit for LEDs to actually turn on, as directed by sensorDelay var
delay(sensorDelay);

// now take a measurement from the sensor, timing a low pulse on the sensor's "out" pin
readPulse = pulseIn(taosOutPin, LOW, 80000);

//if the pulseIn times out, it returns 0 and that throws off numbers. just cap it at 80k if it happens
if(readPulse < .1){
readPulse = 80000;
}

//turn off color sensor and LEDs to save power
taosMode(0);

// return the pulse value back to whatever called for it...
return readPulse;

}

// Operation modes area, controlled by hi/lo settings on S0 and S1 pins.
//setting mode to zero will put taos into low power mode. taosMode(0);

void taosMode(int mode){
   
    if(mode == 0){
    //power OFF mode-  LED off and both channels "low"
    digitalWrite(LED, LOW);
    digitalWrite(S0, LOW); //S0
    digitalWrite(S1, LOW); //S1
    //  Serial.println("mOFFm");
   
    }else if(mode == 1){
    //this will put in 1:1, highest sensitivity
    digitalWrite(S0, HIGH); //S0
    digitalWrite(S1, HIGH); //S1
    // Serial.println("m1:1m");
   
    }else if(mode == 2){
    //this will put in 1:5
    digitalWrite(S0, HIGH); //S0
    digitalWrite(S1, LOW); //S1
    //Serial.println("m1:5m");
   
    }else if(mode == 3){
    //this will put in 1:50
    digitalWrite(S0, LOW); //S0
    digitalWrite(S1, HIGH); //S1
    //Serial.println("m1:50m");
    }
   
    return;

}

void TCS3200setup(){

    //initialize pins
    pinMode(LED,OUTPUT); //LED pinD
   
    //color mode selection
    pinMode(S2,OUTPUT); //S2 pinE
    pinMode(S3,OUTPUT); //s3 pinF
   
    //color response pin (only actual input from taos)
    pinMode(taosOutPin, INPUT); //taosOutPin pinC
   
    //communication freq (sensitivity) selection
    pinMode(S0,OUTPUT); //S0 pinB
    pinMode(S1,OUTPUT); //S1 pinA
   
    return;

}

Logged

Milton Keynes UK
Offline Offline
Tesla Member
***
Karma: 88
Posts: 6287
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What you get back from pulseIn() is an unsigned long indicating the length of the pulse in microseconds. You'd need to read the spec of the device which was providing the pulse to understand what that means. Your code returns it as a float, which is pointless (it is not a float, contains no fractional part, and by converting to a float you reduce the resolution of the value). Anyway, it's unlikely to be a value in the range 0 .. 255 as you seem to have expected.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

thanks for the reply, I will change the variable type. Here is the documentation that I cannot understand.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've been trying to get a TCS3200 sensor working with an arduino due too.  I think your code might be missing a timer - I found this sensor
http://www.robotshop.com/dfrobot-color-sensor-tcs3200.html
The way I understand it is that the output of the light sensor is a digital frequency that varies with the intensity of the light so you need the timer to measure the frequency.
This post might help also:
http://arduino.cc/forum/index.php?topic=130423.0
If I make any progress I will post it here just be sure to post your code once you have it working.
« Last Edit: May 03, 2013, 07:56:27 pm by varela5280 » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Although timers/interrupts are cool they are in no way needed to read the frequency of the light sensor all that is needed is the digitalRead [make sure to set the pinMode to output].  I'm now finding that its great to know that there are 5768 highs in a 10 ms time frame but I still need to figure out some sort of meaningful output... the quest continues.  Here is the code to at least read the input:

Code:
#define OUT  10
#define S2   8
#define S3   9
#define S0   6
#define S1   7
#define OE   23
#define LED  22

#define  Filters_R  0
#define  Filters_G  1
#define  Filters_B  2

int Count[3] = {0};
long count = 0;
int counter = 0;
long start_time = 0;
int G_flag = 1;
int RGB = 0;
long freq = 0;

void setup()
{
  pinMode(OUT, INPUT);
  pinMode(S2, OUTPUT);
  pinMode(S3, OUTPUT);
  pinMode(S0, OUTPUT);
  pinMode(S1, OUTPUT);
  pinMode(OE, OUTPUT);
 
  digitalWrite(S2, HIGH);
  digitalWrite(S3, LOW);
  digitalWrite(S0, HIGH);    // 100% of Output Frequence
  digitalWrite(S1, HIGH);
  digitalWrite(OE, LOW);

  Serial.begin(9600);
  Serial.println("Starting...");
}

void loop()
{
  Serial.println("loop");
  for(int i=0; i<3; i++)
  {
    RGB=i;
    Select_Filters(i);
    start_time = millis();
    count=0;
    for(int i=start_time; i<start_time+10000; i++)
    {
      if(digitalRead(10) == HIGH)
      {
        count++;
      }
      counter++;
    }
    freq = count / 7200;
    Serial.print("value: ");
    Serial.println(count % 255);
    Serial.print("count: ");
    Serial.println(count);
    Serial.print("counter ");
    Serial.println(counter);
    counter=0;
    count=0;
    freq=0;
  }
  delay(3000);
}

void Select_Filters(int RGB)
{
  switch(RGB)
  {
    case Filters_R:          //Red
    digitalWrite(S2, LOW);   
    digitalWrite(S3, LOW);
    Serial.println("-----select Red color");
    break;
   
    case Filters_G:          //Green
    digitalWrite(S2, HIGH);   
    digitalWrite(S3, HIGH);
    Serial.println("-----select Green color");
    break;
   
    case Filters_B:          //Blue
    digitalWrite(S2, LOW);   
    digitalWrite(S3, HIGH);
    Serial.println("-----select Blue color");
    break;
   
    default:                  //Clear(no filter)
    digitalWrite(S2, HIGH);   
    digitalWrite(S3, LOW);
    Serial.println("-----no filter");
    break;
  }
}

void callback()
{
  count++;
}
Logged

Sydney
Offline Offline
God Member
*****
Karma: 14
Posts: 717
Big things come in large packages
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The output of the sensor is a frequency that is linearly proportional to the colour intensity. What you need to do is measure that frequency for R, G and B and then interpret what colour you have.

I wrote a library for this sensor and have a pdf as part of the distribution that explains how the sensor can be calibrated. It also has a few examples sketches, one of which is for calibration. If you are interested follow the link in my signature below.
« Last Edit: May 06, 2013, 07:56:36 am by marco_c » Logged


Pages: [1]   Go Up
Print
 
Jump to: