Measure nightsky with TSL237

How about uW/cm² to Candela then? Or is there any other way of converting uW/cm² to mag/AS2?

Edit: i found a convertion site for w/cm2 to cd/m2 and according to that, 1w/cm2 = 6 830 000 candela/m2

ref: http://www.calcul.com/light-luminance

Ok, got a little help from the guys at www.astronet.se :slight_smile:

This is the code as it looks now:

#include <FreqCounter.h>
#include <Math.h>

long Msqm;
const float A = 22;

void setup() {
  Serial.begin(57600);                    // connect to the serial port
  Serial.println("Frequency Counter");
  
}

long int frq;
void loop() {

 FreqCounter::f_comp= 100;             // Set compensation to 12
 FreqCounter::start(1000);            // Start counting with gatetime of 100ms // CHANGED TO 1000/
 while (FreqCounter::f_ready == 0)         // wait until counter ready
 
 frq=FreqCounter::f_freq;            // read result
 Serial.print(frq);   // print result
 Serial.print(" Hz ");
 Serial.print(Msqm);
 Serial.println(" Mag/Arcsecond2 ");
 delay(20);
 Msqm = A - 2.5*log(frq);
 return;
}

And that gives this on the monitor:

0 Hz 22 Mag/Arcsecond2 
1 Hz -2147483648 Mag/Arcsecond2 
3 Hz 22 Mag/Arcsecond2 
3 Hz 19 Mag/Arcsecond2 
3 Hz 19 Mag/Arcsecond2 
3 Hz 19 Mag/Arcsecond2 
3 Hz 19 Mag/Arcsecond2 
6 Hz 19 Mag/Arcsecond2 
55 Hz 17 Mag/Arcsecond2 
911 Hz 11 Mag/Arcsecond2 
1333 Hz 4 Mag/Arcsecond2 
1319 Hz 4 Mag/Arcsecond2

The formula is A - 2.5*log(frq) where A is the magnitude constant, right now, the "guess" for A is 1Hz at a level 22 mag sky. //not calibrated at all though.

Corpze:
Ok, i start to understand now, for the long, it can hold 32 bit of numbers, witch is 2 billions something, i think that will do, so for now, i will count Hz.

i also found this formula that seems more logical for me :slight_smile:

From candela/m2 to magnitudes/arcsec2:
B=-2.5Log(C/108000) or 12.58-2.5Log(C)

Yes. But the variable has to be able to handle the math you will use when scaling and squaring, be able to count much bigger than the numbers used, and smaller.

If I am dealing with kilometers, my work unit might be in millimeters, mm fractions are lost.
To help keep accuracy, instead of 1 float factor like 333.333333 I keep two integers 1000 and 3 and use those as 'x 1000 / 3' in the bigger equation.
When the bigger equation is written out don't be afraid to rearrange the operations (without breaking the algebra!) to push the intermediate value high before dividing.
X = A * (1000 / 3) * (22 / 7) would re-arrange to X = A * 22000 / 21. Note that with FP using factors you get the first.

Once you have your equation, then is the time to see how many digits you need. If A above is big then I need enough for 7000 x the biggest 'A' can be with enough to the right for display decimals.

Using mm I can show 1.234 km or 1.2 km and know I had 2 places round-safe in the math.

You deal with some squares and factors with lots of places? Some of those will be simple as a ratio of integers, some won't. Pi to 6 places is 3141592 / 1000000, to use that in an integer equation adds 7 digits to the digits needed to hold the number being multiplied by Pi to 6 places. There's a price for precision and scale, in digits and bytes.

a small bug in your code => you printed msqm before calculating it.

  • added a log(0) prevention
#include <FreqCounter.h>
#include <Math.h>

long Msqm;
const float A = 22;

void setup()
{
  Serial.begin(57600);
  Serial.println("Frequency Counter");
}

long frequency;

void loop()
{
  // MAKE MEASUREMENT 
  FreqCounter::f_comp = 100; 
  int gatetime = 1000;

  FreqCounter::start(gatetime);
  while (FreqCounter::f_ready == 0);        // wait until counter ready
  frequency = FreqCounter::f_freq;

  // CONVERT
  if (frequency > 0 )    // prevent log(0)
    Msqm = A - 2.5 * log(frequency);
  else
    Msqn = A;

  // DISPLAY RESULTS
  Serial.print(frequency);
  Serial.print(" Hz ");
  Serial.print(Msqm);
  Serial.println(" Mag/Arcsecond2 ");
  delay(20);
}

Thanks, i will try log10 instead, and add a button, one thing i want to add is higher resulotion on the Hz-side, can i use a divider or something like that? Will mHz result in higher res.?
And measure several samples and average them?

What about this:

frq = 0;
nSamples = 0;
buttonSQM = DigitalRead(HIGH);
while (buttonSQM==HIGH){
frq += FreqCounter::f_freq;
nSamples+=1;
buttonSQM = DigitalRead(HIGH);
}
frq = frq/nSamples;

And measure several samples and average them?

Watch out for rounding errors due to integer division as it truncates.

Think for your application you better sample for some time and determine the minimum and maximum.

frequency = 0;
unsigned long minimum = 1000000;
unsigned maximum = 0;

buttonSQM = digitalRead(SomePin);

while (buttonSQM == HIGH)
{
  frequency = FreqCounter::f_freq;  
  if (frequency > maximum) maximum = frequency ;
  if (frequency < minimum) minimum = frequency;
  buttonSQM = digitalRead(SomePin);
}

now do math with min & max as this gives the range (accuracy) of your measurements.
you can also do average as (min + max)/2;

I am just now building something similar in function, although I'm not interested in measuring dark sky. However, I have a few suggestions for you:

First, think in terms of the area of the sky the sensor is seeing. The shorter the focal length of the lens, the wider the area that impinges upon the sensor. Of course, the sensor is tiny, so that may not be much of a consideration. But it's something to keep in mind.

Second, use an "optical amplifier" to strengthen the signal: a lens. Surplus shops have tons of huge, short-focus lenses that were used in the now-obsolete projection monitors, and you can get a 3" objective for under $10. I found a plastic jar that fit it perfectly, cut the jar up and stuck it on, then mounted the sensor inside it. This thing was extremely sensitive: I was using the TSL235R sensor, which is not as sensitive as the one you describe, I was still getting something like 3 Hz output pointed at a midnight sky. When I realized that I didn't need that much sensitivity, I tore it apart.

GeezerFrog:
I am just now building something similar in function, although I'm not interested in measuring dark sky. However, I have a few suggestions for you:

First, think in terms of the area of the sky the sensor is seeing. The shorter the focal length of the lens, the wider the area that impinges upon the sensor. Of course, the sensor is tiny, so that may not be much of a consideration. But it's something to keep in mind.

Second, use an "optical amplifier" to strengthen the signal: a lens. Surplus shops have tons of huge, short-focus lenses that were used in the now-obsolete projection monitors, and you can get a 3" objective for under $10. I found a plastic jar that fit it perfectly, cut the jar up and stuck it on, then mounted the sensor inside it. This thing was extremely sensitive: I was using the TSL235R sensor, which is not as sensitive as the one you describe, I was still getting something like 3 Hz output pointed at a midnight sky. When I realized that I didn't need that much sensitivity, I tore it apart.

I will use a 20mm 20degree lens, so i will amplify the light :slight_smile:

About the rounding errors, i will look in to that, but something i don´t understand is why i should use log10( instead of log( ?

Then, a guy i spoke to said that using that low of freq. can result in really bad accuracy, and pointed out that i might measure the time between two uprising flanks??? and then invert, then i can get accuracy down to the CPU-speed? I have no idea of what he is meaning?

FreqCounter for very low frequencies (below 100 Hz or something) isn't the best thing you can do to count cycles.

As someone told you, you would need to measure the length of the pulse instead (FreqMeasure, FreqPeriod, InputCapture, pulseIn, millis()/micros() ).
Since at dark time it's rare to get more than 10,000Hz with those sensors, I think FreqCounter isn't useful at all for this project.

Oh... can you recomend any other method, library or code?

At the first page, i linked to this sketch; How to: Light to Frequency Converter - TSL235R? - #17 by madepablo - Interfacing - Arduino Forum

i Think he is counting pulses and from that, fetches the frequency, may that do the trick?

I am not sure, but i found this site: http://www.avdweb.nl/arduino/hardware-interfacing/frequency-period-counter.html

And i am trying this code:

#include <FreqPeriodCounter.h>
 
const byte counterPin = 5; 
const byte counterInterrupt = 1; // = pin 3
FreqPeriodCounter counter(counterPin, micros, 0);
unsigned long centiHz = counter.hertz(100);
float hz = 1000/counter.period;
 
void setup(void) 
{ Serial.begin(9600); 
  attachInterrupt(counterInterrupt, counterISR, CHANGE);
}
 
void loop(void) 
{ if(counter.ready()) Serial.println(counter.hertz());
}
 
void counterISR()
{ counter.poll();
}

And im getting this now;

3068
5004
1903
5016
5008
5053
1669
3660
5034
3665
3070
5018
5005
5057
2103
5033
2497
1668
2514
5043
1907
1667
5032
2497
1666
5046
1906
1666
3651
5056
3652

Am i getting the Hz in "centiHz" now? and why is the values fluctuating that much? i left the sensor in a enclosure with the same amout of light hitting it all the time :confused:

You seem to be futzing around changing too many things at once.

If your process depends on counting pulses, you need to get that process right before
worrying and fiddling with what you do subsequently.

michinyon:
You seem to be futzing around changing too many things at once.

If your process depends on counting pulses, you need to get that process right before
worrying and fiddling with what you do subsequently.

Well, i'm trying out different sketches to try reading just the pulses from the sensor, because the former sketch reading the Hz i think... I am a total newbe and doing many errors to...

minaya:
FreqCounter for very low frequencies (below 100 Hz or something) isn't the best thing you can do to count cycles.

As someone told you, you would need to measure the length of the pulse instead (FreqMeasure, FreqPeriod, InputCapture, pulseIn, millis()/micros() ).
Since at dark time it's rare to get more than 10,000Hz with those sensors, I think FreqCounter isn't useful at all for this project.

Is the limit in the FreqCounter library? i was thinking to count Hz as the sensor itself generates Hz, not pulses... or am i missing something? The sensor is the TSL237 light to frequency sensor.

BR/Daniel

You can count the time length of a number of pulses, the more you count the more the per-pulse average will ... average out.

You can count how many pulses in a measure of time and lose a fraction of a pulse. The longer the time the less the lost fraction means.

pulses/time or time/pulses, both are ratios is all. Get one, you have the other.

GoForSmoke:
You can count the time length of a number of pulses, the more you count the more the per-pulse average will ... average out.

You can count how many pulses in a measure of time and lose a fraction of a pulse. The longer the time the less the lost fraction means.

pulses/time or time/pulses, both are ratios is all. Get one, you have the other.

That sound quite logical even to me :slight_smile: is there any good library/code that i can use for this? I believe that, after counting time, i will be have to translate to time to Hz, in some way, and that Hz is more realible than just counting Hz straight from the sensor?

AHA! Now i understand the differens between pulses and freq, maybe this lib. is more suiteble for me?

http://interface.khm.de/index.php/lab/experiments/frequency-measurement-library/
But he is writning:
The library returns the measured period length in 1/16 us steps as a long integer. To get the frequency, the clock frequency has to divided by the returned value. The clock frequency is set in this example to 16000400 to compensate inaccuracies of the Arduino board.

What is that meaning for me and my arduino?

This might also work?
http://www.pjrc.com/teensy/td_libs_FreqMeasure.html

I wouldn't use a library. I'd save micros() in an unsigned long, count 10,000 pulses and save the micros() right then.
Annnnnd I think you can get micros() in an interrupt though it's stopped. If not then you'll pick up a couple micros setting a flag in the interrupt, leaving the interrupt and catching the flag in loop(). With a tight loop() you'll have micros() very quickly.

Errors --- you can measure Arduino inaccuracy and compensate. Deal with that after you get the rest working. It amounts to changing time microseconds

frequency = pulses / time

If the time is a 62845 microseconds then multiply pulses by 1 million then divide by 62845 to get Hz = cycles(pulses) per second.

10000 pulses / 62845 usecs = 10000 pulses / ( 62845 seconds / 1000000 ) = 10000 pulses x 1000000 / 62845 seconds (doing it with integers and the least loss requires 64-bit long long int) = 159121 Hz.

When you do math for science, keep the units (pulses, seconds, ergs) in the math because at the end if your units don't make sense then your math didn't either. (this is where you remember your science teachers saying the same thing)

Whats wrong with using library? Is the library i have posted of any use?

I am not that experienced so i can code that kind of things :frowning:

Thats why i use librarys and allready written code

@GoForSmoke, 10,000 pulses?!. This would take a whole life if the site is dark. The TSL237 generates generates pulses of frequencies as low as ~0.15Hz in dark skies (even lower if you use filters). That's more than 6 seconds of period, so integrating 10,000 cycles seems a bad idea.

The best approach I think is to measure first one single pulse and decide (at runtime) if you want to count frequencies (or a great amount of pulses to promediate, as GoForSmoke suggested) or you need an alternative way to get the frequency.

Corpze, the SQM is cheap for what it does. If you take into account that those instruments need filters to cut the IR and narrow the spectral sensibility, needs some kind of optics to narrow the FoV, needs a case, an LCD, a board ... you end (in the arduino road) with an instrument that is nearly as expensive as the SQM (or even more!) and probably not as accurate (at least if you don't know what you do/need), trust me. And then, you need to calibrate the device.

If you want to build it just for learning purposes or something else, I think you need to return to the basics and stop trying to get inmediate results. I've been researching on this topic for months and I haven't found any library that just do what you want, sorry.

Just my two cents.