인터럽트로 펄스 카운팅


10

12,500Hz 구형파에서 펄스를 계산하여 출력을 트리거하려고했습니다. 여기까지 내가 가진 코드가 있습니다. Arduino가 재설정되면 25ms 샘플에서 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

이제 동일한 결과를 원하지만 반복해서 반복하고 싶습니다. 그렇게하면 신호가 끊어지면 출력을 끌 수 있습니다 (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에서 시작하는 대신 "count"는 이전 카운트에서 시작합니다. 그래서 점점 커집니다. 12500Hz 신호를 나타내는 상수 값을 반환하여 출력 만 트리거하도록하려고합니다.

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

나는 나 자신을 시도하고 더 나은 설명 내 질문에 편집
브랜든 Whosville에게

답변:


9

0인터럽트를 다시 연결 하기 전에 IRQCount를 다시 설정해야 합니다. 그렇지 않으면 마지막으로 멈춘 지점부터 계속 계산됩니다.

실제로 인터럽트를 첨부하고 지연 직전에 변수를 재설정합니다. 이렇게하면 연결 / 분리 인터럽트의 오버 헤드가 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 바이트이므로이 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);
}

감사합니다 Gerben! 그 코드를 사용하여 가끔 정크 반환을 얻습니다. 이것을 비난하는 가장 쉬운 방법은 무엇입니까? 무엇을해야할지 결정하기 전에 3 번 읽습니다. 아니면 원시 카운트 대신 스팬에 대한 평균 펄스입니까? 여기에 반환의 예가 있습니다. 몇 초마다 이상이 발생합니다. = 438 계산 = 318 계산 = 48을 계산 = 430 계산 = 438 계산 계산 = 439,,,,,,
브랜든 Whosville

1
더 큰 샘플 크기를 제공하기 위해 지연 시간을 연장했습니다. 이것은 시끄러운 입력 소스에서 실행 가능한 리턴을 제공합니다. 이것은 완벽하게 작동하는 것 같습니다! 감사합니다!
Brandon Whosville 16

코드에 clis와 seis를 사용했다고 가정 합니다. 두 개의 연속적인 잘못된 값을 갖는 것이 이상합니다.
Gerben

1
Gerben, 예, cli 및 sei와 함께 코드를 사용했습니다. 두 개의 잘못된 수익을 연속으로 얻는 것이 이상하다는 의미입니까? 그것은 반환이 올바른 것 같습니다, 그것은 정크 반환을 제공하는 안정적이지 않은 들어오는 신호입니다. 만약 내가 샘플을 100ms라고한다면, 샘플 당 많은 펄스를 제공하여 회로를 안전하게 활성화 시키거나 죽일 수 있습니다. 도와 주셔서 감사합니다!
Brandon Whosville

그러나 48과 318은 둘 다 평균 약 435보다 낮습니다. 연결된 회로를 알지 못하므로 arduino 코드 대신 회로 일 수도 있습니다. 어쨌든, 최종 결과에 만족하는 한 ... 기꺼이 도와 드리겠습니다.
Gerben
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.