割り込みによるパルスのカウント


10

12,500 Hzの方形波からのパルスをカウントして出力をトリガーしようとしています。ここに私がこれまでに持っているコードがあります。Arduinoがリセットされると、25 msのサンプルで315がシリアルに出力されます。315 x 40 =12600。これは完璧に機能しているように思えます。

私の唯一の問題は、ボードのリセット時に一度だけこの番号を返すことです。同じコードをに移動するとvoid loop、連続してカウントされ、一定しない戻り値が返されます。

ループセクションに何を入れる必要があるのか​​理解していないので、一定期間を超えて取得している入力ピンのトグルの数を繰り返し正確にカウントできるため、12,500の存在に基づいて出力に何かを行うことができますHz信号かどうか。

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

上記のコードを使用して、リセットボタンを押すたびに、シリアルウィンドウに1行表示されます。

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

同じ結果を得たいのですが、何度も繰り返します。そうすれば、信号が途切れた場合に出力をトリガーしてオフ(LOW)にすることができます。信号が存在する場合、出力はハイになります。

私の試みは、アタッチ割り込みをに移動することでしたvoid loopので、繰り返されます。これは次のようになります。

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

私が得るリターンは自己更新ですが、毎回0から開始するのではなく、「カウント」は前のカウントから開始します。そのため、どんどん大きくなります。12500 Hzの信号を表す定数値を返して、出力がトリガーされるようにしています。

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

「同じコードをvoidループに移動すると、連続してカウントされ、一定しない戻り値が返されます。」正確にはどういう意味ですか?
Ignacio Vazquez-Abrams

私は自分の質問を編集して自分自身をよりよく説明しようとしました
Brandon Whosville 2014年

回答:


9

0割り込みを再度アタッチする前に、IRQCountをリセットする必要があります。それ以外の場合は、前回停止したところから数え続けます。

実際には割り込みを接続したままにし、遅延の直前に変数をリセットします。このようにして、アタッチ/デタッチ割り込みのオーバーヘッドが25ミリ秒の遅延に追加されません。

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

intは2バイトなので、これらの2バイトの設定/読み取りの途中で割り込みが発生する可能性があります。これにより、誤った値が発生する場合があります。値の設定/読み取り中に割り込みを無効にする必要があることを防ぐには

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

ガーベン、ありがとう!そのコードを使用して、時々ジャンクが返ってきます。これを非難する最も簡単な方法は何でしょうか?アウトテイクを行うには、何をすべきかを決定する前に、3つの測定値を言います。または、生カウントの代わりにスパン全体のパルスを平均化しますか?戻りの例を次に示します。数秒ごとに異常が発生します。カウント= 439、カウント= 438、カウント= 430、カウント= 48、カウント= 318、カウント= 438、
Brandon Whosville

1
サンプルサイズを大きくするために遅延を長くしました。これにより、ノイズの多い入力ソースから適切に復帰できます。これは完璧に動作するようです!ありがとうございました!
Brandon Whosville 2014年

clisとseisを含むコードを使用したと思います。2つの連続する誤った値を持っているというかなり奇妙なこと。
Gerben 2014年

1
Gerben、はい、私はcliとseiを含むコードを使用しました。2つの間違ったリターンを続けて取得するのは奇妙なことですか?リターンは正しいようです、それはジャンクリターンを与える安定していない入力信号です。私がサンプリングを100msとすると、サンプルごとに十分なパルスが発生し、回路を安全にアクティブ化または強制終了します。本当にありがとうございます!
Brandon Whosville 2014年

しかし、あなたが手に入れた48と318はどちらも平均の約435よりも低くなっています。接続されている回路がわからないので、arduinoコードではなく、回路である可能性もあります。とにかく、あなたが最終結果に満足している限り...助けてくれてうれしいです。
Gerben 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.