Contando pulsos com interrupção


10

Eu tenho tentado contar pulsos de uma onda quadrada de 12.500 Hz para disparar uma saída. Aqui está o código que tenho até agora. Quando o Arduino é redefinido, ele imprime 315 na serial em uma amostra de 25 ms. 315 x 40 = 12600. O que me parece que está funcionando perfeitamente.

Meu único problema é que ele retorna esse número apenas uma vez após a redefinição do quadro. Agora, se eu mover esse mesmo código para baixo void loop, ele conta consecutivamente, dando-me retornos inconstantes.

Não estou entendendo o que preciso colocar na seção do loop para poder contar repetidamente e com precisão quantas alternâncias do pino de entrada estou obtendo ao longo de um período de tempo para poder fazer algo na saída com base na presença dos 12.500 Sinal de Hz ou não.

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 o código acima, toda vez que pressiono o botão de reset, recebo uma linha na janela serial.

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

Agora eu quero obter o mesmo resultado, mas repetindo várias vezes. Dessa forma, se o sinal cair, posso acionar uma saída para desligar (LOW). Quando o sinal estiver presente, a saída será alta.

Minha tentativa foi mover a interrupção do anexo para dentro void loop, para repetir. Aqui está o que parece.

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

O retorno que recebo é atualizado automaticamente, mas a "contagem", em vez de começar de 0, sempre começa na contagem anterior. Então fica cada vez maior. Estou procurando retornar um valor constante que represente meu sinal de 12500 Hz para que, e somente isso, ative minha saída.

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

"Agora, se eu mover o mesmo código para o loop vazio, ele conta consecutivamente, dando-me retornos inconstantes." significa o que exatamente?
Ignacio Vazquez-Abrams

Eu editei a minha pergunta para tentar explicar melhor a mim mesmo
Brandon Whosville

Respostas:


9

Você precisa redefinir o IRQCount para 0antes de anexar a interrupção novamente. Caso contrário, ele continuará contando de onde parou da última vez.

Na verdade, eu manteria a interrupção anexada e redefiniria a variável imediatamente antes do atraso. Dessa forma, a sobrecarga da conexão / desconexão não é adicionada ao atraso de 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);
}

Como int é 2 bytes, pode ocorrer uma interrupção no meio da configuração / leitura desses dois bytes. Isso pode resultar em um valor errado ocasional. Para impedir que você desative a interrupção ao definir / ler o 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);
}

Obrigado Gerben! Usando esse código, recebo o retorno de lixo ocasional. Qual seria a maneira mais fácil de denunciar isso? Faça uma tomada, digamos 3 leituras antes de tomar uma decisão sobre o que fazer. Ou calcular a média de pulsos ao longo de um intervalo, em vez de uma contagem bruta? Heres um exemplo do retorno, eu recebo a anomalia a cada poucos segundos. Contado = 439, Contado = 438, Contado = 430, Contado = 48, Contado = 318, Contado = 438,
Brandon Whosville

11
Aumentei o atraso para obter um tamanho de amostra maior. Isso me dá um retorno viável da minha fonte de entrada barulhenta. Isso parece funcionar perfeito! Obrigado!
Brandon Whosville

Eu suponho que você usou o código com os clies seinele. Bastante estranho ter dois valores errados consecutivos.
Gerben 5/10

11
Gerben, Sim, eu usei o código com o cli e o sei nele. Você quer dizer que é estranho obter os dois retornos errados seguidos? Parece que os retornos estão corretos, é o sinal recebido que não é estável, dando retornos indesejados. Se eu amostrar mais, digamos 100ms, ele fornece muitos pulsos por amostra para ativar ou eliminar com segurança o circuito. Eu realmente aprecio sua ajuda!
Brandon Whosville

Mas os 48 e 318 que você obteve são ambos inferiores à média de cerca de 435. Eu não conheço o circuito conectado, então poderia ser o circuito, e não o código do arduino. De qualquer forma, contanto que você esteja feliz com o resultado final ... Fico feliz em ter ajudado.
Gerben
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.