Включение/выключение реле по будильникам

Всем привет!
Наверняка, невероятно популярная тема с таймерами, но столько всего перечитал и перепробовал, что в итоге запутался и пришёл к Вам за помощью.
Есть задача - включать реле на несколько секунд в определенное время, потом выключать и так 2 раза в день (утром и вечером) ежедневно.
Повторюсь, пробовал разное. В последнем варианте собрал 4 будильника: 2 на вкл/выкл и ещё 2 такие же через 1 минуту.
Модули: Arduino Nano, DS1302, LCD1602
Описание работы:

  • Элемент списка

1-ый будильник включает реле на 7 секунд,

  • Элемент списка

2-ой будильник выключает,

  • Элемент списка

через минуту 3-ий будильник включает реле на 7 секунд,

  • Элемент списка

4-ый будильник выключает.

Но функционально всё работает как надо, только если в действиях 2-ого и 4-ого будильников выполнять принудительную перезагрузку Ардуино :frowning:
Помогите, пожалуйста, с настройкой таймеров (или действий) для 2-ого и 4-ого будильников вместо перезагрузки. А может, наоборот, 2 и 4 будильники исключить и правильно настроить таймеры в 1 и 3 будильниках. У меня не получилось: то включается реле, но не выключается; то включается и выключается, но потом по кругу каждые 7 секунд циклично включается/выключается, пока не перезагрузишь вручную и т.д.

Код такой (не ругайтесь, плиз):

//-------ПОДКЛЮЧЕНИЕ БИБЛИОТЕК
#include <Wire.h>                       // подключаем библиотеку I2C
#include <LiquidCrystal_I2C.h>          // подключаем библиотеку LCD-дисплея 1602
#include <iarduino_RTC.h>               // подключаем библиотеку RTC DS1302

//-------НАЗНАЧЕНИЕ ПИНОВ
const int PinRELE = 6;                  // вывод 6 к реле на "минус"

//-------МАССИВЫ ДЛЯ БУДИЛЬНИКОВ РЕЛЕ
uint8_t alarm_SEC    = 00;              // будильник №1 секунды
uint8_t alarm_MIN    = 12;              // будильник №1 минуты
uint8_t alarm_HOUR   = 17;              // будильник №1 часы

uint8_t alarm2_SEC   = 07;              // будильник №2 секунды
uint8_t alarm2_MIN   = 12;              // будильник №2 минуты
uint8_t alarm2_HOUR  = 17;              // будильник №2 часы

uint8_t alarm3_SEC   = 00;              // будильник №3 секунды
uint8_t alarm3_MIN   = 13;              // будильник №3 минуты
uint8_t alarm3_HOUR  = 17;              // будильник №3 часы

uint8_t alarm4_SEC   = 07;              // будильник №4 секунды
uint8_t alarm4_MIN   = 13;              // будильник №4 минуты
uint8_t alarm4_HOUR  = 17;              // будильник №4 часы

bool    alarm_FLAG1  = true;            // будильник №1 разрешение работы
bool    alarm_FLAG2  = false;           // будильник №1 включаем реле

bool    alarm2_FLAG1 = true;            // будильник №2 разрешение работы
bool    alarm2_FLAG2 = false;           // будильник №2 выключаем реле

bool    alarm3_FLAG1 = true;            // будильник №3 разрешение работы
bool    alarm3_FLAG2 = false;           // будильник №3 включаем реле

bool    alarm4_FLAG1 = true;            // будильник №4 разрешение работы
bool    alarm4_FLAG2 = false;           // будильник №4 выключаем реле

//-------ИНИЦИАЛИЗАЦИИ МОДУЛЕЙ
LiquidCrystal_I2C lcd(0x27,16,2);       // инициализируем LCD-дисплей 1602
iarduino_RTC time(RTC_DS1302, 5, 3, 4); // инициализируем модуль DS1302

//ПРОЧЕЕ
unsigned long current_pause = millis();  //целое число паузы для таймера
bool rele_pause;                          //переменная паузы для таймера

//-------ОСНОВНАЯ НАСТРОЙКА
void setup() {
  delay(300);                          // задержка после иницализации
  Serial.begin(9600);                  // подключаем последовательный порт
  time.begin();                        // запускаем модуль RTC
  //time.settime(00,17,20,24,3,25,6);  // настраиваем время 0  сек, 17 мин, 20 часов, 24, март, 2025, суббота 

  lcd.init();                           // включаем LCD
  lcd.backlight();                      // включаем подсветку LCD
  lcd.setCursor(9,1);                  // помещаем курсор вниз вправо
  lcd.print("Rele-OF");                    // выводим надпись на LCD

  pinMode(PinRELE, OUTPUT);             // подключаем контакт реле на выход
  digitalWrite(PinRELE, HIGH);          // выключаем реле  - посылаем высокий сигнал

}

//-------ПРОГРАММА
void loop() {
  if (millis() % 1000 == 0) {                             // выводим время каждую секунду
      Serial.println(time.gettime("d-m-Y, H:i:s, D"));    // выводим время на последовательный порт
      delay(1);                                           // задержка в 1 мс

lcd.setCursor(0,0);                     // помещаем курсор вверх влево
lcd.print(time.gettime("d M Y"));       // выводим дату на LCD
lcd.setCursor(0,1);                     // помещаем курсор вниз влево
lcd.print(time.gettime("H:i:s"));       // выводим время на LCD
  }

//-------РАБОТА БУДИЛЬНИКОВ КОМПРЕССОРА
  if(alarm_FLAG1){                      // если будильник №1 включён
   if(time.seconds==alarm_SEC){         // если совпали секунды
    if(time.minutes==alarm_MIN){        // если совпали минуты
      if(time.Hours==alarm_HOUR){       // если совпали часы
        alarm_FLAG2=true;               // устанавливаем флаг, разрешающий будильнику №1 действовать
        }
      }
    }
  }
  else{alarm_FLAG2=false;}              // если будильник выключен, то сбрасываем флаг, разрешающий будильнику №1 действовать
  if(alarm_FLAG2){Func_alarm_action();  // включаем реле
  }

  if(alarm2_FLAG1){                     // если будильник №2 включён
   if(time.seconds==alarm2_SEC){        // если совпали секунды
    if(time.minutes==alarm2_MIN){       // если совпали минуты
      if(time.Hours==alarm2_HOUR){      // если совпали часы
        alarm2_FLAG2=true;              // устанавливаем флаг, разрешающий будильнику №2 действовать
       }
     }
   }
  }
  else{alarm2_FLAG2=false;}              // если будильник выключен, то сбрасываем флаг, разрешающий будильнику №2 действовать
  if(alarm2_FLAG2){Func_alarm2_action(); // выключаем реле
  }

  if(alarm3_FLAG1){                     // если будильник №3 включён
   if(time.seconds==alarm3_SEC){        // если совпали секунды
    if(time.minutes==alarm3_MIN){       // если совпали минуты
     if(time.Hours==alarm3_HOUR){       // если совпали часы
        alarm3_FLAG2=true;              // устанавливаем флаг, разрешающий будильнику №3 действовать
      }
    }
    }
  }
  else{alarm3_FLAG2=false;}              // если будильник выключен, то сбрасываем флаг, разрешающий будильнику №3 действовать
  if(alarm3_FLAG2){Func_alarm3_action(); // включаем реле
  }

  if(alarm4_FLAG1){                     // если будильник №4 включён
   if(time.seconds==alarm4_SEC){        // если совпали секунды
    if(time.minutes==alarm4_MIN){       // если совпали минуты
      if(time.Hours==alarm4_HOUR){      // если совпали часы
        alarm4_FLAG2=true;              // устанавливаем флаг, разрешающий будильнику №4 действовать
      }
    }
    }
  }
  else{alarm4_FLAG2=false;}              // если будильник выключен, то сбрасываем флаг, разрешающий будильнику №4 действовать
  if(alarm4_FLAG2){Func_alarm4_action(); // выключаем реле
  }
}

//-------ДЕЙСТВИЯ

void Func_alarm_action(){                                       // активируем действие
  if (rele_pause == 0 && millis() - current_pause >= 7000) {    // 7 секунд
    lcd.setCursor(9,1);                                         // помещаем курсор вниз вправо
    lcd.print("Rele-ON");                                       // выводим надпись на LCD
    digitalWrite(PinRELE, LOW);                                 // включаем реле
    current_pause = millis();
    rele_pause = 1;
 }
}

void Func_alarm2_action(){                                      // активируем действие
  asm volatile("jmp 0x00");                                     // перезагрузка
 }

void Func_alarm3_action(){                                       // активируем действие
    if (rele_pause == 0 && millis() - current_pause >= 7000) {   // 7 секунд
    lcd.setCursor(9,1);                                          // помещаем курсор вниз вправо
    lcd.print("Rele-ON");                                        // выводим надпись на LCD
    digitalWrite(PinRELE, LOW);                                  // включаем реле
    current_pause = millis();
    rele_pause = 1;
 }
}

void Func_alarm4_action(){                                        // активируем действие
  asm volatile("jmp 0x00");                                       // перезагрузка
}

ага… часики, заряд тротила… и ардуина :slight_smile:
Актуальная тема

1 лайк

Автокормушка для аквариумных рыбок :slight_smile:

можно взять плату esp, и настраивать эти таймеры через браузер…
https://github.com/GyverLibs/GyverPortal
знания требуются по минимуму… может будет полезно…

Не, мне классический вариант нужен)

Жесть какая-то. Читал три раза как трудовик и не понял, зачем 4 будильника?
Одного мало?

1 лайк

Согласен с lilik. Код трудно читаемый.
Могу посоветовать Если времена не перекрываются, то сделайте по простому через delay. Совпадение времени по DS1302, включение реле, delay() отключение реле.

Оставил 2 будильника с delay(7000) с разницей в 1 минуту. После срабатывания 1-ого будильника время в мониторе и на дисплее замирает на времени срабатывания будильника, при этом DS1302 продолжает считать реальное время, т.к. после ручной перезагрузки программы время отображается в штатном режиме и на дисплее и в мониторе.
2-ой будильник через выставленную 1 минуту не срабатывает(((

Код такой получился:

//-------ПОДКЛЮЧЕНИЕ БИБЛИОТЕК
#include <Wire.h>                       // подключаем библиотеку I2C
#include <LiquidCrystal_I2C.h>          // подключаем библиотеку LCD-дисплея 1602
#include <iarduino_RTC.h>               // подключаем библиотеку RTC DS1302

//-------НАЗНАЧЕНИЕ ПИНОВ
const int PinRELE = 6;                  // вывод 6 к реле на "минус"

//-------МАССИВЫ ДЛЯ БУДИЛЬНИКОВ РЕЛЕ

uint8_t alarm_MIN    = 7;               // будильник №1 минуты
uint8_t alarm_HOUR   = 21;              // будильник №1 часы

uint8_t alarm2_MIN   = 8;               // будильник №2 минуты
uint8_t alarm2_HOUR  = 21;              // будильник №2 часы

bool    alarm_FLAG1  = true;            // будильник №1 разрешение работы
bool    alarm_FLAG2  = false;           // будильник №1 включаем реле

bool    alarm2_FLAG1 = true;            // будильник №2 разрешение работы
bool    alarm2_FLAG2 = false;           // будильник №2 выключаем реле

//-------ИНИЦИАЛИЗАЦИИ МОДУЛЕЙ
LiquidCrystal_I2C lcd(0x27,16,2);       // инициализируем LCD-дисплей 1602
iarduino_RTC time(RTC_DS1302, 5, 3, 4); // инициализируем модуль DS1302

//-------ОСНОВНАЯ НАСТРОЙКА
void setup() {
  delay(300);                          // задержка после иницализации
  Serial.begin(9600);                  // подключаем последовательный порт
  time.begin();                        // запускаем модуль RTC
  //time.settime(00,17,20,24,3,25,6);  // настраиваем время 0  сек, 17 мин, 20 часов, 24, март, 2025, суббота 

  lcd.init();                           // включаем LCD
  lcd.backlight();                      // включаем подсветку LCD
  lcd.setCursor(9,1);                   // помещаем курсор вниз вправо
  lcd.print("Rele-OF");                 // выводим надпись на LCD

  pinMode(PinRELE, OUTPUT);             // подключаем контакт реле на выход
  digitalWrite(PinRELE, HIGH);          // выключаем реле  - посылаем высокий сигнал

}

//-------ПРОГРАММА
void loop() {
  if (millis() % 1000 == 0) {                             // выводим время каждую секунду
      Serial.println(time.gettime("d-m-Y, H:i:s, D"));    // выводим время на последовательный порт
      delay(1);                                           // задержка в 1 мс

lcd.setCursor(0,0);                     // помещаем курсор вверх влево
lcd.print(time.gettime("d M Y"));       // выводим дату на LCD
lcd.setCursor(0,1);                     // помещаем курсор вниз влево
lcd.print(time.gettime("H:i:s"));       // выводим время на LCD
  }

//-------РАБОТА БУДИЛЬНИКОВ КОМПРЕССОРА
  if(alarm_FLAG1){                      // если будильник №1 включён
   if(time.seconds==00){                // если совпали секунды
    if(time.minutes==alarm_MIN){        // если совпали минуты
      if(time.Hours==alarm_HOUR){       // если совпали часы
        alarm_FLAG2=true;               // устанавливаем флаг, разрешающий будильнику №1 действовать
        }
      }
    }
  }
  else{alarm_FLAG2=false;}              // если будильник выключен, то сбрасываем флаг, разрешающий будильнику №1 действовать
  if(alarm_FLAG2){Func_alarm_action();  // включаем/выключаем реле
  }

  if(alarm2_FLAG1){                     // если будильник №2 включён
   if(time.seconds==00){        // если совпали секунды
    if(time.minutes==alarm2_MIN){       // если совпали минуты
      if(time.Hours==alarm2_HOUR){      // если совпали часы
        alarm2_FLAG2=true;              // устанавливаем флаг, разрешающий будильнику №2 действовать
       }
     }
   }
  }
  else{alarm2_FLAG2=false;}              // если будильник выключен, то сбрасываем флаг, разрешающий будильнику №2 действовать
  if(alarm2_FLAG2){Func_alarm2_action(); // выключаем/выключаем реле
  }
}

//-------ДЕЙСТВИЯ

void Func_alarm_action(){                                       // активируем действие
    lcd.setCursor(9,1);                                         // помещаем курсор вниз вправо
    lcd.print("Rele-ON");                                       // выводим надпись на LCD
    digitalWrite(PinRELE, LOW);                                 // выключаем/выключаем реле
    delay(7000);                                                // задержка 7 секунд
}

void Func_alarm2_action(){                                      // активируем действие
    lcd.setCursor(9,1);                                         // помещаем курсор вниз вправо
    lcd.print("Rele-ON");                                       // выводим надпись на LCD
    digitalWrite(PinRELE, LOW);                                 // выключаем/выключаем реле
    delay(7000);                                                // задержка 7 секунд
}

Видимо что-то не так в коде будильника:

  if(alarm_FLAG1){                      // если будильник №1 включён
   if(time.seconds==00){                // если совпали секунды
    if(time.minutes==alarm_MIN){        // если совпали минуты
      if(time.Hours==alarm_HOUR){       // если совпали часы
        alarm_FLAG2=true;               // устанавливаем флаг, разрешающий будильнику №1 действовать
        }
      }
    }
  }
  else{alarm_FLAG2=false;}              // если будильник выключен, то сбрасываем флаг, разрешающий будильнику №1 действовать
  if(alarm_FLAG2){Func_alarm_action();  // включаем/выключаем реле

Я не понимаю, зачем используются флаги.
Если задача включить реле на несколько секунд два раза в день то просто

loop{
 Если время = T1
   Включить реле
   delay(...)
   Выключить реле

 Если время = T2
   Включить реле
   delay(...)
   Выключить реле
}

А как T1 и T2 назначить?
Так?

const int T1 ("21:50:00");
const int T2 ("21:51:00");

Вот так функция не работает:

  if(time.gettime("H:i:s")) == T1; {                // если совпало время
   Func_alarm_action();                             // включаем/выключаем реле
  }

  if(time.gettime("H:i:s")) == T2; {                // если совпало время
   Func_alarm_action();                             // включаем/выключаем реле  

Точнее вот так:

  if(time.gettime("H:i:s") == T1);{                // если совпало время
   Func_alarm_action();                             // включаем/выключаем реле
  }

  if(time.gettime("H:i:s") == T2);{                // если совпало время
   Func_alarm2_action();                             // включаем/выключаем реле  
}

Но тоже не работает(

if ( (H==1) && (m==)){} или H должна быть маленькая… и насколько помню надо привязать их к переменным… но что бы наверняка вот используйте готовые библиотеки))) https://robotchip.ru/podklyuchenie-ds1302-k-arduino/

Я просто спрашивал зачем вам флаги, и привел примерный алгоритм. Сравнивайте время, как уже умеете, например

if(time.seconds==00 && time.minutes==alarm_MIN && time.Hours==alarm_HOUR){
}

H большая для формата 24 , а h маленькая для формата 12.
Вроде

Тут не 4 будильника надо а два будильника и таймер.

Сделал так:

uint8_t alarm_SEC    = 00;          // будильник №1 секунды
uint8_t alarm_MIN    = 52;          // будильник №1 минуты
uint8_t alarm_HOUR   = 23;          // будильник №1 часы

uint8_t alarm2_SEC   = 00;          // будильник №1 секунды
uint8_t alarm2_MIN   = 53;          // будильник №2 минуты
uint8_t alarm2_HOUR  = 23;          // будильник №2 часы

и так:

void loop() {
  if (millis() % 1000 == 0) {                             // выводим время каждую секунду
      Serial.println(time.gettime("d-m-Y, H:i:s, D"));    // выводим время на последовательный порт
      delay(1);                                           // задержка в 1 мс

lcd.setCursor(0,0);                     // помещаем курсор вверх влево
lcd.print(time.gettime("d M Y"));       // выводим дату на LCD
lcd.setCursor(0,1);                     // помещаем курсор вниз влево
lcd.print(time.gettime("H:i:s"));       // выводим время на LCD
  }

//-------РАБОТА БУДИЛЬНИКОВ КОМПРЕССОРА
  if(time.seconds==00 && time.minutes==alarm_MIN && time.Hours==alarm_HOUR);{                // если совпало время
   Func_alarm_action();                                                                      // включаем/выключаем реле
  }

  if(time.seconds==00 && time.minutes==alarm2_MIN && time.Hours==alarm2_HOUR);{              // если совпало время
   Func_alarm2_action();                                                                     // включаем/выключаем реле
  }
}

Не работают. Часы перестали отображаться на дисплее и в мониторе(
Подскажите, плиз, куда копать?

Пробовал. Не получается. Поэтому и пришёл к коду с перезагрузками. Он работает.

Будильник настраивал с флагами, но видимо что-то перемудрил:

if(alarm_FLAG1){                      // если будильник №1 включён
   if(time.seconds==00){                // если совпали секунды
    if(time.minutes==alarm_MIN){        // если совпали минуты
      if(time.Hours==alarm_HOUR){       // если совпали часы
        alarm_FLAG2=true;               // устанавливаем флаг, разрешающий будильнику №1 действовать
        }
      }
    }
  }
  else{alarm_FLAG2=false;}              // если будильник выключен, то сбрасываем флаг, разрешающий будильнику №1 действовать
  if(alarm_FLAG2){Func_alarm_action();  // включаем/выключаем реле

ИЗВИНИТЕ, Я ПРОСТО В ШОКЕ
необразованность/ неспособность выражать свои мысли, это что новый тренд какой то?
куда вы лезете со всякими миллисами прочей херью?

два условия, включить “утром” и включить “вечером”, чего проще, поймал “утро” включил и жди, дальше лови “вечер” и жди, или утро опять
кто раньше настанет)) (это для эстетов)

ну в#9 все же сказал @Upper

Коль уж главный профи подключился, подскажи новичку в Песочнице, как сделать, чтоб заработало

польщен, откуда такие выводы?

void loop{
  if (time.Hours == alarm_HOUR_утро) {      // если совпали часы , шоб не дрочить секунды
    if (time.minutes == alarm_MIN_утро) { // если совпали минуты
      if (time.seconds == 00) {      // и секунды
        // тут покрасить яйца в синий цвет
        fill_blue_color();
        // и ждать пока не принесут зеленку
        delay(xxx);
      }
    }
  }
  // дальше
  if (time.Hours == alarm_HOUR_вечер) {      // если совпали часы , шоб не дрочить секунды
    if (time.minutes == alarm_MIN_вечер) { // если совпали минуты
      if (time.seconds == 00) {      // и секунды
        // тут прикладываем и ждать пока отпустит
        fill_white_color();
        // ждать насколько можно долго
        delay(xxx);
      }
    }
  }
}