Тон внутри прерывания
Я пытаюсь воспроизвести звук с помощью зуммера, подключенного к контакту arduino nano. Я также подключил геркон с INPUT_PULLUP на INT0 и светодиод. Программа непрерывно зацикливается (это персональный проект мониторинга окружающей среды и сигнализации), пока язычковый переключатель не будет установлен в положение ВЫСОКИЙ, когда вызывается функция, и зуммер должен воспроизводить односекундный сигнал высокого тона.
void doorStateChange() {
static unsigned long last_interrupt_time = 0;
unsigned long interrupt_time = millis();
if (interrupt_time - last_interrupt_time > 1000)
{
led_B_state = !led_B_state;
digitalWrite(buzzPin, HIGH);
digitalWrite(led_A_Pin, HIGH);
if (millis() - interrupt_time <= 1000 ){
digitalWrite(buzzPin, LOW);
digitalWrite(led_A_Pin, LOW);
}
}
last_interrupt_time = interrupt_time;
}
Вызывается прерывание, загорается светодиод, но я не могу правильно настроить зуммер. Я пробовал с tone(buzzPin, 5000, 1000);
, но кажется, что задержка не работает - звук слышен, но после 1000 мс он продолжает работать в другом тоне (странно?) .
Единственный способ, с помощью которого я мог заставить это работать, — это использовать buzzPin_state = ! buzzPin_state;
где зуммер издает звуковой сигнал, пока геркон находится в ВЫСОКОМ положении.
Я также должен сказать, что attachInterrupt(0, doorStateChange, CHANGE);
.
Информация, которую я получаю при поиске в Google по этому вопросу, является тарабарщиной: некоторые говорят, что задержки не выполняются в прерываниях, другие вызывают внешние функции и т. д.
Каков правильный способ добиться этого?
@Radolino, 👍0
Обсуждение1 ответ
Не выполняйте вызовы delay() внутри ISR. По всей вероятности, он будет висеть бесконечно. Если вы хотите воспроизвести тон на секунду, все, что вам нужно сделать в ISR, это установить флаг, который вы проверяете в основном цикле. Включите зуммер, когда флаг изменит свое состояние. Вспомни, когда ты это сделал. По истечении секунды снова выключите зуммер.
На самом деле в вашем случае вам, вероятно, вообще не нужно прерывание. Также проверьте изменение геркона в основном контуре. Не усложняйте.
- Использование millis() и micros() внутри процедуры прерывания
- Подсчет импульсов с прерыванием
- Устранение дребезга кнопки с помощью прерывания
- Программа arduino выдаёт ошибку expected //primary-expression before ')' token error: //expected ';' before '}' token E
- Почему необходимо использовать ключевое слово volatile для глобальных переменных при обработке прерываний в ардуино?
- Как сгенерировать аппаратное прерывание в mpu6050 для пробуждения Arduino из режима SLEEP_MODE_PWR_DOWN?
- Использование поворотных энкодеров с прерываниями смены контактов
- Arduino непрерывно считывает значение АЦП с помощью прерывания
Можете ли вы дать более подробное описание того, что вы ожидаете и что происходит с этим кодом? Вы просто хотите подтянуть контакт зуммера к высокому нарастающему фронту (когда входной контакт переходит от низкого к высокому)?, @Anonymous Penguin
Я хочу перевести зуммер в положение «ИЗМЕНЕНИЕ» на одну секунду., @Radolino
Но тогда вам не нужен
tone()
, верно? (Подъем/изменение/падение в данном случае не имеют значения), @Anonymous PenguinЯ хотел услышать высокий тон, а не зуммер (звуковой сигнал) по умолчанию., @Radolino
Но дело не только в этом. Я не могу заставить его задержать тон на одну секунду. Это работает только в том случае, если состояние изменяется внутри функции прерывания, что означает, что звук длится столько, сколько на выводе геркона находится высокий уровень., @Radolino
Возможно, вам потребуется разрешить прерывания внутри функции. Попробуйте поместить
sei();
в начале функции., @GerbenФункция tone() инициализирует ШИМ на частоте и определяет количество переключателей, соответствующее желаемой длине. Наряду с инициализацией прерывания захвата вывода, чтобы оно совпадало с каждым переключением ШИМ. Где ISR PWM уменьшает этот счетчик. Следовательно, нахождение внутри другого ISR предотвратит ISR OCI (или PWM). Предложение Гербена о SEI() поможет. Но вы действительно должны написать ISR() или функции, вызываемые AttachInterrupt(), чтобы они не были ДЛИННЫМИ или блокирующими. ISR должны быть быстрыми., @mpflaga
@mpflaga хорошо понял, но я начинаю думать, что весь дизайн этой функции неверен., @Radolino