Go Down

Topic: light into frequency (Read 1 time) previous topic - next topic


does anybody have some ideas how to deal with a TSL230 Light to Frequency Converter from parallax?


Oct 22, 2006, 12:55 pm Last Edit: Oct 22, 2006, 12:57 pm by Florito Reason: 1
No, but reading their description, all you need to do is to measure the time between the last and the current LO to HIGH ramp. This value will be direct proportional to the light intensity.
If you want to control something by light, you can always use (much cheaper) photo-resistors of course (see the Arduino Tutorials).
p.s. i think this kind of stuff should be more on the 'Interfacing' topic.


did you figure out how to interface and measure he TSL230? if so please share!


Dec 22, 2007, 04:51 am Last Edit: Dec 22, 2007, 04:55 am by paulb Reason: 1
I think the output is just a pulse right? It beats a photoresistor all to hell for wide range.

As to the code, do something like this.

long pulseTime;
#define pulsePin  3    // change this to input pin
void setup(){

void loop(){
// first two lines prevent reading an incomplete pulse
pulseTime=0;                                     // clean out variable
while(digitalRead(pulsePin) == 1){};   // find a high pulse
while(digitalRead(pulsePin) == 0){};   // find a low pulse
while(digitalRead(pulsePin) == 1){       // we know we are at the beginning of a clean pulse now

Serial.println(pulseTime);     // debug variable


You better do some math and make sure you're not going to overrun even a long variable. The TSL230 can put out some really long pulses when set to the lowest freq range ~ 1 hz
In that case you might need a delayMicroseconds() inside the loop - but you'll  lose some accuracy. You could also work out an overflow routine - to preserve the accuracy but it will be tricky.

Other things to think about -
Build up some samples and average to get rid of jitter.

Sample repeatedly until you have  an integral of 60 hz   e.g. 16 or 33 ms to remove 60 cycle freq from your result. There is a lot of this, especially in fluorescent light but even in incandescent room lighting. Plus powerline coupling everywhere which gets into the analog electronics of the sensor. Sample the starttime with millis() then build up samples till you have 33 ms then divide by the number of samples you've taken to average.

Maybe post some code in playground when you get it going. We used these sensors to pull heartbeat signals off of LED's shined through fingers and they worked pretty well. The technique requires solid hardware design to make work reliably though. I remember I posted some code in the Wiring forum at the time - It's going back two or three years though so dig deep.

Why doesn't an admin move this whole thread to a hardware forum, to be more useful :)

Paul Badger


I saw that light-to-freq. chip before. Are you using that over a CdS cell for better accuracy? You could possibly determine what KIND of light you are seeing with the abilities of this chip, no? Just out of curiosity, what are you using the TSL230 for??


thanks paulb for all the info and code. i will give it  try once i have time.

i am trying to find the best way for the finger heart beat detector and thought this chip might do the trick. but i think since it has such a wide light range it will not be the best chip for the job.



I actually don't think it's such a bad chip for heartbeat sensor. You should definitely sample on power line frequency though.

One issue is that it is larger than some other sensors, and kind of makes a lump in the finger sensor, I suppose this could be good or bad.  Taos also makes a much smaller three wire model in something that is smaller than a TO92 package. It might be a better choice (cheaper too) since you can pretty much control the light you use through the finger.

If you've noticed the commercial models (in the emergency room) they are plenty bright.

FYI - Circuit Cellar had an article on building a pulse oxyimeter a few years back - maybe search their site. From memory it used a Taos sensor - maybe voltage output - right into an A/D input. We made the technique work with op-amps too.

One key is that the physical mount must try and immobilize the sensor - the emergency room models have a pretty fierce clamp on them. The circuit cellar model used a split piece of PVC conduit. We found that some stretchy pipe insulation was useful and worked fine too. You can kind of tighten it up to spec by wrapping with duct tap.

Good luck,

I'd like to get a page for this up sometime in the near term - other people would surely like to figure out easiest way too. Mabye someone will come up with a good source (or design for) a simple clamp.



hey thanks for the info.

i found the article you mentioned:




Our family used to have this REALLY old exercise maching (stationary bicycle kind), and it has this odd-looking snap that you put on your finger, and then plug the 1.5mm jack into the machine to measure your heartbeat. I always wondered how it worked. Now I know; on one half of the snap (the device looks like a wooden clothes pin), it has an ultrabright IR LED. On the other half, it has a light-to-frequency converter. I could salvage that...I'd be curious to see what the code looks like that you are using. Can you post it? Also, are you using an A/D converter?  


With a pulse output you don't use A/D instead measure the pulse with the code above. You should add something to sample on an integral of the power line frequency though. As I said above, there's some code on the Wiring site, if you dig deep enough.

The advantage of the pulse system is a much wider range, as much as 15-18 bits of A to D, which starts to turn into a really hairy (and expensive) analog system (at least if you want it to be accurate).



I finally had some time to hook up the TSL230 to an Arduino Mini.

here is the code i used for the arduino board and some code to print out a graph with processing.

the graph is still a bit jumpy. i hope to make this a bit more stable.

-- here is the code for the arduino --
int s0 = 8;
int s1 = 9;
int s2 = 10;
int s3 = 11;
int inPin = 2;

unsigned long duration;

void setup(){

 pinMode(inPin, INPUT);

 pinMode(s0, OUTPUT);
 pinMode(s1, OUTPUT);
 pinMode(s2, OUTPUT);
 pinMode(s3, OUTPUT);




void loop(){
 duration = pulseIn(inPin, HIGH);


-- code for processing

// i have the TSL2300 on a solderess board and am holding a IR led to the side of my finger
// you might have to adjust the distance between IR led and TSL230 to get the graph in the right range

// Graph
// by David A. Mellis
// Demonstrates reading data from the Arduino board by graphing the
// values received.
// based on Analog In
// by <a href="http://itp.jtnimoy.com">Josh Nimoy</a>.

import processing.serial.*;

Serial port;
String buff = "";
int NEWLINE = 10;

// Store the last 64 values received so we can graph them.
int[] values = new int[64];

int min_value = 0;
int max_value = 0;
int min_pos = 0;
int max_pos = 0;

void setup()
 size(600, 600);
 // println("Available serial ports:");
 // println(Serial.list());

 port = new Serial(this, Serial.list()[0], 9600);  


void draw()

 // Graph the stored values by drawing a lines between them.
 max_value = -1000;
 min_value = 1000;

 for (int i = 0; i < 63; i++) {
   line(i * 8, 255 - values, (i + 1) * 8, 255 - values[i + 1]);

   if(values < min_value){
     min_value = values;
     min_pos = i;
   if(values > max_value){
     max_value = values;
     max_pos = i;

 line(min_pos * 8, 0              , min_pos * 8, 255 - min_value);
 line(max_pos * 8, 255 - max_value, max_pos * 8, height);

 while (port.available() > 0)


void serialEvent(int serial)

 if (serial != NEWLINE) {
   // Store all the characters on the line.
   buff += char(serial);
 else {
   if(buff.length() > 0){
     // The end of each line is marked by two characters, a carriage
     // return and a newline.  We're here because we've gotten a newline,
     // but we still need to strip off the carriage return.
     buff = buff.substring(0, buff.length()-1);

     // Parse the String into an integer.
     int val = Integer.parseInt(buff);

     // Clear the value of "buff"
     buff = "";

     // Shift over the existing values to make room for the new one.
     for (int i = 0; i < 63; i++)
       values = values[i + 1];

     int temp_val = val - 10000;
     // Add the received value to the array.
     values[63] = temp_val;
     print(" " + temp_val);


Go Up