Pulse Counter Arduino
Pulse Counter Arduino
Pulse Counter Arduino
up vote 2 I have been trying to count pulses from a 12,500 Hz square wave to trigger an output.
down vote Here's the code I have so far. When the Arduino is reset it prints 315 to the serial over a
favorite
25 ms sample. 315 x 40 = 12600. Which seems to me it's working perfectly.
My only problem is it only returns this number once upon reset of the board. Now if I
move that same code down into void loop, it counts consecutively giving me
inconstant returns.
I am not understanding what I need to put in the loop section so I can repeatedly and
accurately count how many toggles of the input pin I am getting over a period of time so I
can do something to the output based off the presence of the 12,500 Hz signal or not.
volatile int IRQcount;
int pin = 2;
int pin_irq = 0; //IRQ that matches to pin 2
void setup() {
// Put your setup code here, to run once:
Serial.begin (9600);
attachInterrupt(pin_irq, IRQcounter, RISING);
delay(25);
detachInterrupt(pin);
Serial.print(F("Counted = "));
Serial.println(IRQcount);
}
void IRQcounter() {
IRQcount++;
}
void loop() {
// Put your main code here, to run repeatedly:
}
Using the above code, every time I press the reset button I get one line in the serial
window.
Counted
Counted
Counted
Counted
Counted
=
=
=
=
=
441
442
441
441
441
Now I want to get the same result, but repeating over and over. That way if the signal drops
out I can trigger an output to turn off (LOW). When the signal is present the output will go
high.
My attempt was to move the attach interrupt down into void loop, so it would repeat.
The return I get is self-updating, but the "count" instead of starting from 0 each time starts
from the previous count. So it gets larger and larger. I am looking to return a constant value
that represents my 12500 Hz signal so that, and only that, will trigger my output.
Counted = 442
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
886
1330
177
2221
2667
3112
3557
4002
4448
4893
5338
5784
6229
6674
7120
7565
8010
8456
8901
9347
9792
10237
10683
11130
11576
12022
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
Counted
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
12469
12915
13361
13808
14254
14700
15147
15593
16040
16486
16932
17378
17825
18271
18717
19164
19610
20056
20503
20949
21395
21842
22288
22735
23169
23616
24062
24508
24955
25401
25730
25756
26200
26646
27093
27539
27985
28432
28878
29324
29770
30217
30663
31110
31556
32002
32449
-32641
-32195
-31748
-31302
-30855
-30408
-29962
-29515
-29069
-28622
"Now if i move that same code down into void loop it counts consecutively giving me inconstant
returns." means what exactly? Ignacio Vazquez-Abrams Oct 4 '14 at 15:39
You need to reset IRQCount back to 0 before attaching the interrupt again. Otherwise it will just
continue counting from where it stopped last time.
I would actually keep the interrupt attached and just reset the variable just before the delay. That way
the overhead of attach/detachinterrupt doesn't get added to the 25ms delay.
volatile int IRQcount;
int pin = 2;
int pin_irq = 0; //IRQ that matches to pin 2
void setup() {
// put your setup code here, to run once:
Serial.begin (9600);
attachInterrupt(pin_irq, IRQcounter, RISING);
}
void IRQcounter() {
IRQcount++;
}
void loop() {
// put your main code here, to run repeatedly:
IRQcount = 0;
delay(25);
int result = IRQcount;
Serial.print(F("Counted = "));
Serial.println(result);
}
Since an int is 2 bytes an interrupt might occur in the middle of setting/reading those two bytes. This
might result in an occasional wrong value. To prevent that you should disable interrupt while
setting/reading the value
volatile int IRQcount;
int pin = 2;
int pin_irq = 0; //IRQ that matches to pin 2
void setup() {
// put your setup code here, to run once:
Serial.begin (9600);
attachInterrupt(pin_irq, IRQcounter, RISING);
}
void IRQcounter() {
IRQcount++;
}
void loop() {
// put your main code here, to run repeatedly:
cli();//disable interrupts
IRQcount = 0;
sei();//enable interrupts
delay(25);
cli();//disable interrupts
int result = IRQcount;
sei();//enable interrupts
Serial.print(F("Counted = "));
Serial.println(result);
Thanks Gerben! Using that code i get the occasional junk return. What would be the easiest way to
denounce this? Make an out take lets say 3 readings before making a decision on what to do. Or
averaging pulses over a span instead of a raw count? Heres an example of the return, i get the
anomaly every few seconds. Counted = 439, Counted = 438, Counted = 430, Counted = 48,
Counted = 318, Counted = 438, Brandon Whosville Oct 4 '14 at 16:16
1
I lengthened the delay to give a larger sample size. This gives me a workable return from my noisy
input source. This seems to work perfect! Thank you! Brandon Whosville Oct 4 '14 at 16:54
I assume you used the code with the clis and seis in it. Rather strange having two consecutive
wrong values. Gerben Oct 5 '14 at 12:32
1
Gerben, Yes i used the code with the cli and sei in it. Do you mean its strange getting the two wrong
returns in a row? It seems the returns are correct, it is the incoming signal that is not stable giving
junk returns. If i sample over lets say 100ms it gives plenty of pulses per sample to safely activate
or kill the circuit. I really appreciate your help! Brandon Whosville Oct 6 '14 at 15:13
But the 48 and 318 you got are both lower that the average of about 435. I don't know the connected
circuit, so it could just as well be the circuit, instead of the arduino code. Anyways, as long as you
are happy with the end result... Glad to have helped. Gerben Oct 6 '14 at 17:41
http://arduino.stackexchange.com/questions/4451/counting-pulses-with-interrupt
http://kms15.github.io/ArduinoPulseGenerator/