Підрахунок імпульсів з перериванням


10

Я намагався рахувати імпульси від квадратної хвилі 12 500 Гц, щоб викликати вихід. Ось код у мене поки що. Коли ардуїно скидається, він надруковує 315 в серіалі протягом 25 мс-зразка. 315 x 40 = 12600. Мені здається, він працює чудово.

Моя єдина проблема полягає в тому, що це число повертається лише один раз після скидання плати. Тепер, якщо я переміщу той самий код вниз void loop, він рахує послідовно, даючи мені непостійні повернення.

Я не розумію, що мені потрібно помістити в розділ циклу, щоб я міг неодноразово і точно рахувати, скільки перемикань вхідного штифта я отримую за певний проміжок часу, щоб я міг зробити щось на виході, виходячи з присутності 12 500 Гц сигнал чи ні.

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 Гц, так що, і тільки це, спровокує мій вихід.

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

"Тепер, якщо я переміщу цей самий код внизу в недійсний цикл, він рахується послідовно, даючи мені непостійні повернення." означає що саме?
Ігнасіо Васкес-Абрамс

Я відредагував своє запитання, щоб спробувати краще пояснити себе
Брендон Уосвілль

Відповіді:


9

Вам потрібно відновити IRQCount назад до 0того, як знову приєднати переривання. Інакше він просто продовжить рахувати з того місця, де він зупинився минулого разу.

Я б фактично зберігав переривання приєднаним і просто скинув змінну безпосередньо перед затримкою. Таким чином, накладні витрати на приєднання / відключення переривання не додаються до затримки 25 мс.

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,
Брендон Уесвілл

1
Я подовжив затримку для отримання більшого розміру вибірки. Це дає мені справну віддачу від мого шумного джерела введення. Це, здається, працює ідеально! Дякую!
Брендон Уосвіл

Я припускаю, що ви використовували код з clis і seis в ньому. Досить дивно мати два послідовні помилкові значення.
Гербен

1
Гербен, так, я використав код із cli та sei в ньому. Ви маєте на увазі його дивне отримання двох неправильних повернень поспіль? Здається, повернення є правильним, це вхідний сигнал, який не є стабільним і дає непотрібні прибутки. Якщо я пробую, скажімо, 100 мс, це дає багато імпульсів на зразок, щоб безпечно активувати або вбити ланцюг. Я дуже ціную вашу допомогу!
Брендон Уосвіл

Але отримані вами 48 і 318 є нижчими, ніж в середньому близько 435. Я не знаю підключеної схеми, тому це може бути так само добре, як замість коду arduino. У будь-якому випадку, поки ви задоволені кінцевим результатом ... Радий, що допомогли.
Гербен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.