Inconsistant color sensor

I will start with I am new to Arduino. I have had inconsistent results for weeks trying to sense color. I have tried the TCS3200 (three units) with all different gains set and the LED on and off. Using the tcs34725 (three different units, one of which was a CQRobot version (confirming that my soldering job installing the header pins was not the culprit. I tried two different Libraries for the 34725 version, the adafruit and the native 34725. LED turned on and off. I have changed the lighting in the room for all. And I started with a Mega 2650 and moved to an Uno R3.

Every time I run the program it seems the values are very different. I even used the map function to try to keep the values in the 0 - 255 range.

I captured the highest and lowest color value over 100 samples and used them for the map function each time the program starts.

I am at the end of my wits. All I want is to differentiate red, yellow, orange, green, blue. I cannot get any color to be consistent.

********************* TCS3200 Code ***********************

#include <LiquidCrystal.h>

#define s0 6     //Module pins wiring
#define s1 7
#define s2 8
#define s3 9
#define out 10


#define led 7
int red = 0;
int r = 0;
int green = 0;
int g = 0;
int blue = 0;
int b = 0;
int low_r = 1000;
int high_r = 0;
int low_g = 1000;
int high_g = 0;
int low_b = 1000;
int high_b = 0;
int i =0; 

/*  
Initialize the library by associating any needed LCD interface pins
with the arduino pin number it is connected to
*/

const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);


// begin setup

void setup(void) {

   pinMode(s0,OUTPUT);    //pin modes
   pinMode(s1,OUTPUT);
   pinMode(s2,OUTPUT);
   pinMode(s3,OUTPUT);
   pinMode(out,INPUT);
   pinMode(led, OUTPUT);
   
   digitalWrite(led, HIGH);  //turn on/off LED
   Serial.begin(9600);

   digitalWrite(s0,HIGH); //Putting S0/S1 on HIGH/HIGH levels means the output frequency scalling is at 100% (recommended)
   digitalWrite(s1,HIGH); //LOW/LOW is off HIGH/LOW is 20% and LOW/HIGH is  2%



  // initial values.  reset after 100 samples!
  int red = map(r, 64, 379, 255, 0);
  int blue = map(b, 29, 350, 255, 0);
  int green = map(g, 32, 443, 255, 0);
}


void loop(void) {
   digitalWrite(s2,LOW);        //S2/S3 levels define which set of photodiodes we are using LOW/LOW is for RED LOW/HIGH is for Blue and HIGH/HIGH is for green
   digitalWrite(s3,LOW);
   // Serial.print("Red value= "); 
   r = pulseIn(out,LOW);
   delay (50);
   
   digitalWrite(s2,LOW);
   digitalWrite(s3,HIGH);
   //Serial.print("Blue value= ");
   b = pulseIn(out,LOW);
   delay (50);
   
   digitalWrite(s2,HIGH);
   digitalWrite(s3,HIGH);
   // Serial.print("Green value= ");
   g = pulseIn(out,LOW);
   delay (50);
   
  lcd.begin(16, 2);
  // Print a message to the LCD.

// write to first line of lcd
  lcd.setCursor(0, 0);
  
  //RED
  lcd.print("R");  lcd.print(red, DEC);  lcd.print(" "); //lcd.print(r, DEC);
  Serial.print("R:"); Serial.print(r, DEC);  Serial.println(" ");
  Serial.print("mapped R:"); Serial.print(red, DEC);  Serial.print(" ");
  //GREEN
  lcd.print("G");  lcd.print(green, DEC);  lcd.print(" "); //lcd.print(g, DEC);
  Serial.print("G:"); Serial.print(g, DEC);  Serial.println(" ");
  Serial.print("mapped G:"); Serial.print(green, DEC);  Serial.print(" ");
  //BLUE
  lcd.print("B");  lcd.print(blue, DEC); lcd.print(" ");  //lcd.print(b, DEC);
  Serial.print("B: "); Serial.print(b, DEC); Serial.println(" ");
  Serial.print("mapped B:"); Serial.print(blue, DEC);  Serial.print(" ");
  
  Serial.println(" ");  

  Serial.print("HR:"); Serial.print(high_r, DEC);  Serial.print(" ");
  Serial.print("LR:"); Serial.print(low_r, DEC);  Serial.print(" ");
  Serial.print("HG:"); Serial.print(high_g, DEC);  Serial.print(" ");
  Serial.print("LG:"); Serial.print(low_g, DEC);  Serial.print(" ");
  Serial.print("HB:"); Serial.print(high_b, DEC);  Serial.print(" ");
  Serial.print("LB:"); Serial.print(low_b, DEC);  Serial.print(" ");
  Serial.println(" ");
  
  i++; // A counter (variable=i means to add 1 to i every loop)
 
  if (i <= 100) { 
    
    Serial.print(i, DEC); 
    Serial.println(" "); 

    // finds the highest and lowest number for R,G,& B
      if (r > high_r) high_r = r; 
      if (b > high_b) high_b = b; 
      if (g > high_g) high_g = g; 
      if (r < low_r) low_r = r; 
      if (b < low_b) low_b = b;
      if (g < low_g) low_g = g;  
      if (i == 1) { Serial.print("check RED"); }
      if (i == 25) { Serial.print("check geeen"); }
      if (i == 50) { Serial.print("check blue"); }
      //if (i == 75) { Serial.print("check any"); }
      }
      
      if (i == 100)
      Serial.print("  **** Recalibrated ****");
      
      // maps numbers so HIGH and LOW so that it fits in 0-255 range
      red = map(r, low_r, high_r, 255, 0);
      blue = map(b, low_b, high_b, 255, 0);
      green = map(g, low_g, high_g, 255, 0);
      
    if (i > 100 ) {
        // Checks the current detected color and prints
        lcd.setCursor(0, 1);
        lcd.print("detecting color ");
        lcd.setCursor(0, 1);
/**********************************************/
 //decide which color is present
 
        if (red > 250 && green > 250 && blue > 250) {
           lcd.println(" - white detected!");
           lcd.print(" ");
        } else if (red < 25 && green < 25 && blue < 25) {
           lcd.println(" - black detected!");
           lcd.print(" ");
        } else if (red > 200 &&  green > 200 && blue < 100) { 
            lcd.println(" - yellow detected!");
            lcd.print(" ");
        } else if (red > 200 &&  green > 25 && blue < 100) {
           lcd.println(" - orange detected!");
           lcd.print(" ");
        } else if (red > 200 &&  green < 100 && blue > 200) {
           lcd.println(" - purple detected!");
           lcd.print(" ");
        } else if (red > 240 && green < 120 && blue < 75) {
           lcd.println(" - Red detected!");
           lcd.print(" ");
        } else if (red < 190 && green < 150 && blue < 170) {
           lcd.println(" - Blue detected!");
           lcd.print(" ");
        } else if (red < 180 && green < 150 && blue < 70) {
           lcd.println(" - Green detected!");
           lcd.print(" ");
        } else {
           lcd.println(" - Unknown Color!");
           lcd.print(" ");
        }

/**********************************************/

        delay(1000); // 1 second 
    } // end program loop
 
  delay(50);
}

Welcome to the forum, and thanks for posting your code correctly!

Please post some examples of what you mean by "inconsistent". Also post some examples of the raw measurements for a static setup.

Very large variations in output suggest poor connections, bad solder joints, etc. Please post a photo of your setup and a closeup of the connections to the sensor.

Your initial color setup is obviously wrong because the initial r g b values are = 0 and therefore are beyond the map functions range below:

All conditions below are incorrect too, because the color is determined not by the absolute values of the RGB components, but by their ratio.

For example, you have white as R > 250, G > 250 and B > 250. It's wrong concept.
In fact, any color with approximately equal values of all three components will look like white, only of different brightness.

You need to study how the RGB color model works. At the moment, the logic in your program is incorrect and therefore it is impossible to say for sure whether the sensor is working correctly or not

One likely approach would be to convert your RGB data to HSL color scheme, where the HUE (color) is independent of the brightness.

I haven't looked at your code closely, but given b707's comments, I suggest that you start with the simplest possible example, and examine the raw output for tests with several color cards, stable lighting and sensor positioning.

Post that code and some example output, in addition to the information requested earlier.

I found that the examples that come with the TCS34725 library are doing a good job.
Didn't like the TCS3200.
Leo..

Indeed. That one performs very well.

You should probably display 'red' (mapped 'r') AFTER you map it, and not before.

To map RGB to color, a good choice is to map the RGB color space to the HLV (Hue, Lightness, Value) or HSB (Hue, Saturation, Brightness) color space and use the "Hue" value for color.

Just install the Adafruit TCS34725 library from the library manager in the IDE.
The library does all the heavy lifting for you, and installs example code.
Leo..

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.