Поведение tone() не соответствует ожидаемому в цикле while
У меня есть детектор дыма с пьезоизлучателем. Я хочу использовать Arduino в режиме пониженного энергопотребления, чтобы он работал от батареи 9 В. Я подключил прерывание, и когда цифровой выход датчика MQ-2 становится высоким, он переключается на функцию мониторинга.
В цикле while я проверяю, достиг ли аналоговый датчик порогового значения, и вывожу в последовательный порт, чтобы убедиться, что я нахожусь в условном выражении. Если я использую:
digitalWrite(buzzer, HIGH);
затем звучит пьезо, но если я использую
tone(buzzer, 1000,200);
delay(200);
это не так. Я не понимаю, почему это так.
Полный код выглядит следующим образом:
#include "LowPower.h"
int redLed = 12;
int greenLed = 11;
int buzzer = 10;
int smokeA0 = A5;
// Ваше пороговое значение
int sensorThres = 50;
int smokeD0 = 2;
void setup() {
pinMode(redLed, OUTPUT);
digitalWrite(redLed, LOW);
pinMode(greenLed, OUTPUT);
digitalWrite(greenLed, HIGH);
pinMode(buzzer, OUTPUT);
pinMode(smokeA0, INPUT);
pinMode(smokeD0, INPUT);
}
void switchToMonitor() {
Serial.begin(9600);
int digitalSensor = digitalRead(smokeD0);
if (digitalRead(smokeD0) == HIGH)
{
digitalWrite(redLed, HIGH);
digitalWrite(greenLed, LOW);
}
else {
digitalWrite(redLed, LOW);
digitalWrite(greenLed, HIGH);
}
//Это будет обновлено позже, чтобы использовать аналоговый вход
// Использование цифровых технологий для облегчения отладки
while (digitalSensor == HIGH) {
int analogSensor = analogRead(smokeA0);
Serial.print("Pin A0: ");
Serial.println(analogSensor);
Serial.print("Pin D0: ");
Serial.println(digitalSensor);
// Проверяем, достиг ли он порогового значения
if (analogSensor > sensorThres) {
digitalWrite(buzzer, HIGH);
// тон (зуммер, 1000,200);
Serial.println("here");
delay(1000);
}
else {
// digitalWrite(redLed, LOW);
// digitalWrite(greenLed, HIGH);
noTone(buzzer);
Serial.println("also here?");
}
// задержка (100);
digitalSensor = digitalRead(smokeD0);
}
noTone(buzzer);
}
void loop() {
// задержка (100);
//Низкая мощность.ожидание();
attachInterrupt(0, switchToMonitor, CHANGE);
LowPower.powerDown(SLEEP_FOREVER, ADC_ON, BOD_ON);
detachInterrupt(0);
}
@David Bekker, 👍0
Обсуждение1 ответ
Лучший ответ:
Вы не можете использовать функцию delay() или функцию tone() на основе таймера в обработчике прерывания. Установите флаг в прерывании и запустите код в цикле () условно на основе состояния флага. Не забудьте сделать переменную флага volatile.
Вынул из обработчика прерываний и все заработало. Спасибо, @David Bekker
- Использование millis() и micros() внутри процедуры прерывания
- Подсчет импульсов с прерыванием
- Устранение дребезга кнопки с помощью прерывания
- Программа arduino выдаёт ошибку expected //primary-expression before ')' token error: //expected ';' before '}' token E
- Почему необходимо использовать ключевое слово volatile для глобальных переменных при обработке прерываний в ардуино?
- Как сгенерировать аппаратное прерывание в mpu6050 для пробуждения Arduino из режима SLEEP_MODE_PWR_DOWN?
- Использование поворотных энкодеров с прерываниями смены контактов
- Arduino непрерывно считывает значение АЦП с помощью прерывания
@Juraj Функция тона работает, когда используется в цикле void() и не переключается между режимом малой мощности и режимом работы. Это не работает только в приведенном примере кода, @David Bekker
подключите зуммер к аккумулятору... он издает звук?, @jsotola