Часы ds 3231

Тема в разделе "Arduino & Shields", создана пользователем greck, 21 мар 2015.

  1. xbSlick

    xbSlick Нуб

    Коллеги, доброго времени суток!
    Пользуясь вашими советам "наваял" скетч на базе 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
    {ВЫКЛЮЧАЕМ РЕЛЕ}
     
     
  2. vvr

    vvr Инженерище

    числа 00 не бывает)))
     
    Tomasina и xbSlick нравится это.
  3. xbSlick

    xbSlick Нуб

    Да, понял еще ранее, до дисплея всеравно доходит ОДИН ноль ))
     
  4. Tomasina

    Tomasina Сушитель лампочек Модератор

    зачем int, если число больше 59 никогда не будет?
     
  5. obuhanoe

    obuhanoe Гик

    Я для 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");
        }
     
    Последнее редактирование: 28 июл 2016
  6. fogary

    fogary Гик

    Вы через будильники часов реализуете включение/выключение реле? Если да, то, если не ошибаюсь, будильник должен сработать даже в отсутствии внешнего питания, т. е. от батарейки. Тогда, при загрузке, можно будет проверить - сработал какой-то из будильников или нет.
    В принципе, должно работать, но конечно же нужно проверить.
     
  7. xbSlick

    xbSlick Нуб

    НЕТ, от будильника ОТКАЗАЛСЯ. Ввиду сложности реализации функции длительности включения реле (таймер) и последующей проверке. В этом скетче, как видно, будильник "самодельный". Контроллер ПОСТОЯННО проверяет условие должно ли быть включенным реле. И даже если ВДРУГ контроллер включился на середине времени полива - программа отработает половину времени и выключится. Кстати...это не есть хорошо...но что поделать...нет света - нет полива.
     
  8. fogary

    fogary Гик

    Чисто из интереса, в чем именно сложность возникла?
     
  9. fogary

    fogary Гик

    Восьмеричный формат?
     
  10. xbSlick

    xbSlick Нуб

    Поясню что НЕ смог побороть, может подскажете...
    1. После включения будильника необходимо включать таймер обратного отсчета времени. Причем делать это нужно НЕ с начала запуска программы, а после включения будильника. Без использования библиотек не смог придумать решение, но глубоко не копал так как см. дальше...
    2. Таймер через "Миллис" имеет ограничения в 50 дней. У меня теплица с автополивом. Может будет ИБП. После 50-ти дней счетчик сбрасывается в ноль. Нужно делать проверку. Вроде, даже, нашел решение на этом же форуме.
    3. Нашел библиотеки таймеров (SimpleTimer, Timer). По идее через них можно реализовать включение реле на нужный промежуток времени. "Курил мануалы" и не нашел есть ли там "обход проблемы в 50 дней". Судя по всему на серъезные задачи их НЕ поставишь, а только на "помигать лампочкой".
    4. Есть мысли что аппаратные таймеры могут выручить, но беглое "курение мануалов" не позволило мне постичь "ДЗЫ" и эта тема была отложена.
    5. Не нашел недостатков в подходе запуска реле через проверку часов старта, финиша и текущего времени (как в скетче выше). Но догадываюсь что знаю не все, поэтому и написал здесь...
     
    Последнее редактирование: 29 июл 2016
  11. fogary

    fogary Гик

    Какую функцию выполняет таймер обратного отсчета?
     
  12. xbSlick

    xbSlick Нуб

    Ну как же, он отсчитывает часы на протяжении которых включено реле для полива. После истечения срока - реле в "Лоу".
     
  13. DIYMan

    DIYMan Guest

    Вот, почитайте, это про вредные советы типа "реле в "Лоу"". Иногда, даже в бОльшем кол-ве случаев реле в "Лоу" - включает реле, и не выключает:

    http://forum.amperka.ru/threads/Про-уровни-срабатывания-реле.8996/
     
  14. fogary

    fogary Гик

    Как минимум, два варианта решения:

    1. В часах есть два будильника. Первый настроить на время включения реле, второй - на выключение. Т. е. проверить какой будильник сработал и либо включить, либо выключить реле.

    2. Один из будильников, сначала настроить на время включения реле, а после срабатывания - перенастроить на время выключения, и наоборот.

    При включении питания, проверить текущее время и выставить соответствующий режим реле, и, для второго варианта, настроить будильник.
     
  15. ruslan55

    ruslan55 Нерд

  16. uvarofff

    uvarofff Нуб

    Друзья, прочёл всю ветку, вроде со всем разобрался, на основе ваших скетчей набросал свой. Залил в леонардо - не работает. Я нуб, но хочу разложить всё по полочкам. Помогите разобраться - тыкните в ошибку.

    Код (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мс

    }
     
  17. Karabas

    Karabas Гик

    И не должен работать.
    Во первых у вас при каждом запуске программы переустанавливаются часы, в простейшем случае, нужно после заливки скетча и его работы, сразу залить его же, но с закомментированной строчкой с установкой часов.

    Второе- вся ваша программа исполняется один раз в стартапе, условия IF должны быть в LOOP-е.
    Третье- вы проверяете равенство времени, с точностью до секунд. Один делей на 1000мсек и ваш будильник сработает раз черер раз бри большой удаче.
     
  18. uvarofff

    uvarofff Нуб

    Спасибо.

    Заменил на
    Код (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 у меня модуль с диодом, но нет даже намёка на включение.
     
  19. Karabas

    Karabas Гик

    Потому что
    Код (C++):
    tmp_h = time.Hours;
    tmp_m = time.minutes;
    tmp_s = time.seconds;
     
    должно обновляться в главном цикле.
     
  20. uvarofff

    uvarofff Нуб

    Главный цикл - это void loop, верно?
    Внедрил строки туда, диодик тускло поморгал раз в секунду, затем перестал.
    Мигал ровно минуту, пока время соответствовало условию.

    Затем убрал delay(1000), диод мигать перестал, но светил всё равно ровно минуту из условия, зато в serial время сыпалось без остановки.

    Ничего не понял. Думал, что эта конструкция рабочая, или я что-то напортачил.