Impulse mit Interrupt zählen

10

Ich habe versucht, Impulse von einer Rechteckwelle mit 12.500 Hz zu zählen, um einen Ausgang auszulösen. Hier ist der Code, den ich bisher habe. Wenn der Arduino zurückgesetzt wird, druckt er 315 über ein 25-ms-Sample auf die Seriennummer. 315 x 40 = 12600. Was mir scheint, es funktioniert perfekt.

Mein einziges Problem ist, dass diese Nummer beim Zurücksetzen der Karte nur einmal zurückgegeben wird. Wenn ich jetzt denselben Code nach unten verschiebe void loop, zählt dies nacheinander und gibt mir unbeständige Renditen.

Ich verstehe nicht, was ich in den Loop-Bereich einfügen muss, damit ich wiederholt und genau zählen kann, wie viele Umschaltungen des Eingangspins ich über einen bestimmten Zeitraum erhalte, damit ich basierend auf dem Vorhandensein der 12.500 etwas mit dem Ausgang tun kann Hz-Signal oder nicht.

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

Mit dem obigen Code wird jedes Mal, wenn ich die Reset-Taste drücke, eine Zeile im seriellen Fenster angezeigt.

Counted = 441
Counted = 442
Counted = 441
Counted = 441
Counted = 441

Jetzt möchte ich das gleiche Ergebnis erzielen, aber immer wieder wiederholen. Auf diese Weise kann ich, wenn das Signal abfällt, einen Ausgang zum Ausschalten auslösen (LOW). Wenn das Signal vorhanden ist, geht der Ausgang hoch.

Mein Versuch war, den Attach-Interrupt nach unten zu verschieben void loop, damit er sich wiederholt. So sieht es aus.

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

Die Rückgabe, die ich erhalte, wird automatisch aktualisiert, aber die "Zählung" beginnt nicht jedes Mal bei 0, sondern bei der vorherigen Zählung. So wird es immer größer. Ich möchte einen konstanten Wert zurückgeben, der mein 12500-Hz-Signal darstellt, damit und nur dieser meinen Ausgang auslöst.

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
Brandon Whosville
quelle
"Wenn ich jetzt denselben Code in die Void-Schleife verschiebe, zählt er nacheinander und gibt mir unbeständige Renditen." bedeutet was genau?
Ignacio Vazquez-Abrams
Ich habe meine Frage bearbeitet, um mich besser zu erklären
Brandon Whosville

Antworten:

9

Sie müssen IRQCount zurücksetzen, 0bevor Sie den Interrupt erneut anhängen. Andernfalls wird nur an der Stelle weiter gezählt, an der es beim letzten Mal angehalten hat.

Ich würde den Interrupt tatsächlich angeschlossen lassen und die Variable kurz vor der Verzögerung zurücksetzen. Auf diese Weise wird der Overhead von Attach / Detachinterrupt nicht zur Verzögerung von 25 ms addiert.

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

Da ein int 2 Bytes beträgt, kann während des Einstellens / Lesens dieser beiden Bytes ein Interrupt auftreten. Dies kann gelegentlich zu einem falschen Wert führen. Um dies zu verhindern, sollten Sie den Interrupt deaktivieren, während Sie den Wert einstellen / lesen

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);
}
Gerben
quelle
Danke Gerben! Mit diesem Code bekomme ich gelegentlich Junk Return. Was wäre der einfachste Weg, dies anzuprangern? Nehmen Sie eine Messung vor, bevor Sie eine Entscheidung treffen, was zu tun ist. Oder Mittelung von Impulsen über eine Spanne anstelle einer Rohzählung? Hier ist ein Beispiel für die Rückkehr, ich bekomme die Anomalie alle paar Sekunden. Gezählt = 439, gezählt = 438, gezählt = 430, gezählt = 48, gezählt = 318, gezählt = 438,
Brandon Whosville
1
Ich habe die Verzögerung verlängert, um eine größere Stichprobe zu erhalten. Dies gibt mir eine brauchbare Rückkehr von meiner verrauschten Eingangsquelle. Das scheint perfekt zu funktionieren! Danke!
Brandon Whosville
Ich gehe davon aus, dass Sie den Code mit den clis und seis verwendet haben. Ziemlich seltsam, zwei aufeinanderfolgende falsche Werte zu haben.
Gerben
1
Gerben, ja ich habe den code mit dem cli und sei drin benutzt. Meinst du, es ist seltsam, die zwei falschen Renditen hintereinander zu bekommen? Es scheint, dass die Renditen korrekt sind. Es ist das eingehende Signal, das nicht stabil ist und Junk-Renditen liefert. Wenn ich über 100 ms sample, gibt es viele Impulse pro Sample, um die Schaltung sicher zu aktivieren oder zu beenden. Ich schätze deine Hilfe sehr!
Brandon Whosville
Aber die 48 und 318, die Sie haben, sind beide niedriger als der Durchschnitt von ungefähr 435. Ich kenne die angeschlossene Schaltung nicht, also könnte es genauso gut die Schaltung sein, anstelle des Arduino-Codes. Wie auch immer, solange Sie mit dem Endergebnis zufrieden sind ... Ich bin froh, geholfen zu haben.
Gerben