Small sketch for TSL235R Light to Frequency sensor

Today I received two TSL235 sensors that convert incoming light to frequency. As there was no article on the playground yet on this particular sensor I wrote a small sketch and added some comments - Arduino Playground - TSL235R - to get people started. The code does not compensate for anything yet (input voltage, temperature etc) ; maybe some future version.

In contrast to the TSL230R it has no configurable divider for the frequency so the # IRQ's can become quite high. Today's max inhouse ~160000 . Therefor I used only the rising edge for the IRQ routine. When it is really really dark one could use CHANGE edge for the IRQ, to double the precision, but be carefull as your Arduino might get stalled during daylight :slight_smile:

As always comments and remarks are welcome,

Rob

Take a look, may be here you could found something interesting.
http://arduino.cc/forum/index.php/topic,21536.0.html

I hope it could helps you.
madepablo

robtillaart:
...In contrast to the TSL230R it has no configurable divider for the frequency so the # IRQ's can become quite high. Today's max inhouse ~160000 . Therefor I used only the rising edge for the IRQ routine. When it is really really dark one could use CHANGE edge for the IRQ, to double the precision, but be carefull as your Arduino might get stalled during daylight :slight_smile:

As always comments and remarks are welcome,

Rob

I'm seeing this too, if the sensor sees the window the script output stops. When I shield the sensor from bright light, it starts streaming output again, with the first value read being very high.

How do I set this up to scale for brighter environments? I'm trying to design a logger that tracks how many minutes of sunlight there are at a given location over the course of a day. Any suggestions on getting this sensor to do the sensing?

Cheers, D

For bright sunlight you should use: attachInterrupt(0, irq1, RISING); - but still it can generate too much IRQ's to handle. So if SW cannot handle HW comes in.

check - http://interface.khm.de/index.php/lab/experiments/arduino-frequency-counter-library/ - to get an idea how this can be done.

Please not that this lib affects internal timers so some things may not work anymore.

Another alternative is to make a HW divider before connecting to Arduino. check - Building Dividers With Flip-Flop | PDF -

Dear Rob,
Thank you for the code. Works great with my Uno on digital pin 2, and on digital pin 3 with small change in code. Can you tell me how to modify it to read two TSL235 sensors?
Best, David

two TSL should be something like this (not tested)

/*
 *    FILE: TSL235R_duo.pde
 *  AUTHOR: Rob Tillaart
 *    DATE: 2013-02-15
 *
 * PURPOSE: prototype TSL235R monitoring (double)  
 *
 * Digital Pin layout ARDUINO
 * =============================
 *  2     IRQ 0    - to TSL235R
 *
 * PIN 1 - GND
 * PIN 2 - VDD - 5V
 * PIN 3 - SIGNAL
 *
 */

volatile unsigned long counter1= 0;
volatile unsigned long counter2= 0;
unsigned long oldcnt1 = 0;
unsigned long oldcnt2 = 0;
unsigned long t = 0;
unsigned long last;

void irq1()
{
  counter1++;
}

void irq2()
{
  counter2++;
}

///////////////////////////////////////////////////////////////////
//
// SETUP
//
void setup() 
{
  Serial.begin(115200);
  Serial.println("START");
  pinMode(2, INPUT);
  digitalWrite(2, HIGH);
  attachInterrupt(0, irq1, RISING);
  attachInterrupt(1, irq2, RISING);
}

///////////////////////////////////////////////////////////////////
//
// MAIN LOOP
//
void loop() 
{
  if (millis() - last > 1000)
  {
    last = millis();
    t = counter1;
    unsigned long hz = t - oldcnt1;
    Serial.print("FREQ: "); 
    Serial.print(hz);
    Serial.print("\t = "); 
    Serial.print((hz+50)/100);  // +50 == rounding last digit
    Serial.println(" mW/m2");
    oldcnt1 = t;

    t = counter2;
    hz = t - oldcnt2;
    Serial.print("FREQ: "); 
    Serial.print(hz);
    Serial.print("\t = "); 
    Serial.print((hz+50)/100);  // +50 == rounding last digit
    Serial.println(" mW/m2");
    oldcnt2 = t;
  }
}
// END OF FILE

This worked with two sensors.
Thanks!

Welcome!

Is there any change i can use the code for the TSL237 - sensor?
That sensor is way more sensitive for low light, i believe it has a output frequency @ 21.8 ?W/cm2 instead of the TSL235 that has 430 ?W/cm2.

It may be some other differences to? Here is the PDF for it: https://docs.google.com/viewer?a=v&q=cache:Plvrk-_pFQwJ:www.ams.com/eng/content/download/250250/975933/file/TSL237-J.pdf+TSL237&hl=sv&pid=bl&srcid=ADGEESjUTdu6N77Fo19CfVUS9QH3XGxoRrMVamEsH0Ks55GQgOfOke8V-DaDA0qYjHfaNHOmm9-tUJVo5ovLYqdlAONPu6ZyLsKOm_iwdDCqSC2U_2hMFH2ynBy48mAt6bFnG9jLaAYl&sig=AHIEtbShhuCFzTVDeFqfAbEUaVrjHy2ypw

The reason i want to use this is that when i push a button i want to take a reading from the sensor, (or two-three readings and use a median value for better accuracy) and then calculate that value to Magnitude / square arc second Magnitudes/ Square Arc Second

so i dont wanna do a continous reading, just when i press a button, take a reading, display the magnitude/ square arc second on a lcd for about 10 sec. and then my arduino will continue with the rest of my code (witch is stepper motor controll with steps printout and a DHT-sensor.

Can this be done with this code?

BR/ Daniel

Is there any change i can use the code for the TSL237 - sensor?

You need to compare the datasheets and if the only diff is the light intensity/frequency relation it should be possible.

-update-
A quick look says yes as the output signal is typically 4.5V that is enough to trigger an IRQ I think. Otherwise you can add an extra transistor to make it 5V pulses.

The link to the TSL237 datasheet - http://www.ams.com/eng/content/download/250250/975933/file/TSL237-J.pdf -

At least a bit shorter :wink:

robtillaart:
two TSL should be something like this (not tested)

/*
  • FILE: TSL235R_duo.pde
  • AUTHOR: Rob Tillaart
  • DATE: 2013-02-15
  • PURPOSE: prototype TSL235R monitoring (double)
  • Digital Pin layout ARDUINO
  • =============================
  • 2     IRQ 0    - to TSL235R
  • PIN 1 - GND
  • PIN 2 - VDD - 5V
  • PIN 3 - SIGNAL

*/

volatile unsigned long counter1= 0;
volatile unsigned long counter2= 0;
unsigned long oldcnt1 = 0;
unsigned long oldcnt2 = 0;
unsigned long t = 0;
unsigned long last;

void irq1()
{
 counter1++;
}

void irq2()
{
 counter2++;
}

///////////////////////////////////////////////////////////////////
//
// SETUP
//
void setup()
{
 Serial.begin(115200);
 Serial.println("START");
 pinMode(2, INPUT);
 digitalWrite(2, HIGH);
 attachInterrupt(0, irq1, RISING);
 attachInterrupt(1, irq2, RISING);
}

///////////////////////////////////////////////////////////////////
//
// MAIN LOOP
//
void loop()
{
 if (millis() - last > 1000)
 {
   last = millis();
   t = counter1;
   unsigned long hz = t - oldcnt1;
   Serial.print("FREQ: ");
   Serial.print(hz);
   Serial.print("\t = ");
   Serial.print((hz+50)/100);  // +50 == rounding last digit
   Serial.println(" mW/m2");
   oldcnt1 = t;

t = counter2;
   hz = t - oldcnt2;
   Serial.print("FREQ: ");
   Serial.print(hz);
   Serial.print("\t = ");
   Serial.print((hz+50)/100);  // +50 == rounding last digit
   Serial.println(" mW/m2");
   oldcnt2 = t;
 }
}
// END OF FILE

I need to create a sensor array, Its possible check more than 2 sensor? (almost 7-10).

Regards

Yes that would be possible but not for the very bright signals. Check the (PCI) PinChangeInterrupt library - Arduino Playground - PinChangeInt - and give every sensor its own counter.

As the PCI-lib is a SW lib it takes more time to handle every pulse than the HW based interrupts mentioned above so this will limit the amount of pulses per second that can be handled.

Hi,

Is there a way to sample a reading, by that I mean just take ONE reading from the sensor and then stop the loop in this sketch? I'm not too familiar with the attachInterrupt concept and am a little confused as to how to get just one reading rather than loop it over and over again. I tried running it the code in the void setup() portion but that isn't working. Or can I write another function to say sample one reading? But that would require passing variables from function to function.

Sorry for the lack of knowledge on my part.

madsci:
Hi,

Is there a way to sample a reading, by that I mean just take ONE reading from the sensor and then stop the loop in this sketch? (...)
Or can I write another function to say sample one reading? But that would require passing variables from function to function.

Sorry for the lack of knowledge on my part.

Does anybody know how to implement that? At least some clues what to search for :slight_smile:

volatile bool doneOnce = false;

void setup()
{
... setup thingies here
}

void loop()
{
  if (! doneOnce)
  {
    doneOnce = true;
    ... do the thing;
  }
  do other thingies
}