Dear all,
I'm trying to use a geiger tube counter with the Arduino mega board. I have used the code below that works correctly. However, I would like to implement a pulse count for one hour to obtain an average cpm during 60 minutes. I suppose may not be possible works with Millis since I have tried without success other conditions inside or outside the "if".
could someone help me with this.
Thanks in advanced...
Cesar
// Conversion factor - to uSV/h
#define CONV_FACTOR 0.00151
int geiger_input = 7;
long count = 0;
long cpmH = 0;
long countPerMinute = 0;
long timePrevious = 0;
long timePreviousMeassure = 0;
long time = 0;
long countPrevious = 0;
float radiationValue = 0.0;
long cpmM = 0;
void countPulse() { // Captures count of events from Geiger counter board
count++;
}
void setup(){
pinMode(geiger_input, INPUT);
digitalWrite(geiger_input,HIGH);
interrupts();
Serial.begin(19200);
attachInterrupt(0,countPulse,FALLING);
}
void loop(){
if (millis()-timePreviousMeassure > 60000){
cpmM=1*count;
radiationValue = cpmM * CONV_FACTOR;
timePreviousMeassure = millis();
Serial.print("cpmM = ");
Serial.print(cpmM,DEC);
Serial.print(" - ");
Serial.print("uSv/h = ");
Serial.println(radiationValue,4);
count = 0;
}
}
You need to also post the sketch you wrote that doesn't work. Otherwise we can only guess the error.
I'm surprised that the posted code works correctly, because there are a couple of fairly serious problems with it. You've been lucky so far!
- variables shared with interrupt routines must be declared "volatile", fixed as follows:
volatile long count = 0;
- Likewise, variables shared with interrupts must be protected from corruption by the interrupt, while it is being accessed by the main program. Do this by making a copy of the variable (with the interrupts turned off) before using it in the main program. Fixed as follows:
noInterrupts(); //off
long count_copy=count;
count=0; //reset count here, not later in the code
interrupts(); //back on
cpmM=1*count_copy; //why bother to multiply by "1"?
Hint: one hour in milliseconds is 3600000UL.
My difficulty here is how to make two counts happen simultaneously without interrupting the other. When I do,
if (millis()-timePreviousMeassure > 60000){
cpmS = sec_count;
.........
sec_count = 0;
}
the count starts again from zero. I can't use other if(Millis().....for 3600000
I never need this before, but I suppose that there is some rule or some way to do.
Hi UltraSeven,
if (millis()-timePreviousMeassure > 60000) means every 60 thousand milliseconds which is every 60 seconds = every minute.
You get the counts from one minute. To obtain an averaged value each hour you could add the counts of each minute to another variable and increment a second countervariable.
If this countervariable reaches value 60 one hour is over then calculate hour-average value.
This would result in a averaged value updated one every 60 minutes.
A floating average could be calculated with an array of 60 elements.
Whenever a minute is over actualise array-element of this minute.
If minute 3 is over MinuteCounts[3] = count
If minute 4 is over MinuteCounts[4] = count
etc. etc.
calculate hour-average by adding all 60 elements of the array.
best regards
Stefan
Hi Stefan,
Looks very easy. I will try.
Thanks a lot.
Also thanks to aarg and jremington for the observations.
Regards,
UltraSeven