Помогите разобраться, почему arduino зависает на этой строчке (где бы она не стояла): attachInterrupt(0, alarmFunction, FALLING); Спойлер: Скетч Код (C++): #include <Wire.h> #include <DS3231.h> #include <avr/sleep.h> #include <LiquidCrystal_I2C.h> DS3231 clock; RTCDateTime dt; boolean isAlarm = false; int alarmLED = 4; int count = 0; int wakePin = 2; LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display void sleepNow() // Функция увода ардуины в спячку. { lcd.clear(); lcd.noBacklight(); digitalWrite(alarmLED, LOW); // Выключаем светодиод set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Здесь устанавливается режим сна sleep_enable(); // Включаем sleep-бит в регистре mcucr. Теперь возможен слип count = 0; // Обнуляем счетчик прошедших секунд sleep_mode(); // Здесь устройство перейдет в режим сна!!! } void alarmFunction() // Функция просыпания { sleep_disable(); lcd.backlight(); lcd.clear(); lcd.print("*** INT 0 ***"); lcd.setCursor(0, 1); lcd.print("WakeUp Alarm"); isAlarm = true; digitalWrite(alarmLED, isAlarm); // Включаем светодиод } void setup() { attachInterrupt(0, alarmFunction, FALLING); // Эта строка вызывает зависание ардуино lcd.init(); lcd.backlight(); lcd.clear(); // Initialize DS3231 lcd.print("Init DS3231"); delay(2000); clock.begin(); clock.enableOutput(false); clock.armAlarm1(false); clock.armAlarm2(false); clock.clearAlarm1(); clock.clearAlarm2(); // Automatik (Year, Month, Day, Hour, Minute, Second) clock.setDateTime(__DATE__, __TIME__); // Set Alarm1 - Every 20s in each minute // setAlarm1(Date or Day, Hour, Minute, Second, Mode, Armed = true) clock.setAlarm1(0, 0, 0, 25, DS3231_MATCH_S); // Setup LED Pin pinMode(alarmLED, OUTPUT); pinMode(wakePin, INPUT); digitalWrite(wakePin, HIGH); digitalWrite(alarmLED, 1); } void loop() { lcd.clear(); dt = clock.getDateTime(); lcd.print(dt.hour); lcd.print(":"); lcd.print(dt.minute); lcd.print(":"); lcd.print(dt.second); lcd.print(""); count++; delay(1000); // Ждем секунду // Проверяем - если прошло 10 секунд - засыпаем if (count >= 10) { lcd.clear(); lcd.print("Ent Sleep mode"); delay(2000); count = 0; isAlarm = false; clock.clearAlarm1(); digitalWrite(alarmLED, isAlarm); sleepNow(); // Вызов функции sleep() для засыпания } }
А можно подробнее по поводу "где она стояла"? Мои предположения: После вызова функции 'attachInterrupt' сработает прерывание -- вызовется его обработчик 'alarmFunction'. И в приведенном Вами примере может случиться так, что функции lcd.* вызовутся до того как будет вызвана функция lcd.init() -- это первое предположение зависания, второе -- перед вызовом обработчика прерывания все прерывания отключаются, и если функции lcd.* зависят от прерываний, то это то же может привести к зависанию. Вообще по "правилам хорошего тона" обработчик прерываний должен выполнять минимум работы, а у Вас он занимается выводом информации на дисплей -- это не есть гут. PS: все сказанное выше актуально для Arduino UNO, за другие контроллеры не уверен.
Скорее всего тут и сидит засада. Функции для работы с дисплеем наверняка используют delay, а delay в прерываниях использовать вообще нельзя, т.к. внутри прерывания заблокированы другие прерывания, в т.ч. прерывание таймера, в котором обновляется счетчик, за которым следит delay. Только не для ардуино, а для AVR. В других контроллерах/процессорах ситуация аналогична с поправкой на возможное наличие приоритетов прерываний.
Сделал так: Код (C++): void alarmFunction() // Функция просыпания { sleep_disable(); digitalWrite(alarmLED, isAlarm); // Включаем светодиод } ардуина просыпается по прерыванию, засыпает, и больше не просыпается.
Вы используете прерывание "по спаду": Код (C++): attachInterrupt(0, alarmFunction, FALLING); А в докуметации к ATmega328 (раздел '9.1 Sleep Modes') указано следующее: Попробуйте: Код (C++): attachInterrupt(0, alarmFunction, CHANGE); Ну и соответственно логику программы нужно будет пересмотреть. PS: Для более точной информации все-таки следует покапаться в документации.
В процессе экспериментов со скетчем у меня потерялась строчка в конце "void loop()" Код (C++): clock.clearAlarm1(); вернул её на место и все заработало, просыпается каждую минуту на 25ой секунде и через десять секунд засыпает. Сейчас скетч выглядит так: Спойлер Код (C++): #include <Wire.h> #include <DS3231.h> #include <avr/sleep.h> #include <LiquidCrystal_I2C.h> DS3231 clock; RTCDateTime dt; boolean isAlarm = false; int alarmLED = 4; int count = 0; int wakePin = 2; LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display void sleepNow() // Функция увода ардуины в спячку. { lcd.clear(); lcd.noBacklight(); digitalWrite(alarmLED, LOW); // Выключаем светодиод set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Здесь устанавливается режим сна sleep_enable(); // Включаем sleep-бит в регистре mcucr. Теперь возможен слип count = 0; // Обнуляем счетчик прошедших секунд sleep_mode(); // Здесь устройство перейдет в режим сна!!! } void alarmFunction() // Функция просыпания { sleep_disable(); isAlarm = true; digitalWrite(alarmLED, isAlarm); // Включаем светодиод } void setup() { attachInterrupt(0, alarmFunction, FALLING); // Эта строка вызывает зависание ардуино lcd.init(); lcd.backlight(); lcd.clear(); // Initialize DS3231 lcd.print("Init DS3231"); delay(2000); clock.begin(); clock.enableOutput(false); clock.armAlarm1(false); clock.armAlarm2(false); clock.clearAlarm1(); clock.clearAlarm2(); // Automatik (Year, Month, Day, Hour, Minute, Second) clock.setDateTime(__DATE__, __TIME__); // Set Alarm1 - Every 20s in each minute // setAlarm1(Date or Day, Hour, Minute, Second, Mode, Armed = true) clock.setAlarm1(0, 0, 0, 25, DS3231_MATCH_S); // Setup LED Pin pinMode(alarmLED, OUTPUT); pinMode(wakePin, INPUT); digitalWrite(wakePin, HIGH); digitalWrite(alarmLED, 1); } void loop() { lcd.backlight(); lcd.clear(); dt = clock.getDateTime(); lcd.print(dt.hour); lcd.print(":"); lcd.print(dt.minute); lcd.print(":"); lcd.print(dt.second); lcd.print(""); count++; delay(1000); // Ждем секунду // Проверяем - если прошло 10 секунд - засыпаем if (count >= 10) { lcd.clear(); lcd.print("Ent Sleep mode"); delay(2000); count = 0; isAlarm = false; clock.clearAlarm1(); digitalWrite(alarmLED, isAlarm); sleepNow(); // Вызов функции sleep() для засыпания } } Большое спасибо за помощь!
Дергает один раз в минуту, при наступлении 25ой секунды. В дальнейшем планируется сделать чтобы ардуина просыпалась в одно и тоже время каждый день, опрашивала датчик, записывала показания на sd-карту и опять засыпала.
Ну так остался один шаг, если научились усыплять и пробуждать алярмом. Кстати, опыт весьма полезный, наверняка пригодится со временем.
работает ли это от зависания? rduino watchdog или автоматический RESET в случае зависания https://geektimes.ru/post/255800/
это работает, но у меня программа засыпает на 5 минут и на эти 5 мин надо отключать watchdog, и ардуинка может зависнуть пока будет спать
Доброй ночи! Помогите новичку разобраться с одним вопросом. Имеется плата Arduino nano с подключенными к ней 3 сервомоторчиками. Возможно ли, считать данные с сервомоторчиков управляемых платой Arduino nano и передать их скажем на Arduino UNO с мотор шилдом для управления шаговыми двигателями (не вмешиваясь в работу Arduino nano).
Возможно. Любой технический вопрос сводится к финансовому. На валы сервомашинок надо поставить энкодеры нужного разрешения, а это (пром. энкодеры) от 5 тыр (условная Корея, на самом деле хрен знает кто), сейчас может и больше - я привел сентябрьско- октябрьскую цену.
А если взять данные с потенциометра сервомоторчика? Вот пример https://habrahabr.ru/company/amperka/blog/127773/#comment_4225506