Color Sensing with TCS3200, Need Help with Code & Understanding

A good diffusor is a white pingpong ball. Cut a hole for the RGB LED to be stuck through.

Johan_Ha:
Just take care that you change each negative value to 0 before outputting it. A negative value just becomes another positive value. val + 256 or something similar. Better set it to zero.

How do you think I'd go about doing that?

I'm thinking maybe an if and if else statement would work, but I'm not sure what variable/argument to put in it.

Something like:

if(frequency < 0){
frequency = 0;
}

Or maybe use the "constrain" command? Although I'm not sure how it works. It's what I just see online.

Not the frequency! The frequency doesn't get negative, does it? Have a look at this:

bcolor = map(frequency, 25,70,255,0);

If frequency is below 25, bcolor goes over 255. If frequency goes over 70, bcolor becomes negative. Don't mind what frequency is. Check only bcolor and set it to 0 or 255 if it went over the boundaries.

Johan_Ha:
Not the frequency! The frequency doesn't get negative, does it? Have a look at this:

bcolor = map(frequency, 25,70,255,0);

If frequency is below 25, bcolor goes over 255. If frequency goes over 70, bcolor becomes negative. Don't mind what frequency is. Check only bcolor and set it to 0 or 255 if it went over the boundaries.

Ah, so I don't need an If statement? Just need to adjust the numbers in the "map", and calibrate it to my setup?

I see that map() uses the syntax of: map(value, fromLow, fromHigh, toLow, toHigh)

I'm not sure how to change this. I tried changing it to (frequency, 25,70,0,255) for fun. The comments in the code say the RGB range (" //Remaping the value of the frequency to the RGB Model of 0 to 255") is 0 to 255. So I reckon the results in terminal should be within the bounds of 0 to 255 then too.

I'm worried that it's not working 100% correct, as I see numbers below 0.

For example when scanning a yellow paper, the LED does show up yellow.

But the terminal shows:

R= 158 G= 60 B= -153

This is right, as Yellow is a mix of Red and Green, however, blue is set to a negative number. Do you think that's OK? Or should the code be altered to make blue (or any other negative value) be set to 0?

Is it possible that negative values may be being sent to the LED, and have an harmful effect on the output?

I have no idea of what the frequencies mean. But B= -153 is just plain wrong. The analogWrite() writes values from 0 to 255. That's one unsigned byte. Whatever you put there will be treated as an unsigned byte. -153 is a signed number that needs more than 8 bits. Passing it to the analogWrite() will just pass 8 bits. The value passed is 01100111 or 103. Doing writeAnalog(-153) will equal analogWrite(103).

If frequency 25 means full blue colour and frequency 70 means zero blue colour, then your original mapping function is correct. But do as I told you to. If the map function returns values outside the 0 - 255 range, you must adjust the value to 0 or 255. Why it goes beyond the range is beyond me. Instead of adjusting to the range, perhaps you could re-read the sensor until you get sane values.

Johan_Ha:
I have no idea of what the frequencies mean. But B= -153 is just plain wrong. The analogWrite() writes values from 0 to 255. That's one unsigned byte. Whatever you put there will be treated as an unsigned byte. -153 is a signed number that needs more than 8 bits. Passing it to the analogWrite() will just pass 8 bits. The value passed is 01100111 or 103. Doing writeAnalog(-153) will equal analogWrite(103).

If frequency 25 means full blue colour and frequency 70 means zero blue colour, then your original mapping function is correct. But do as I told you to. If the map function returns values outside the 0 - 255 range, you must adjust the value to 0 or 255. Why it goes beyond the range is beyond me. Instead of adjusting to the range, perhaps you could re-read the sensor until you get sane values.

Thank you, I'll try these out, and will let you know what happens.

I've been wondering something else too, but I can't find much info online.

I want the LED to turn off, if the sensor isn't detecting any color. (For example, if I take the sensor off of the colored paper, it will push a bunch of negative values that are like -1800 and such. During this, the LED is a yellowish green color.)

Instead of the LED being ON in this situation, I'd like it to be turned off. So that it only turns on when there's "sane values" detected by the sensor (such as when it's placed against a colored piece of paper).

Do you know how I could do this?

What is pushing negative values? The sensor? The sensor produces a square wave, the frequency of which tells the colour. Or the colour intensity? This I know nothing of.

Just check what values you get when nothing is in front of the sensor. Define the condition according to those values. Fix your code so that when that condition occurs, zero is outputted to the leds.

Thank you so much! I'll try that out.

Hi All

Interesting topic & conversation:

Here is my current take on things ... code still has issues

/***************************************************     
Observe and report an object's visible color spectrum via a TCS3200 light-to-frequency converter
       
 Materials Schedule

  Arduino Uno - 1 each
   https://store.arduino.cc/usa/arduino-uno-rev3
  DF Robot Gravity I/O Shield - 1 each 
   https://www.dfrobot.com/product-1009.html
  DF Robot Color Sensor - 1 each
   https://www.dfrobot.com/product-540.html 
  A-B Cable - 1 each
   https://www.staples.com/usb+ab+cable/directory_usb+ab+cable 
  Wire Bundles - 7 female/female wires 
   https://www.adafruit.com/product/266   

 Assembly

   1.Connect A-B cable to arduino and laptop and upload sketch    
   2.Connect aurduino and shield
   3.Connect color sensor to I/O shield digital pins 4, 5, 6, 7, 8 and VCC and GND with (7) female/female wires
      
      (D)  Digital  D4    Green   S0
      (D)  Digital  D5    Black   S1
      (D)  Digital  D6    Red     S2
      (D)  Digital  D7    White   S3
      (D)  Digital  D8    Yellow  OUT       
      (+)  Voltage  VCC   Red     VCC
      (-)  Ground   GND   Black   GND
      
   4.Open serial monitor to view sensor readings at 9600 baud   

 Sensor assumptions (Texas Advanced Optoelectronic Solutions TCS3200)  
    
    Max output frequency = 600 kHz (1 kHz = 0.001 MHz, 600 kHz = 0.6 MHz)
    Max data acquisition rate = 1 datapoint/microsecond (1,000 microseconds = 1 millisecond)

    8 bit Timer on Atmel AVR - FreqCount Library, for measuring frequencies - Paul Stoffregen <paul@pjrc.com>

        *        1ms       2ms       4ms       8ms
      2 MHz     8x250     32x125    64x125    128x125              
      1 MHz     8x125     8x250     32x125    64x125

    Sensor power settings
      
      Clear:   S2 High  S3 Low        
      Red:     S2 Low   S3 Low         
      Blue:    S2 Low   S3 High        
      Green:   S2 High  S3 High   

    RGB Model - How to Mechatronics

      Clear:  Red   ?  Green   ?  Blue   ?  Clear ?
      Red:    Red  25  Green  72  Blue 255  Clear 0  Hex 1946FF https://convertingcolors.com/rgb-color-25_70_255.html#about
      Green:  Red  30  Green  90  Blue 255  Clear 0  Hex 1E5AFF https://convertingcolors.com/rgb-color-30_90_255.html#about
      Blue:   Red  25  Green  70  Blue 255  Clear 0  Hex 1946FF https://convertingcolors.com/rgb-color-25_70_255.html#about 

    RGB Model - DF Robot

      Clear:  Red 118  Green 106  Blue 111  Clear 0  Hex 766A6F  https://convertingcolors.com/rgb-color-118_106_111.html#about
      Red:    Red  92  Green  33  Blue  35  Clear 0  Hex 5C2123  https://convertingcolors.com/rgb-color-92_33_35.html#about
      Green:  Red 112  Green  78  Blue  57  Clear 0  Hex 704E70  https://convertingcolors.com/rgb-color-112_78_112.html
      Blue:   Red  38  Green  33  Blue  45  Clear 0  Hex 26212D  https://convertingcolors.com/rgb-color-38_33_45.html#about                 

    RGB Model - surfnm

      Clear:  Red 255  Green 255  Blue 255  Clear 0  Hex FFFFFF  https://convertingcolors.com/rgb-color-255_255_255.html
      Red:    Red 255  Green   0  Blue   0  Clear 0  Hex FF0000  https://convertingcolors.com/rgb-color-255_0_0.html
      Green:  Red   0  Green 255  Blue   0  Clear 0  Hex 00FF00  https://convertingcolors.com/rgb-color-0_255_0.html
      Blue:   Red   0  Green   0  Blue 255  Clear 0  Hex 0000FF  https://convertingcolors.com/rgb-color-0_0_255.html      

 Engineering
   
    Created by Dejan Nedelkovski
     https://howtomechatronics.com/tutorials/arduino/arduino-color-sensing-tutorial-tcs230-tcs3200-color-sensor/
    Created by DF Robot
     https://www.dfrobot.com/wiki/index.php/TCS3200_Color_Sensor_(SKU:SEN0101)     
    Team Arduino Forum
     Color Sensing with TCS3200, Need Help with Code & Understanding
     https://forum.arduino.cc/index.php?topic=549632.0
     Problem with Arduino Uno Color sensor TC3200
     https://forum.arduino.cc/index.php?topic=469940.0
    Modified by surfnm
    
 *************************************************/

//=== Global constants and variables ======

// TCS3200 light-to-frequency converter wiring 
#define S0 4
#define S1 5
#define S2 6
#define S3 7
#define sensorOut 8

int frequency = 0;  // int (16 bit = 2 byte value = range of -32,768 to 32,767)

// === Setup code, runs once =========================

void setup() {
  
  pinMode(S0, OUTPUT);
  pinMode(S1, OUTPUT);
  pinMode(S2, OUTPUT);
  pinMode(S3, OUTPUT);
  pinMode(sensorOut, INPUT);
  
  // Setting frequency-scaling to 20%
  digitalWrite(S0,HIGH);
  digitalWrite(S1,LOW);
  
  Serial.begin(9600);  // use the serial port to print out the resultant data
}

// === Main code, runs/loops repeatedly ==============

void loop() {
  
  // Setting Red filtered photodiodes to be read
  digitalWrite(S2,LOW);
  digitalWrite(S3,LOW);
  // Reading the output frequency
  frequency = pulseIn(sensorOut, LOW);
  // Remap the value of the Frequency to the RGB Model 
  // Syntax - map(value, fromLow, fromHigh, toLow, toHigh)
  // Frequency Model fromLow = 0, Frequency Model fromHigh = 600
  // RGB Model toLow = 0, RGB Model toHigh = 255
  frequency = map(frequency, 0,600,0,255);
  // Printing the value on the serial monitor
  Serial.print("R= ");//printing name
  Serial.print(frequency);//printing RED color frequency
  Serial.print("  ");
  delay(100);

  // Setting Green filtered photodiodes to be read
  digitalWrite(S2,HIGH);
  digitalWrite(S3,HIGH);
  // Reading the output frequency
  frequency = pulseIn(sensorOut, LOW);
  // Remap the value of the Frequency to the RGB Model 
  // Syntax - map(value, fromLow, fromHigh, toLow, toHigh)
  // Frequency Model fromLow = 0, Frequency Model fromHigh = 600
  // RGB Model toLow = 0, RGB Model toHigh = 255
  frequency = map(frequency, 0,600,0,255);  
  // Printing the value on the serial monitor
  Serial.print("G= ");//printing name
  Serial.print(frequency);//printing GREEN color frequency
  Serial.print("  ");
  delay(100);

  // Setting Blue filtered photodiodes to be read
  digitalWrite(S2,LOW);
  digitalWrite(S3,HIGH);
  // Reading the output frequency
  frequency = pulseIn(sensorOut, LOW);
  // Remap the value of the Frequency to the RGB Model 
  // Syntax - map(value, fromLow, fromHigh, toLow, toHigh)
  // Frequency Model fromLow = 0, Frequency Model fromHigh = 600
  // RGB Model toLow = 0, RGB Model toHigh = 255
  frequency = map(frequency, 0,600,0,255);  
  // Printing the value on the serial monitor
  Serial.print("B= ");//printing name
  Serial.print(frequency);//printing BLUE color frequency
  Serial.println("  ");
  delay(100);
}