Loading...
Pages: [1]   Go Down
Author Topic: New library for TCS230 RGB Color Sensor  (Read 862 times)
0 Members and 1 Guest are viewing this topic.
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 TCS230 is a color light-to-frequency converter on single CMOS integrated circuit. The output is a square wave(50% duty cycle) with frequency directly proportional to light intensity (irradiance). The full-scale output frequency can be scaled by one of three preset values via two control input pins. Output enable (OE) places the output in the high-impedance state for multiple-unit sharing of a icrocontroller input.

I recently acquired one of these sensors and was surprised at not being able to find a good library, and explanation for how to use the sensor, so I wrote one. The library is available at http://code.google.com/p/arduino-code-repository/ (the link in my signature below). This library has a dependency on the FreqCount library for frequency counting (included in the download).

Library example code includes:
* Simple blcking read from the sensor
* Simple RGB non-blocking read
* Example incorporating sensor calibration
* Color learning and matching   

As usual an questions, comments and suggestions for improvement are welcome.
Logged


Netherlands
Offline Offline
Tesla Member
***
Karma: 90
Posts: 9401
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Thanks for sharing! you're good in libs! Well done,

Some small remarks to think over

Code:
typedef struct
{
uint32_t value[RGB_SIZE]; // Raw data from the sensor
} color32;

typedef struct
{
uint8_t value[RGB_SIZE]; // the evaluated colour data (RGB value 0-255 or other)
} color8;

Code:
void setEnable(bool t); // enable the device (using OE or frequency)
=>
void enable();
void disable();

Choose better names for some variables,
keeps the code more readable / maintainable
and you can remove comments as code becomes self documenting

e.g.
Code:
uint8_t _OutputEnable;
uint8_t _FreqScaler0, _FreqScaler1;
color32 _DarkCalibration;
color32 _WhiteBalance;
color32 _currentRaw;
color8 _currectRGB;
   also for the function prototypes
   
   MD_TCS230(... uint8_t freqScaler0, uint8_t freqScaler1, uint8_t outputEnable);

   
Have a look at error handling and return values. It is only slightly more code and adds real value
   
Code:
bool MD_TCS230::setFilter(uint8_t f)
// set the sensor color filter
{
if ((_S2 == NO_PIN) || (_S3 == NO_PIN))
return false;

DUMPS("\nsetFilter ");
switch (f)
{
case TCS230_RGB_R: DUMPS("R"); digitalWrite(_S2, LOW); digitalWrite(_S3, LOW); break;
case TCS230_RGB_G: DUMPS("G"); digitalWrite(_S2, HIGH); digitalWrite(_S3, HIGH); break;
case TCS230_RGB_B: DUMPS("B"); digitalWrite(_S2, LOW); digitalWrite(_S3, HIGH); break;
case TCS230_RGB_X: DUMPS("X"); digitalWrite(_S2, HIGH); digitalWrite(_S3, LOW); break;
default: DUMPS("setFilter error"); Serial.println(f, DEC); return false; break;   
}
return true;
}

or

Code:
bool MD_TCS230::setSampling(uint8_t t)
// set sampling rate divisor for frequency counter
{
if (t > 0)
{
   _readDiv =  t;
   return true;
   }
return false;
}

or

Code:
bool MD_TCS230::setDarkCal(sensorData *d)
// set dark calibration data for rgb calculations
{
if (d == NULL)
return false;

DUMPS("\nsetDarkCal");
for (uint8_t i=0; i<RGB_SIZE; i++)
{
DUMP(" ", d->value[i]);
_Fd.value[i] = d->value[i];
}
return true;
}

BTW I like your consequent debugging style!
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

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

Hey Rob! Nice to hear from you again smiley

Quote
Have a look at error handling and return values. It is only slightly more code and adds real value
Good point. I'll check what makes sense for the lib.

Of interest to me- did you notice that there was a pdf file that expained the theory of how to convert a reading from the sensor to a valid RGB value? Same folder as the libraries. Most of the nomenclature for the library comes from there for consistency with the algebra behind the code. Also a lot of the variable names are directly related to the pins of the sensor and what is printed on the breakout boards, which I thought would make it easier for users to relate the library to the hardware.

This next one is interesting and one I have thought about for some time and I would welcome yours and others thoughts:
Quote
void    setEnable(bool t);       // enable the device (using OE or frequency)
=>
void enable();
void disable();

I have used objects that split out methods for every little property (like the trivial enable/disable here) and I have found that I then have to handle calling different functions in my code somehow, like
Code:
if (condition)
  object.enable()
else
  object.disable()
when in fact I could have used
Code:
object.enablefunction(condition);
which I think is shorter, clearer and more 'data driven' rather than code intensive.

Similary for libraries where there are many options to set, I would tend to think in terms of object.setoption(option, value) rather than a slew of .option1(), .option2(), etc. Is there any specific advantage to splitting out the functions that I don't understand? Clearly my style can be easily converted to be more wordy by implementing wrapper functions.
Logged


Netherlands
Offline Offline
Tesla Member
***
Karma: 90
Posts: 9401
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OK,
you have good args for your choices made. Keeping in sync with the datasheet is - at least for private parts - a good idea. For the public part you are on another abstraction level so more readable makes sense there. A library can hide the internals of the datasheet


Code:
if (condition)
  object.enable();
else
  object.disable();
-->
object.enablefunction(condition);

This makes perfect sense if the condition evaluates to true, but less (imho) when you want to disable() when the condition is true

Code:
if (condition)
  object.disable();
else
  object.enable();
-->
object.enablefunction(condition == false);    // looks a bit strange
object.enablefunction(!condition);               // risk of missing the !

most conditions are easy to rewrite to their negate version, so I think your args make more sense.



I often have code like this
Code:
if (condition)
{
  object.enable();
  ... other code
}

....  lines of other code

if (condition2)
{
  object.disable();
  ... other code
}
-->
object.enablefunction(condition);
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

Belgium
Offline Offline
Full Member
***
Karma: 0
Posts: 220
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, I've tried your library but it does not seem to work with the board that I have. This is myTCS230 board (bought it on Ebay) http://www.bajdi.com/?attachment_id=940
I've connected OE to pin 8, S2 to pin 12, S3 to pin 13 and connected 5V and GND. I then tried the example calibrate sketch but I only get [0,0,0] values. The other sketches also don't work for me. The blocking sketch only gives 0 all the time, the non blocking sketch give [255,255,255] not matter what I hold in front of the sensor.
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

Did you connect OUT to pin 5? The Freqcount library counts frequency on that pin.

You also need to decide how to set s0 and s1. I would suggest you set them for 100% output (both 5v from memory)

Edit: your sensor looks like mine. It needs to be modified as explained in the PDF file that is in the library folder with the .cpp file if you want to use the OE line for control.
« Last Edit: February 25, 2013, 08:21:04 pm by marco_c » Logged


Belgium
Offline Offline
Full Member
***
Karma: 0
Posts: 220
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Oops I hadn't seen the pdf file  smiley-red I've just read it and cut the trace on my board. It was connected to ground just like yours. I've just uploaded the calibrate sketch and it works. Thanks for making the library and writing the pdf file. Not many libraries are that well documented  smiley
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

No problems. I hope you have fun with the sensor. It actually works quite well if the calibration is right.
Logged


Pages: [1]   Go Up
Print
 
Jump to: