Arduino с прерываниями переходит в состояние блокировки
Я совершенно не разбираюсь в использовании прерываний на Arduino, и я столкнулся со странной проблемой. Я использую Arduino Pro Mini, датчик освещенности и модуль RTC (DS3231), который установил 2 будильника, один на восходе солнца и один на закате. Каждый раз, когда DST запускает сигнал тревоги, процедура прерывания (здесь onAlarm() ) блокирует состояние Arduino, и там ничего не происходит. Есть ли что-то неправильное в коде, который я пишу?
Приведенный ниже код немного упрощен, я просто разрешаю вызовы методов, а не их полные объявления.
#include <avr/sleep.h>//эта библиотека AVR содержит методы, управляющие режимами ожидания
#include <avr/power.h>
#include <DS3232RTC.h> //Библиотеку RTC https://github.com/JChristensen/DS3232RTC
#define ldrInterruptPin 2
#define DS2331interruptPin 3
void setup() {
Serial.begin(9600);//Начать последовательную связь
Wire.begin();
//_____________________ настройка прерываний DS3231_________
pinMode(DS2331interruptPin, INPUT_PULLUP);
digitalWrite(DS2331interruptPin, HIGH);
attachInterrupt(digitalPinToInterrupt(DS2331interruptPin), onAlarm, FALLING);
//_____________________ прерывания настройки LD235R_________
pinMode(ldrInterruptPin, INPUT);
digitalWrite(ldrInterruptPin, HIGH);
attachInterrupt(digitalPinToInterrupt(ldrInterruptPin), irq1, RISING);
resetDS3231Alarms();
time_t t = RTC.get();
setUpAlarms();
}
void loop() {
//считывание показаний датчика освещенности vlaues
}
Вопог это функция onAlarm:
void onAlarm() {
Serial.println("ALARM");
formatTime(timestamp, RTC.get());
if (RTC.alarm(ALARM_1))
{
Serial << F("SLEEP alarm at ") << timestamp << endl;
goToSleep();
}
else if (RTC.alarm(ALARM_2))
{
Serial << F("WakeUP Alarm at ") << timestamp << endl;
Serial.println("Time to Wake up......!");
sleep_disable();
Serial.println("I woke up!!!");
attachInterrupt(digitalPinToInterrupt(ldrInterruptPin), irq1, RISING);
}
// обновить время сна и пробуждения на основе текущего дня
setUpAlarms();
};
Сброс настроек ()
void resetDS3231Alarms() {
// инициализируйте аварийные сигналы известными значениями, снимите флаги аварийных сигналов, снимите флаги прерывания аварийных сигналов
RTC.setAlarm(ALM1_MATCH_DATE, 0, 0, 0, 1);
RTC.setAlarm(ALM2_MATCH_DATE, 0, 0, 0, 1);
RTC.alarm(ALARM_1);
RTC.alarm(ALARM_2);
RTC.alarmInterrupt(ALARM_1, false);
RTC.alarmInterrupt(ALARM_2, false);
RTC.squareWave(SQWAVE_NONE);
}
Каждый раз, когда возникает сигнал тревоги, код блокируется и выводит именно то, что указано в описании захвата последовательного монитора ниже: Он просто печатает "AL" из Serial.println("ALARM"); и оттуда ничего не происходит
Кто-нибудь знает, что вызывает эту проблему и как ее можно решить?
@Emanuel Giurgiu, 👍2
Обсуждение1 ответ
Лучший ответ:
Когда процессор AVR переходит в спящий режим, единственный способ, которым он может проснуться , - это прерывание. Если он перейдет в спящий режим с отключенными прерываниями, то он никогда не проснется.
Процедуры прерывания по умолчанию не прерываются: первое
, что делает процессор при обслуживании прерывания, - это отключает дальнейшие
прерывания. Таким образом, ваша функция onAlarm()
выполняется с
отключенными прерываниями. Если он перейдет в спящий режим, он заблокирует процессор.
Быстрым и грязным решением было бы вызвать функцию interrupts()
прямо перед сном
. Однако я бы не рекомендовал этого делать, так как в конечном итоге вы будете накладывать
контексты прерывания один на другой. Правильным решением было бы
сократить ваши процедуры обслуживания прерываний до минимума, который должен быть
выполнен немедленно, и обрабатывать все остальное в обычном коде в пределах
loop()
. В данном конкретном случае установка volatile bool
вполне
может быть единственным, что вам действительно нужно сделать. Ваш цикл ()
проверит этот
bool
и позаботится обо всем остальном.
Такс, это работает с обоими вариантами, которые вы дали, но я выбрал тот, у которого есть bool, @Emanuel Giurgiu
- RtcDateTime' не называет тип
- Ошибка модуля часов реального Времени-DS3231
- Возникла проблема с переобъявлением символа другого типа
- Как разбудить Arduino с помощью rtc?
- Установить регистр управления на низкий уровень в ds3231 rtc
- Светодиод не мигает - Arduino UNO+WiFi R3 ATmega328P+Плата ESP8266
- Как подсчитать количество нарастающих фронтов на DS3231 rtc?
- Arduino Nano, модуль часов DS3231 RTC и 4 каскадных светодиодных матричных модуля FC-16
Никогда не используйте
Последовательный
в прерывании. Он сам полагается на прерывание, чего не может произойти, потому что выполняется ваше прерывание., @MajenkoЯ удалил все серийные отпечатки, и проблема все еще присутствует. В методе onAlarm() ничего не выполняется, и код зависает, @Emanuel Giurgiu
Возможно, вы вызываете функцию, которая сама вызывает
delay()
. Это тоже сломается. Прерывания должны быть абсолютным минимумом, с которым вы можете справиться - в идеале просто установите флаг, а затем проверьте этот флаг вloop ()
, чтобы выполнить свою реальную работу. Прерывание фиксирует событие, но не выполняет всю работу., @Majenko