Коллеги, доброго времени суток! Пользуясь вашими советам "наваял" скетч на базе DS3231 с задачей включать РЕЛЕ на пару часов в нужное время. При этом, учтен момент возможного пропуска включения или выключения (например, выключили свет). "Прогнал" на рабочей схеме, вроде все норм. Но опыта мало, может я чего-то НЕ вижу и где-то вылезет "БОК". Можно получить совет, что все сделано верно ? Код (C++): int H_start = 00; // Старт полива ЧАСЫ. int M_start = 44; // Стар полива МИНУТЫ. int H_finish = 00; // Окончание полива ЧАСЫ. int M_finish = 50; // Окончание полива МИНУТЫ. int H_cur = 0; // Текущее значание ЧАСОВ. int M_cur = 0; // Текущее значение МИНУТ. if (H_cur >= H_start && M_cur >= M_start && H_cur <= H_finish && M_cur <= M_finish) // Сверяем текущее время с состоянем будильника. {ВКЛЮЧАЕМ РЕЛЕ} else {ВЫКЛЮЧАЕМ РЕЛЕ}
Я для DS1307 библиотека DS1307RTC.h сделал следующим образом. считываю данные с SD и сохраняю в переменные startM - минуты начала периода startH - часы начала периода endM - минуты конца периода endH - часы конца периода секунды считаем равные 0 Код (C++): time_t v_RTC_now = RTC.get(); TimeElements tmp_b, tmp_e; tmp_b.Second = 0; tmp_b.Minute = startM; tmp_b.Hour = startH; tmp_b.Day = day(v_RTC_now); tmp_b.Month = month(v_RTC_now); tmp_b.Year = year(v_RTC_now)-1970; tmp_e = tmp_b; tmp_e.Minute = endM; tmp_e.Hour = endH; time_t v_RTC_b = makeTime(tmp_b); time_t v_RTC_e = makeTime(tmp_e); и сама проверка Код (C++): if (v_RTC_now >= v_RTC_b && v_RTC_now <= v_RTC_e) { // debug_log("sched: " + String(graph) + " polivaem"); }
Вы через будильники часов реализуете включение/выключение реле? Если да, то, если не ошибаюсь, будильник должен сработать даже в отсутствии внешнего питания, т. е. от батарейки. Тогда, при загрузке, можно будет проверить - сработал какой-то из будильников или нет. В принципе, должно работать, но конечно же нужно проверить.
НЕТ, от будильника ОТКАЗАЛСЯ. Ввиду сложности реализации функции длительности включения реле (таймер) и последующей проверке. В этом скетче, как видно, будильник "самодельный". Контроллер ПОСТОЯННО проверяет условие должно ли быть включенным реле. И даже если ВДРУГ контроллер включился на середине времени полива - программа отработает половину времени и выключится. Кстати...это не есть хорошо...но что поделать...нет света - нет полива.
Поясню что НЕ смог побороть, может подскажете... 1. После включения будильника необходимо включать таймер обратного отсчета времени. Причем делать это нужно НЕ с начала запуска программы, а после включения будильника. Без использования библиотек не смог придумать решение, но глубоко не копал так как см. дальше... 2. Таймер через "Миллис" имеет ограничения в 50 дней. У меня теплица с автополивом. Может будет ИБП. После 50-ти дней счетчик сбрасывается в ноль. Нужно делать проверку. Вроде, даже, нашел решение на этом же форуме. 3. Нашел библиотеки таймеров (SimpleTimer, Timer). По идее через них можно реализовать включение реле на нужный промежуток времени. "Курил мануалы" и не нашел есть ли там "обход проблемы в 50 дней". Судя по всему на серъезные задачи их НЕ поставишь, а только на "помигать лампочкой". 4. Есть мысли что аппаратные таймеры могут выручить, но беглое "курение мануалов" не позволило мне постичь "ДЗЫ" и эта тема была отложена. 5. Не нашел недостатков в подходе запуска реле через проверку часов старта, финиша и текущего времени (как в скетче выше). Но догадываюсь что знаю не все, поэтому и написал здесь...
Ну как же, он отсчитывает часы на протяжении которых включено реле для полива. После истечения срока - реле в "Лоу".
Вот, почитайте, это про вредные советы типа "реле в "Лоу"". Иногда, даже в бОльшем кол-ве случаев реле в "Лоу" - включает реле, и не выключает: http://forum.amperka.ru/threads/Про-уровни-срабатывания-реле.8996/
Как минимум, два варианта решения: 1. В часах есть два будильника. Первый настроить на время включения реле, второй - на выключение. Т. е. проверить какой будильник сработал и либо включить, либо выключить реле. 2. Один из будильников, сначала настроить на время включения реле, а после срабатывания - перенастроить на время выключения, и наоборот. При включении питания, проверить текущее время и выставить соответствующий режим реле, и, для второго варианта, настроить будильник.
Подробное описание часов реального времени DS3231, пример подключения к микроконтроллеру http://radiolaba.ru/microcotrollers/ds3231-podklyuchenie-chasov-realnogo-vremeni.html
Друзья, прочёл всю ветку, вроде со всем разобрался, на основе ваших скетчей набросал свой. Залил в леонардо - не работает. Я нуб, но хочу разложить всё по полочкам. Помогите разобраться - тыкните в ошибку. Код (C++): #include <Wire.h> #include <RTC.h> RTC time; int h; //Установленное время часы int m;//Установленное время минуты int s;//Установленное время секунды int lamp = 6; int tmp_h,tmp_m,tmp_s; void setup() { delay(300); Serial.begin(9600); time.begin(RTC_DS1307); time.settime(0,15,11,13,12,16,2); // 0 сек, 15 мин, 11 часов, 13, декабря, 2016 года, вторник tmp_h = time.Hours; tmp_m = time.minutes; tmp_s = time.seconds; if (tmp_h==11 && tmp_m==15 && tmp_s==30) { //Включаем в 11.15 digitalWrite(lamp, HIGH); } if (tmp_h==19 && tmp_m==00 && tmp_s==00); { //Выключаем в 7 вечера digitalWrite(lamp, LOW); } } void loop() { delay(1000); Serial.println(time.gettime("d-m-Y, H:i:s, D")); // выводим время delay(1); // приостанавливаем на 1 мс, чтоб не выводить время несколько раз за 1мс }
И не должен работать. Во первых у вас при каждом запуске программы переустанавливаются часы, в простейшем случае, нужно после заливки скетча и его работы, сразу залить его же, но с закомментированной строчкой с установкой часов. Второе- вся ваша программа исполняется один раз в стартапе, условия IF должны быть в LOOP-е. Третье- вы проверяете равенство времени, с точностью до секунд. Один делей на 1000мсек и ваш будильник сработает раз черер раз бри большой удаче.
Спасибо. Заменил на Код (C++): #include <Wire.h> #include <RTC.h> RTC time; int H; //Установленное время часы int m;//Установленное время минуты int s;//Установленное время секунды int lamp = 6; int tmp_h,tmp_m,tmp_s; void setup() { pinMode(lamp, OUTPUT); delay(300); Serial.begin(9600); time.begin(RTC_DS1307); //time.settime(0,15,11,13,12,16,2); tmp_h = time.Hours; tmp_m = time.minutes; tmp_s = time.seconds; } void loop() { if (tmp_h==11 && tmp_m==17) { //Включаем в 11 утра digitalWrite(lamp, HIGH); } if (tmp_h==19 && tmp_m==00); { //Выключаем в 7 вечера digitalWrite(lamp, LOW); } delay(1000); Serial.println(time.gettime("d-m-Y, H:i:s, D")); // выводим время delay(1); // приостанавливаем на 1 мс, чтоб не выводить время несколько раз за 1мс } И вот незадача, всё равно не работает. В качестве lamp у меня модуль с диодом, но нет даже намёка на включение.
Потому что Код (C++): tmp_h = time.Hours; tmp_m = time.minutes; tmp_s = time.seconds; должно обновляться в главном цикле.
Главный цикл - это void loop, верно? Внедрил строки туда, диодик тускло поморгал раз в секунду, затем перестал. Мигал ровно минуту, пока время соответствовало условию. Затем убрал delay(1000), диод мигать перестал, но светил всё равно ровно минуту из условия, зато в serial время сыпалось без остановки. Ничего не понял. Думал, что эта конструкция рабочая, или я что-то напортачил.