Conteggio degli impulsi con interruzione


10

Ho cercato di contare gli impulsi da un'onda quadra da 12.500 Hz per attivare un'uscita. Ecco il codice che ho finora. Quando viene ripristinato, Arduino stampa 315 sul seriale su un campione di 25 ms. 315 x 40 = 12600. Mi sembra che funzioni perfettamente.

Il mio unico problema è che restituisce questo numero solo una volta al reset della scheda. Ora, se sposto lo stesso codice in giù void loop, conta contante dandomi rendimenti incostanti.

Non capisco cosa devo inserire nella sezione loop in modo da poter contare ripetutamente e accuratamente quanti toggles del pin di input sto ottenendo in un periodo di tempo in modo da poter fare qualcosa all'output in base alla presenza del 12.500 Segnale 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 il codice sopra, ogni volta che premo il pulsante di ripristino ottengo una riga nella finestra seriale.

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

Ora voglio ottenere lo stesso risultato, ma ripetendo ancora e ancora. In questo modo, se il segnale si interrompe, posso attivare l'uscita (LOW). Quando è presente il segnale, l'uscita aumenterà.

Il mio tentativo era di spostare in basso l'interrupt di collegamento void loop, quindi si sarebbe ripetuto. Ecco come appare.

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

Il ritorno che ottengo è auto-aggiornamento, ma il "conteggio" invece di partire da 0 ogni volta inizia dal conteggio precedente. Quindi diventa sempre più grande. Sto cercando di restituire un valore costante che rappresenta il mio segnale a 12500 Hz in modo che, e solo quello, attiverà la mia uscita.

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

"Ora, se sposto lo stesso codice in un ciclo vuoto, conta in modo consecutivo dandomi rendimenti incostanti." cosa significa esattamente?
Ignacio Vazquez-Abrams,

Ho modificato la mia domanda per cercare di spiegarmi meglio
Brandon Whosville,

Risposte:


9

È necessario ripristinare IRQCount 0prima di ricollegare l'interrupt. Altrimenti continuerà a contare da dove si è fermata l'ultima volta.

Vorrei effettivamente mantenere l'interrupt collegato e ripristinare la variabile appena prima del ritardo. In questo modo l'overhead di attach / detachinterrupt non viene aggiunto al ritardo di 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);
}

Poiché un int è di 2 byte, potrebbe verificarsi un interruzione durante l'impostazione / lettura di questi due byte. Ciò potrebbe comportare un valore errato occasionale. Per evitare che sia necessario disabilitare l'interrupt durante l'impostazione / lettura del valore

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

Grazie Gerben! Usando quel codice ottengo il ritorno indesiderato occasionale. Quale sarebbe il modo più semplice per denunciarlo? Fai un take out diciamo 3 letture prima di prendere una decisione su cosa fare. O la media degli impulsi su un arco invece di un conteggio grezzo? Ecco un esempio del ritorno, ricevo l'anomalia ogni pochi secondi. Contato = 439, Contato = 438, Contato = 430, Contato = 48, Contato = 318, Contato = 438,
Brandon Whosville

1
Ho allungato il ritardo per dare una dimensione del campione maggiore. Questo mi dà un ritorno realizzabile dalla mia fonte di input rumorosa. Questo sembra funzionare perfettamente! Grazie!
Brandon Whosville,

Presumo che tu abbia usato il codice con la clis e la seis dentro. Piuttosto strano avere due valori consecutivi sbagliati.
Gerben,

1
Gerben, Sì, ho usato il codice con il cli e sei in esso. Vuoi dire che è strano ottenere i due ritorni sbagliati di seguito? Sembra che i ritorni siano corretti, è il segnale in entrata che non è stabile dando rendimenti spazzatura. Se eseguo il campionamento, diciamo 100ms, fornisce molti impulsi per campione per attivare o uccidere in sicurezza il circuito. Apprezzo molto il vostro aiuto!
Brandon Whosville,

Ma i 48 e 318 ottenuti sono entrambi inferiori alla media di circa 435. Non conosco il circuito collegato, quindi potrebbe anche essere il circuito, invece del codice arduino. Comunque, purché tu sia felice del risultato finale ... Sono contento di averti aiutato.
Gerben,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.