Pages: 1 ... 3 4 [5] 6   Go Down
Author Topic: Measure nightsky with TSL237  (Read 11472 times)
0 Members and 1 Guest are viewing this topic.
Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 220
Posts: 13836
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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%

Logged

Rob Tillaart

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

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4813
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

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.
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Sweden
Offline Offline
Jr. Member
**
Karma: 0
Posts: 80
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

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?
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 220
Posts: 13836
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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++;
}
 
Logged

Rob Tillaart

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

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4813
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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)

So 10000ms of measurements is a number i can start with.

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.

Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Sweden
Offline Offline
Jr. Member
**
Karma: 0
Posts: 80
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, the bits and pieces are starting to fall in place now smiley

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?
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 220
Posts: 13836
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


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

Rob Tillaart

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

Sweden
Offline Offline
Jr. Member
**
Karma: 0
Posts: 80
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, thanks, i will give this a try!
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 220
Posts: 13836
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

update smiley
Code:
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;
}

Logged

Rob Tillaart

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

Sweden
Offline Offline
Jr. Member
**
Karma: 0
Posts: 80
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

update smiley
Code:
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?
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 220
Posts: 13836
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

the ul makes the compiler interpret the number as unsigned long.
Logged

Rob Tillaart

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

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4813
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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!

 

Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Sweden
Offline Offline
Jr. Member
**
Karma: 0
Posts: 80
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4813
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Pages: 1 ... 3 4 [5] 6   Go Up
Jump to: