Shop OBEX P1 Docs P2 Docs Learn Events
Help With TCS3200 (Understanding Output) — Parallax Forums

Help With TCS3200 (Understanding Output)

aeroutaaerouta Posts: 7
edited 2014-02-19 14:07 in Accessories
Hello, I am using a version of the code posted in the forum 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, but that is not the case. I have reviewed alot of information on the Parallax and TAOS site. My guess it has something to do with the Spectral Response charts included in the sensor documentation however the y-axis (Relative Response) is never clearly defined, this renders their meaning elusive. I am sure I’m missing something quite elementary but I can’t seem to put it all together. Any help would be great.
/*
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;
}

Comments

  • aeroutaaerouta Posts: 7
    edited 2013-01-08 12:16
    I found this information online. The first step shows a normalization of RGB. Does this correspond to the RGB values obtained from the TCS3200-DB? And is this the correct way to normalize the RGB values between [0,1]
  • aeroutaaerouta Posts: 7
    edited 2013-01-09 18:17
    I am now using a code that using an interrupt so that the pulse count are over a fixed time period. I believe this is more useful then the above code. However I still need help interpreting these values. I would like to convert them over the RGB, HSI etc. Any response, help, comment, code advance would be awesome!
    byte s0=8,s1=9,s2=12,s3=11, LED = 13;int out=2;
    int flag=0;
    byte counter=0;
    byte countR=0,countG=0,countB=0;
    void setup()
     {
     Serial.begin(115200);
     pinMode(s0,OUTPUT);
     pinMode(s1,OUTPUT); 
     pinMode(s2,OUTPUT);
     pinMode(s3,OUTPUT);
     pinMode(LED,OUTPUT);
     }
     
    void TCS()
     {
     flag=0;  
     digitalWrite(s1,HIGH);
     digitalWrite(s0,HIGH);
     digitalWrite(s2,LOW);
     digitalWrite(s3,LOW);
     digitalWrite(LED,HIGH);
     attachInterrupt(0, ISR_INTO, LOW);
     timer0_init();
     
     }
    void ISR_INTO()
     {
     counter++;
     }
     void timer0_init(void)
     {
      TCCR2A=0x00;
      TCCR2B=0x07;   //the clock frequency source 1024 points
      TCNT2= 100;    //10 ms overflow again
      TIMSK2 = 0x01; //allow interrupt
     }
     int i=0;
     ISR(TIMER2_OVF_vect)//the timer 2, 10ms interrupt overflow again. Internal overflow interrupt executive function
    {
        TCNT2=100;
        flag++;
     if(flag==1)
      {
        countR=counter;
        //Serial.print("red=");Serial.println(countR,DEC);
        digitalWrite(s2,HIGH);
        digitalWrite(s3,HIGH);
      }
      else if(flag==2)
       {
        countG=counter;
        //Serial.print("green="); Serial.println(countG,DEC);
        digitalWrite(s2,LOW);
        digitalWrite(s3,HIGH);
       }
       else if(flag==3)
        {
        countB=counter;
        //Serial.print("blue="); Serial.println(countB,DEC); Serial.println("\n"); 
        digitalWrite(s2,LOW);
        digitalWrite(s3,LOW);
        
        }
        else if(flag==4)
         {
         flag=0;
         //Serial.print("white "); Serial.println("0"); Serial.print("red "); Serial.println(countR,DEC); Serial.print("blue "); Serial.println(countB,DEC); Serial.print("green "); Serial.println(countG,DEC); Serial.print("\n\n\n");
           Serial.print("0");Serial.print(" ");Serial.print(countR,DEC);Serial.print(" ");Serial.print(countG,DEC);Serial.print(" ");Serial.println(countB,DEC);
    
    
         }
           counter=0;
    }
    void loop()
     {
      TCS();
    while(1);
     }
    
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-01-09 18:36
    To make sense of the outptus from the TCS3200, you need to do a white balance, wherein each R, G, and B output is ratioed to the values obtained from a white reference subject. This will give you RGB values that you can use to convert to HSB and other color spaces. White balancing is covered in the TCS3200 docs.

    BTW, you can safely ignore the clear channel from the sensor.

    -Phil
  • aeroutaaerouta Posts: 7
    edited 2013-01-10 05:17
    Thanks for your Reply!!!

    I looked through the PDF provided on the parallax site for information on white balancing, I was not able to find it. But you response was intiutive enough.

    Do you recommend using the first or second approach for reading the sensor output. The first code; a pure white subject approaches an RGB reading of [0 0 0] and a black subject [INF INF INF]. While the second approach seems to do the inverse.

    Also, I am taking a reading of a transparent colored fuild in a circular test tube. Do you recommend using a square tube instead to avoid the glare? Or I could not use the sensor mounted LEDs and reposition some to the sides? I think this may help ensure that I am not reading the specular reflection. I would like to match the tube reading to a color card.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-01-10 08:09
    Since the liquid is transparent, I would use a diffuse white backlight behind a square test tube for your illumination. Take a white reading using water or some other clear liquid. Then ratio each RGB coordinate of subsequent tests against those of the white reading, and multiply by the refence constant (usually 255 for 8-bit data), viz:
    Rbalanced = Rraw * 255 / Rwhite
    Gbalanced = Graw * 255 / Gwhite
    Bbalanced = Braw * 255 / Bwhite

    If you're using a BASIC Stamp, be sure to take the necessary steps to account for 16-bit overflow.

    -Phil
  • aeroutaaerouta Posts: 7
    edited 2013-01-14 06:01
    Thanks Phil, I have been working on the setup, I'll up load a picture soon!
  • aeroutaaerouta Posts: 7
    edited 2014-02-19 11:53
    Hello Phil, I have a quick question regarding the back lighting with this sensor. Do you recommend a certain type of LED? Ideally, I would like to use an LED that will show the entire visible spectrum uniformly.(fat chance) I know this may be impossible with a single LED but I am hoping you have a few suggestions that will get me close. If I do need to use several LED how would I do so? I am trying to avoid the dip at 480-500nm that most LEDs have. I am concerned that the sensor will have less precision in detecting variations at this frequency.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2014-02-19 13:08
    A white LED will probably do what you want. They contain a single blue emitter and a broad-spectrum phosphor that's excited by the blue light. The spectrum will show a sharp blue peak embedded in a more uniform curve covering blue through red. Most LED datasheets will show the output specturm. Just pick one that meets your requirements.

    -Phil
  • aeroutaaerouta Posts: 7
    edited 2014-02-19 14:07
    Thanks for the response.

    I have reviewed several white LED output spectrums. Most of them seem to have a dip in the 480-500nm range. Why is this? Does this not mean that I will loss sensitivity in that range because there will be very minimal light being reflected with that wavelength? I was comparing the two spectral response graphs for the TCS3200DB. The spectral response dips significantly at ~490 with the white LED Illumination.
Sign In or Register to comment.