10

I have been trying to count pulses from a 12,500 Hz square wave to trigger an output. Here's the code I have so far. When the Arduino is reset it prints 315 to the serial over a 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 = 441
Counted = 442
Counted = 441
Counted = 441
Counted = 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. Here's what it looks like.

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);
}

void IRQcounter() {
   IRQcount++;
}

void loop() {
  // Put your main code here, to run repeatedly:

  attachInterrupt(pin_irq, IRQcounter, RISING);
  delay(25);
  detachInterrupt(pin);
  Serial.print(F("Counted = "));
  Serial.println(IRQcount);
}

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 = 886
Counted = 1330
Counted = 177
Counted = 2221
Counted = 2667
Counted = 3112
Counted = 3557
Counted = 4002
Counted = 4448
Counted = 4893
Counted = 5338
Counted = 5784
Counted = 6229
Counted = 6674
Counted = 7120
Counted = 7565
Counted = 8010
Counted = 8456
Counted = 8901
Counted = 9347
Counted = 9792
Counted = 10237
Counted = 10683
Counted = 11130
Counted = 11576
Counted = 12022
Counted = 12469
Counted = 12915
Counted = 13361
Counted = 13808
Counted = 14254
Counted = 14700
Counted = 15147
Counted = 15593
Counted = 16040
Counted = 16486
Counted = 16932
Counted = 17378
Counted = 17825
Counted = 18271
Counted = 18717
Counted = 19164
Counted = 19610
Counted = 20056
Counted = 20503
Counted = 20949
Counted = 21395
Counted = 21842
Counted = 22288
Counted = 22735
Counted = 23169
Counted = 23616
Counted = 24062
Counted = 24508
Counted = 24955
Counted = 25401
Counted = 25730
Counted = 25756
Counted = 26200
Counted = 26646
Counted = 27093
Counted = 27539
Counted = 27985
Counted = 28432
Counted = 28878
Counted = 29324
Counted = 29770
Counted = 30217
Counted = 30663
Counted = 31110
Counted = 31556
Counted = 32002
Counted = 32449
Counted = -32641
Counted = -32195
Counted = -31748
Counted = -31302
Counted = -30855
Counted = -30408
Counted = -29962
Counted = -29515
Counted = -29069
Counted = -28622
2
  • "Now if i move that same code down into void loop it counts consecutively giving me inconstant returns." means what exactly? Oct 4, 2014 at 15:39
  • I edited my question to try and better explain myself Oct 4, 2014 at 16:11

1 Answer 1

9

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);
}
6
  • 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, Oct 4, 2014 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! Oct 4, 2014 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, 2014 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! Oct 6, 2014 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, 2014 at 17:41

Not the answer you're looking for? Browse other questions tagged or ask your own question.