Часы и датчик дождя - правильный алгоритм для полива

Имеется полив газона. Полив в 11-00 включается и в 16-00 выключается по времени. Включение отключение работает на Arduino + DS3231.
Включение/выключение реализовано следующим кодом:

if (tm.Hour == 11 && tm.Minute == 00) {
Relay1();
}

if (tm.Hour == 16 && tm.Minute == 00) {
Relay2();
}

Relay1() - Функция запускающая полив
Relay2() - функция выключающая полив

Появилось желание выключать полив или вообще не включать, если идёт дождь. Как только дождь прекращается, но если 16-00 не наступило, полив должен включиться.
Для обнаружения дождя применён датчик протечки + LM393.

Показание с датчика считывается с цифрового пина, состояние HIGH (датчик сухой) и LOW (идёт дождь).

int val = readRain(); - присваивает переменной val состояние HIGH или LOW.

Вопрос: Как правильно организовать алгоритм включение/выключение полива, в зависимости от того, идёт дождь или нет.

if (tm.Hour == 11 && tm.Minute == 00 && val == HIGH) { // если 11-00 и нет дождя, то полив включается
Relay1();
}

if (val == LOW) { // если появляется дождь, то полив выключается
Relay2();
}

if (tm.Hour == 16 && tm.Minute == 00) { // если 16-00, то полив выключается
Relay2();
}

Проблема в том, как включить вновь полив, если закончился дождь, но не наступило 16-00?

Используйте операторы > и < вместо == для того, чтобы задать промежуток времени, при котором полив включен или выключен. К примеру:

byte hour_ = tm.Hour;

if(val == HIGH){//если нет дождя
if(hour_ > 11 &&  hour_ < 16)
 Relay1();
}
else{// если дождь
Relay2();
}

P.S.Перечитайте, как вставлять код на форуме

1 лайк

А если включение и отключение нужно не в 00 минут, а например включение в 11:30, а выключение в 16:45?

А какая проблема добавить условие?
Хотя, как по мне, тогда проще считать время в минутах, или вообще использовать Unix-формат

1 лайк

Используй упакованное время, Luke.
В сутках 1440 минут, вот и делай простейшую свёртку

uint16_t  PackedTime = 60*Hour + Minute;

Дальше простые сравнения

1 лайк

включать реле если и время и не дождь

Написал алгоритм и код:

int h1 = 11;
int h2 = 16;
int m1 = 5;
int m2 = 45;

Что бы не лазить постоянно и не исправлять часы и минуты по всему коду, присвоил нужные значения переменным.
Включение полива в примере будет в 11:05, выключение в 16:45.

if (val == HIGH){
  if (h2 > tm.Hour >= h1){
    if (tm.Minute >= m1){
      Relay1();
    }
  }
  else {
    if (tm.Minute >= m1){
      Relay2();
    }
    else {
      Relay1();
    }
  }
}
else {
  Reley2();
}

Такое имеет право на жизнь?

Где про это прочитать детальнее?

В школьном учебнике арифметики? Рассуждайте логически. В сутках 24 часа, в часе - 60 минут. Значит в сутках 24*60=1440 минут. Соответственно, любой момент времени можно представить, как количество минут, прошедших после полуночи. Т.е. 11:05 можно представить как 665 минут, 16:45 - как 1005 минут. И с этими числами уже работать.

ЗЫ: по аналогии, в сутках 86400 секунд (если нужна точность до секунды)

2 лайка

Не всё так просто, если условия для часов и минут делать отдельно.

Примерно так:



uint8_t h1 = 11;
uint8_t h2 = 16;
uint8_t m1 = 5;
uint8_t m2 = 45;

unsigned int on_water_time;
unsigned int off_water_time;

on_water_time = h1 * 60u + m1; //время включения в минутах
off_water_time = h2 * 60u + m2;//время выключения

Уже три человека Вам об этом сказали)))

Не нужно “организовывать алгоритм”, нужно просто записать единственное логическое выражение, в котором перечислить все свои хотелки.

3 лайка

Почему моя схема и код не будут работать? Буду смотреть в сторону считать время в минутах, но так же хотелось знать, почему мой пример не рабочий? Я проверил с разными входными данными, код рабочий.

А где в нём вообще m2 ?

Интересно, как проверяли?

Например, если на часах 12:00 и нет дождя.

if (h2 > tm.Hour >= h1) - 12 больше h1 (11), но меньше h2 (16) - результат true

if (tm.Minute >= m1) - 00 не больше и не равно m1 (5) - результат false

Возвращаемся в начало и спустя секунду будет 12:01, вновь проверяем. Так будет до тех пор, пока не будет 12:05.

if (tm.Minute >= m1) - 05 равно m1 (5) - результат true - Relay1()

Какое ещё время проверить?

Это точно пропустил, сейчас добавлю.

if (val == HIGH){
  if (h2 > tm.Hour >= h1){
    if (tm.Minute >= m1){
      Relay1();
    }
  }
  else {
    if (tm.Minute >= m2){
      Relay2();
    }
    else {
      Relay1();
    }
  }
}
else {
  Reley2();
}

Теперь имеется m2, в первый раз вместо m2, написал m1, а разное время проверял по блок-схеме, а не коду.

Проверять по блок-схеме - то ещё занятие…
Проверьте на ардуино, и выведите значения в сериал

Конструкция

if (h2 > tm.Hour >= h1)

не уверен, что будет работать.

И что будет, если значение минут m2 будет меньше m1?
Например вкл.14.45 и выкл 15.05?

Так же стр. 12 противоречит стр.2

P.S. если что, почитайте, похожая тема
https://arduino.ru/forum/pesochnitsa-razdel-dlya-novichkov/problemy-s-upravleniem-solnechnoi-batareei

проверил со временем 13:07 и понял, что мой код не работает.

Си такого синтаксиса не знает

1 лайк

Увереннее надо быть - не будет так компилироваться

А чего бы это ей не компилироваться?
Вот только делать будет действительно не то, что автору хотелось! :slight_smile:

Ха! Если вывод включен как ВСЕ, то оно даже сообщает об этом :smiley: :

Спойлер
uint8_t h2 = 10, h1 = 6, hr = 9;

void setup() {
  pinMode(13, OUTPUT);
  digitalWrite(13, 0);
  
  if (h2 > hr >= h1) {
    digitalWrite(13, 1);
  }
}

void loop() { }

warning: comparisons like ‘X<=Y<=Z’ do not have their mathematical meaning [-Wparentheses]