TCS34725 RGB sensor calibration

Hi, I am currently interfacing TCS34725 with Arduino Uno. I am getting RGB values in the range 0-65565. Want to scale it down to 0-255 and return those values to control solenoid valves.
Here is the code for the same. Kindly help for the same. Thank you.

#include <Wire.h>
#include “Adafruit_TCS34725.h”

// Pick analog outputs, for the UNO these three work well
// use ~560 ohm resistor between Red & Blue, ~1K for green (its brighter)
#define redpin 3
#define greenpin 5
#define bluepin 6
// for a common anode LED, connect the common pin to +5V
// for common cathode, connect the common to ground

// set to false if using a common cathode LED
#define commonAnode true

// our RGB → eye-recognized gamma color
byte gammatable[256];

Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X);

void setup() {
Serial.begin(9600);
Serial.println(“Color View Test!”);

if (tcs.begin()) {
Serial.println(“Found sensor”);
} else {
Serial.println(“No TCS34725 found … check your connections”);
while (1); // halt!
}

// use these three pins to drive an LED
pinMode(redpin, OUTPUT);
pinMode(greenpin, OUTPUT);
pinMode(bluepin, OUTPUT);

// thanks PhilB for this gamma table!
// it helps convert RGB colors to what humans see
for (int i=0; i<256; i++) {
float x = i;
x /= 255;
x = pow(x, 2.5);
x *= 255;

if (commonAnode) {
gammatable = 255 - x;

  • } else {*
    _ gammatable = x; _
    _
    }
    _
    _ //Serial.println(gammatable*);
    }
    }
    void loop() {_

    uint16_t clear, red, green, blue;
    _ tcs.setInterrupt(false); // turn on LED*
    * delay(60); // takes 50ms to read*_

* tcs.getRawData(&red, &green, &blue, &clear);*
* tcs.setInterrupt(true); // turn off LED*

* Serial.print(“C:\t”); Serial.print(clear);*
* Serial.print("\tR:\t"); Serial.print(red);*
* Serial.print("\tG:\t"); Serial.print(green);*
* Serial.print("\tB:\t"); Serial.print(blue);*
* // Figure out some basic hex code for visualization*
* uint32_t sum = clear;
_ float r, g, b;
r = red; r /= sum;
g = green; g /= sum;
b = blue; b /= sum;
r = 256; g = 256; b = 256;
Serial.print("\t");

Serial.print((int)r, HEX); Serial.print((int)g, HEX); Serial.print((int)b, HEX);

* Serial.println();
//Serial.print((int)r ); Serial.print(" “); Serial.print((int)g);Serial.print(” "); Serial.println((int)b );
analogWrite(redpin, gammatable[(int)r]);
analogWrite(greenpin, gammatable[(int)g]);
analogWrite(bluepin, gammatable[(int)b]);
}*_

Hi,
Welcome to the forum.

Please read the first post in any forum entitled how to use this forum.
http://forum.arduino.cc/index.php/topic,148850.0.html then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.

Thanks.. Tom.. :slight_smile:

Sorry about you not getting a response.

If you are just wanting to take a reading from 0-65535 and convert it to 0-255, simply divide by 256.

However, if you want to actually "normalize" the data, such as if you wanted the color regardless of how bright it is, then there's a little more to it.

The trick here is that if you find your maximum value between Red, Green, and Blue, and then divide all values by this maximum, you get a value from 0 to 1.

R_norm = R / MAX
G_norm = G / MAX
B_norm = B / MAX

So if your values are 1000, 500, 160, then your normalized values will be 1, 0.5, 0.16.

Getting MAX is easy enough:

MAX = R;
if (G > MAX) MAX = G;
if (B > MAX) MAX = B;

So with that being said, it is simply a matter of multiplying it my your desired scale. In this case, 255.

If you are using floating-point math, then the order isn't particular. If you are trying to stick with integer or fixed-point math, then you will want to find your max, THEN multiply the values by 255, THEN divide by the max. This way, you avoid falling into the 0-1 range.

Here's my code for this in my hue light color-matching project.Keep in mind I'm using floating-point:

MAX = getR();
	if (getG() > MAX) MAX = getG();
	if (getB() > MAX) MAX = getB();
	
	if (MAX)
	{
		r_norm = getR() / MAX;
		r_norm *= NORM_SCALE;
		g_norm = getG() / MAX;
		g_norm *= NORM_SCALE;
		b_norm = getB() / MAX;
		b_norm *= NORM_SCALE;
	}
	else
	{
		r_norm = 0;
		g_norm = 0;
		b_norm = 0;
	}

It already sounds like this is more than you need, but if you need actual calibration, I would write up something about that, too.

Simply omit this line

 r *= 256; g *= 256; b *= 256;

to get values below 256.