中断计数脉冲


10

我一直在尝试计算来自12,500 Hz方波的脉冲以触发输出。这是我到目前为止的代码。重置Arduino后,它将在25毫秒的样本中将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:
}

使用上面的代码,每当我按下重置按钮时,我在串行窗口中就会得到一行。

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

现在,我想获得相同的结果,但是要重复一遍又一遍。这样,如果信号丢失,我可以触发输出以关闭(低)。存在信号时,输出将为高电平。

我的尝试是将附加中断向下移动到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循环中,它会连续计数,从而给我带来不固定的回报。” 到底是什么意思?
伊格纳西奥·巴斯克斯

我编辑我的问题,试图更好地解释自己
布兰登Whosville

Answers:


9

您需要将IRQCount重置为0再次连接中断之前。否则,它将仅从上次停止的位置继续计数。

我实际上会保留中断,只是在延迟之前重置变量。这样,attach / detachinterrupt的开销不会增加到25ms的延迟中。

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个字节,因此在设置/读取这两个字节的过程中可能会发生中断。这可能会导致偶尔出现错误的值。为防止在设置/读取值时应禁用中断

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,
布兰登·沃斯维尔2014年

1
我延长了延迟,以提供更大的样本量。这使我从嘈杂的输入源中得到了可行的回报。这似乎工作完美!谢谢!
Brandon Whosville 2014年

我假设您在代码中使用了clis和seis。具有两个连续的错误值,这很奇怪。
Gerben 2014年

1
Gerben,是的,我在cli和sei中使用了代码。您是不是很奇怪连续得到两次错误的回报?看来回报是正确的,只是传入的信号不稳定,给垃圾回报。如果我采样超过100ms,则每个采样都会产生大量脉冲,以安全地激活或终止电路。非常感谢您的帮助!
Brandon Whosville 2014年

但是,您得到的48和318均低于约435的平均值。我不知道连接的电路,因此也可能是电路,而不是arduino代码。无论如何,只要您对最终结果感到满意...很高兴为您提供帮助。
Gerben 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.