Contando pulsos con interrupción


10

He estado tratando de contar pulsos de una onda cuadrada de 12,500 Hz para activar una salida. Aquí está el código que tengo hasta ahora. Cuando se reinicia el Arduino, imprime 315 en la serie en una muestra de 25 ms. 315 x 40 = 12600. Lo que me parece que funciona perfectamente.

Mi único problema es que solo devuelve este número una vez al reiniciar el tablero. Ahora, si muevo ese mismo código hacia abajo void loop, cuenta consecutivamente y me da retornos inconstantes.

No entiendo lo que necesito poner en la sección de bucle para poder contar de forma repetida y precisa cuántas palancas del pin de entrada obtengo durante un período de tiempo para poder hacer algo en la salida en función de la presencia de los 12,500 Señal de Hz o no.

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

Usando el código anterior, cada vez que presiono el botón de reinicio obtengo una línea en la ventana serial.

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

Ahora quiero obtener el mismo resultado, pero repetir una y otra vez. De esa manera, si la señal se cae, puedo activar una salida para que se apague (BAJA). Cuando la señal está presente, la salida será alta.

Mi intento fue mover la interrupción de conexión hacia abajo void loop, para que se repita. Así es como se ve.

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

El retorno que obtengo se actualiza automáticamente, pero el "conteo" en lugar de comenzar desde 0 cada vez comienza desde el conteo anterior. Entonces se hace más y más grande. Estoy buscando devolver un valor constante que represente mi señal de 12500 Hz para que, y solo eso, active mi salida.

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

"Ahora, si muevo ese mismo código al bucle de vacío, cuenta de forma consecutiva y me da resultados inconstantes". ¿Qué significa exactamente?
Ignacio Vazquez-Abrams

Edité mi pregunta para tratar de explicarme mejor
Brandon Whosville

Respuestas:


9

Debe restablecer IRQCount nuevamente 0antes de volver a conectar la interrupción. De lo contrario, continuará contando desde donde se detuvo la última vez.

De hecho, mantendría la interrupción conectada y simplemente restablecería la variable justo antes del retraso. De esa forma, la sobrecarga de la interrupción de conexión / desconexión no se agrega al retraso de 25 ms.

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

Como un int es de 2 bytes, puede ocurrir una interrupción en el medio de configurar / leer esos dos bytes. Esto podría ocasionar un valor incorrecto ocasional. Para evitarlo, debe desactivar la interrupción mientras configura / lee el valor

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

Gracias Gerben! Usando ese código obtengo el retorno ocasional de basura. ¿Cuál sería la forma más fácil de denunciar esto? Haga una toma, digamos 3 lecturas antes de tomar una decisión sobre qué hacer. ¿O promediar pulsos en un lapso en lugar de un recuento bruto? Aquí hay un ejemplo del retorno, me sale la anomalía cada pocos segundos. Contada = 439, Contada = 438, Contada = 430, Contada = 48, Contada = 318, Contada = 438,
Brandon Whosville

1
Alargué el retraso para dar un tamaño de muestra más grande. Esto me da un retorno viable de mi fuente de entrada ruidosa. ¡Esto parece funcionar perfecto! ¡Gracias!
Brandon Whosville

Supongo que usaste el código con los clis y seis en él. Más bien extraño tener dos valores incorrectos consecutivos.
Gerben

1
Gerben, sí, usé el código con el cli y el sei. ¿Quieres decir que es extraño obtener los dos retornos incorrectos seguidos? Parece que los retornos son correctos, es la señal entrante que no es estable dando retornos basura. Si tomo muestras, digamos 100 ms, da muchos pulsos por muestra para activar o matar el circuito de manera segura. ¡Realmente aprecio tu ayuda!
Brandon Whosville

Pero los 48 y 318 que obtuviste son más bajos que el promedio de aproximadamente 435. No conozco el circuito conectado, por lo que podría ser el circuito, en lugar del código arduino. De todos modos, siempre y cuando estés satisfecho con el resultado final ... Me alegro de haber ayudado.
Gerben
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.