Go Down

### Topic: Measure nightsky with TSL237 (Read 34626 times)previous topic - next topic

#### robtillaart

#60
##### Mar 06, 2013, 07:13 pm
the .x part error must be seen through "logarithmic glasses"

log(10) = 1
log(11) = 1.041392685
so if the value is around 10 and the math does truncating, the max error is 4% log(10.999999) - log(10)
if the math does rounding, the max error is < 2.2% log(10.499999) - log(10)

log(100) = 2
log(101) = 2.004321374
=> error is max 0.43% ( trunc => 0.22%)

log(1000) = 3
log(1001) = 3.000434077
=> 0.05%

at 10000 it will be max ~0.005%

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

#### GoForSmoke

#61
##### Mar 06, 2013, 07:23 pm

I understand that i will lose the .x count of the pulses if the time runs out

If you count a certain number of pulses and then see the time, it will be the fraction of a usec that you miss, not a fraction of the much-longer pulse. So in the interrupt routine, we count pulses and get whole pulses that way (detail: have to get start time on a pulse, then count pulses and on the last get end time) and not lose the bigger (pulse is way longer than usec) fraction.
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

#### Corpze

#62
##### Mar 06, 2013, 07:46 pm

I understand that i will lose the .x count of the pulses if the time runs out

If you count a certain number of pulses and then see the time, it will be the fraction of a usec that you miss, not a fraction of the much-longer pulse. So in the interrupt routine, we count pulses and get whole pulses that way (detail: have to get start time on a pulse, then count pulses and on the last get end time) and not lose the bigger (pulse is way longer than usec) fraction.

So, to measure the time between a certain no of pulses, can i use the PulseIn? PulseIn uses just High or Low on a digital pin, I really want to use Rising or something like that?

#### robtillaart

#63
##### Mar 06, 2013, 07:58 pm
NO pulse in measures one pulse.

with an IRQ based counter you can count X pulses in e.g. 10.000.000 microseconds and use that

something like this,
Code: [Select]
`void setup(){  Serial.begin(38400);  attachInterrupt(0, ISR, RISING);}void loop(){  unsigned long start = micros();  interrupts();  while (micros() - start < 10000000UL); // wait 10 seconds   noInterrupts();    Serial.println(count);  count = 0;}void ISR(){   count++;}`

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

#### GoForSmoke

#64
##### Mar 06, 2013, 08:09 pm

No i havenĀ“t really used interrupts more then those that allready have been written in existing code... I have read the reference about interrupts and there are two kinds? internal and external? the external ones are located on pin2 and 3 on the uno. Is one of those inputs usable for me?

Okay. You will be using external interrupt on pin 2 or 3 since you want to detect the starting edge of the pulse.

Quote
I think 10sec will be the highest time i want to measure (the original SQM-meter measures on 2sec)

Just as long as you have a time to aim for. What is reasonable, the data will show like if 1 second consistently gets very close to 10 seconds then 1 second will be good. And if less then that will be good. Of course if 10 seconds does not give consistent values then there is a problem.

2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

#### Corpze

#65
##### Mar 06, 2013, 08:36 pm
Ok, the bits and pieces are starting to fall in place now

I will look in to the example sketch and try that when i have the time to do that, after a given no time (10 sec) i will be able to read the count of pulses in the serial monitor, how will i translate that in to Hz? or am i stepping ahead to fast now?

#### robtillaart

#66
##### Mar 06, 2013, 08:43 pm

if you have x pulse in 10 seconds that makes  x/10  Hz
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

#### Corpze

#67
##### Mar 06, 2013, 08:46 pm
Ok, thanks, i will give this a try!

#### robtillaart

#68
##### Mar 06, 2013, 08:53 pm
update
Code: [Select]
`void loop(){  unsigned long start = micros();  interrupts();  while (micros() - start < 10000000UL); // wait 10 seconds   noInterrupts();    Serial.print(count/10);  Serial.print(".");  Serial.print(count%10);  Serial.println("Hz");  count = 0;}`
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

#### Corpze

#69
##### Mar 06, 2013, 08:54 pm

update
Code: [Select]
`void loop(){  unsigned long start = micros();  interrupts();  while (micros() - start < 10000000UL); // wait 10 seconds   noInterrupts();    Serial.print(count/10);  Serial.print(".");  Serial.print(count%10);  Serial.println("Hz");  count = 0;}`

Why UL on the micros?

#### robtillaart

#70
##### Mar 06, 2013, 09:08 pm
the ul makes the compiler interpret the number as unsigned long.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

#### GoForSmoke

#71
##### Mar 06, 2013, 10:11 pm

NO pulse in measures one pulse.

with an IRQ based counter you can count X pulses in e.g. 10.000.000 microseconds and use that

something like this,

May I suggest a change or two?

I base how I get start and end time on the pulses being expected to come in at less than 10 kHz. Far less, possibly 100's of millis apart, but I'd like to see if this can handle brighter light too.

Anyway, this is more what I had in mind:

Code: [Select]
`volatile unsigned long pulseCount = 0UL;unsigned long startT, endT, freq, pC;void counter(){  pulseCount++; // counting pulses}void setup(){  Serial.begin(38400);  Serial.println( "Frequency counter" );  attachInterrupt(0, counter, RISING);}void loop(){  noInterrupts();  pC = pulseCount;  interrupts();    if ( pC == 1UL )  {    startT = micros(); // start time very close to on a pulse edge    // getting end time should have the same lag within a few cycles  }  // if pulses are 5/second, 10 seconds will take 50 pulses --- check the 5/sec!  if ( pC >= 51UL ) // 50 pulses -after- pulse #1 which was used to start time ON a pulse  {    endT = micros();    endT -= startT; // end now holds elapsed micros    // frequency = pulses/second, we have pulses and microseconds, 1000000 usecs/sec    // Hz = pulses x 1000000 / microseconds      freq = pC * 1000000UL / endT;    Serial.print( "\n count " );    Serial.println( pC );    Serial.print( " micros " );    Serial.println( endT );    Serial.print( " freq " );    Serial.println(freq);    noInterrupts();    pulseCount = 0UL;    interrupts();  }}`

Anyway it compiles and runs but for my test pulses I grounded pin2 through 4.7k ohms and then tapped a jumper (with 5V through a resistor and led) end on the resistor leg connected to the pin.

Maybe it's bounce but I got my pulses without having to tap more than once.

A little debug, it seems I need to copy pulseCount to pC at the speed I got pulses. The math was wrong until I did!

2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

#### Corpze

#72
##### Mar 07, 2013, 07:38 am
The code seems to work fine and for every 50 (+1) pulse it prints the time it took to gather those 50 pulses right? Is there any way to add a decimal or two to the frequencies (float?)

Code: [Select]
` count 51 micros 934564 freq 54 count 51 micros 3450896 freq 14 count 51 micros 8804244 freq 5 count 51 micros 2095280 freq 24 count 51 micros 796124 freq 64 count 51 micros 2395064 freq 21 count 51 micros 975288 freq 52 count 51 micros 13221620 freq 3 count 51 micros 956156 freq 53`

#### minaya

#73
##### Mar 07, 2013, 08:51 am
Just change 'unsigned long freq' to 'float freq'.

The problem I see with the interrupt approach is the large range of frequencies that the TSL is able to output. If you try the program at daytime or pointing at a light source (lets say, 500,000Hz, or even more!), maybe that can overflow?, or hang the Arduino and force you to press reset or power it off/on?.

Even at nightime the frequency output can change if the moon is present.

#### GoForSmoke

#74
##### Mar 07, 2013, 12:05 pm
Those frequencies are integer pulse per second Hz because of the 1000000 / microseconds part of the math.
They could as easily be pulse per msec by using 1000 / micros and give Hz to 3 places.
The other half of that trick is in placing a decimal point in the printout rather than resorting to floats.

Say I have 1234 pulse/msec in a variable named mFreq and I want to print Hz.
I print mFreq / 1000 and get the integer "1"
and then I print a decimal point.

Then I look at mFreq % 1000 which gives the remainder of mFreq / 1000.
If it's less than 100, I print a zero.
{
If it's less than 10, I print another zero. Note I only check for < 10 if the value is < 100.
}
Then I print the remainder.

And yes, it can be rounded up or down but you best do that when calculating what you will display.

Remember that display is for looks. Don't let looks dictate substance, they should only reflect it.
On a full-blown PC, I'd go with doubles but with Arduino I go with what works best and happens to be fastest as well. And this time I didn't need to use long-long's for intermediate steps!

Let me know if you need more. Maybe Rob or someone else won't get there first. My posts are just my attempts to help.

2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

Go Up