Проблема с работоспособностью скетка

SamFer
Offline
Зарегистрирован: 22.04.2019

Господа, всем привет!

Пару месяцев назад я создавал темы в которых просил помощи в реализации кода и мне очень сильно помогли.

Сейчас у меня снова возникла потребность в помощи.

Прикладываю скетч, который идеально работал до какого-то момента. Но теперь есть проблема. По какой-то причине релею включения дренажа и реле включения полива не срабатывает по установленному расписанию и срабатванию датчика (геркона) уровня воды. Если отключить Ардуино и потом включит, то скетч продолжает нормально работать. Прошу помощи у опытных коллег, так как не знаю в каком направлении копать.

Спасибо большое за помощь!


#include <Wire.h>                                       // Библиотека iarduino_RTC будет использовать методы и функции библиотеки Wire.

#include <iarduino_RTC.h>                                   // Подключаем библиотеку iarduino_RTC для работы с модулями реального времени.
    iarduino_RTC time(RTC_DS3231);                          // Объявляем объект time для работы с RTC модулем на базе чипа DS3231, используется аппаратная шина I2C
                                                            
    int relay = 5; // Определение пина для реле включения насоса полива
    int relay_lights = 3; // Определение пина для реле включения света певрого стеллажа
    int relay_lights2 = 4; // Определение пина для реле включения света второго стеллажа
    String RT = "50";
    String TimeOn = "00:00:00"; // Время включения первого полива
    String TimeOff = "00:00:00"; // Время выключения первого полива
    String TimeOn2 = "08:00:00"; // Время включения второго полива
    String TimeOff2 = "08:02:00"; // Время выключения второго полива
    String TimeOn3 = "16:00:00"; // Время включения третьего полива
    String TimeOff3 = "16:02:00"; // Время выключения третьего полива
    String LightsOn = "05:00:00"; // Время включения освещения
    String LightsOff = "22:00:00"; // Время выключения освещения
    #define pumpPin 6 // Определение пина для реле включения дренажного насоса
    #define waterSensorPin 2 //при отсутствии воды замыкается на GND
    #define pump_ON digitalWrite (pumpPin, HIGH)
    #define pump_OFF digitalWrite(pumpPin, LOW)
    #define noWater digitalRead(waterSensorPin) == LOW
    unsigned long timeON;
    unsigned long workTime = 120000; // 2 минуты 
    boolean flag = true;   
    
void setup(){                                               //
    delay(300);                                             // Ждем готовности модуля отвечать на запросы
    Serial.begin(9600);                                     // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бод.
    time.begin();                                           // Инициируем работу с модулем.
    pinMode(relay, OUTPUT);
    pinMode(relay_lights, OUTPUT);
    pinMode(relay_lights2, OUTPUT);
    digitalWrite(relay, LOW);
    digitalWrite(relay_lights, HIGH);
    digitalWrite(relay_lights2, HIGH);
    pinMode(waterSensorPin, INPUT_PULLUP);
    pinMode(pumpPin, OUTPUT);
    
}                                                           //
void loop(){                                                //
    if(millis()%1000==0){                                   // Если прошла 1 секунда.
      Serial.println(time.gettime("d-m-Y, H:i:s, D"));      // Выводим время.
      delay(1);                                             // Приостанавливаем скетч на 1 мс, чтоб не выводить время несколько раз за 1мс.
    }                                                       //
    RT = time.gettime("H:i:s");
    if (RT == TimeOn){
     digitalWrite(relay, HIGH);
    }

if (RT == TimeOff){  
  digitalWrite(relay, LOW);
  } 

if (RT == TimeOn2){
  digitalWrite(relay, HIGH);
}
if (RT == TimeOff2){
  digitalWrite(relay, LOW);
}

if (RT == TimeOn3){
  digitalWrite(relay, HIGH);
}

if (RT == TimeOff3){
  digitalWrite(relay, LOW);
}
if (noWater && flag){
      pump_ON;
      timeON = millis();
      flag = false;
    }
if (millis() - timeON > workTime){
      pump_OFF;
      flag = true;
    }
if (RT == LightsOn){
    digitalWrite(relay_lights, HIGH);
    digitalWrite(relay_lights2, HIGH);
}
if (RT == LightsOff){
    digitalWrite(relay_lights, LOW);
    digitalWrite(relay_lights2, LOW);
}
} 

 

b707
Offline
Зарегистрирован: 26.05.2017

у вас для первого полива время включения и выключения совпадают. Не знаю, важно ли это для вас - но как-то "неакууратненько"

SamFer
Offline
Зарегистрирован: 22.04.2019

Да, действительно помарка. Не заметил сразу. Я просто вчера перенастраивал время и не углядел. Спасибо, что обратили внимание! 

 

А по основному вопросу может быть есть какие-то мысли? Из-за чего такая штука может происходить?

b707
Offline
Зарегистрирован: 26.05.2017

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

кривовато написано => кривовато работает (работает через раз). Явные ошибки не в синтаксе, явные ошибки в проектировании программы.

SamFer
Offline
Зарегистрирован: 22.04.2019

Согласен, что программа кривоватая, потому что знания у меня кривоватые. НО она работала несколько месяцев, а тут БАЦ и перестала хорошо работать ))))

Сейчас еще раз подключился к Ардуино, все перепроверил, прогнал несколько циклов включения-выключения полива - все четко работает, по секундам. Свет так же по таймингу включается-выключается. Как-будто какая-то барабашка. Посмотрю завтра утром, может нормально будет работать. 

 

Еще вот что я заметил. Когда подключается к последовательному порту, чтобы мониторить время на RTC, то время обновляется не каждую секунду, как это по идее должно быть (судя по коду), а каждые несколько секунд, иногда подвисает на секунд двадцать. Но при этом это зависание не влияет на срабатывание включения-выключения, я по таймеру засекал.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

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

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

SamFer
Offline
Зарегистрирован: 22.04.2019

Если честно, все что после "ПС" я не понял )))))

Какие автоматы?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

А как именно реализована схема включения реле полива? Какое именно реле применяется?

SamFer
Offline
Зарегистрирован: 22.04.2019

Схема такая:

Насос 12 Вольт подключен к блоку питания на 12 Вольт. К ардуино подключено вот такое реле (https://iarduino.ru/shop/Expansion-payments/rele-elektromehanicheskoe-do-250v-10-a-1--kanal-5v.html) (это не реклама, просто именно его и покупал там). Реле подключено к пину 6 на Ардуно. И вот когда наступает время полива, которая сравнивается с RTC включается реле и идет полив. Так же вылючается.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

qwone пишет:

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

Тоже обратил на это внимание, идёт сравнение на совпадение (четкое совпадение) «несравнимых величин». 

Однакоесли раньше работало - значит сейчас что то «не даёт работать». Не исключено что погрешности в секунду вносит что из исполнимой цепи. 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

SamFer пишет:

Если честно, все что после "ПС" я не понял )))))

Какие автоматы?

 https://www.youtube.com/watch?v=0L0catcHqy8   Вот и в программировании такая же штука есть.

SamFer
Offline
Зарегистрирован: 22.04.2019

Спасибо за инфу! Буду просвещатся!

SamFer
Offline
Зарегистрирован: 22.04.2019

Может тогда поставить знак не "==" времени включения, а "=>"?

И еще, может нюанс с тем, что при мониторинге серийного порта время не каждую секунду обновляется? Но тоже пока не ложится как теория, так как при тестовых прогонах это не влияло на включение-выключение.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

BOOM пишет:
Однакоесли раньше работало - значит сейчас что то «не даёт работать». Не исключено что погрешности в секунду вносит что из исполнимой цепи. 

Возмите обычный будильник. Вы его поставили на 6 часов. Пусть есть некий механизм который контролирует совпадение. Точно идет звонок. Но если этот механизм проспал. То звонка уже в этот день не будет. Поэтому и проверяют на точно и поздно. Если поздно на секунду то все равно запускают звонок

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

SamFer пишет:

Может тогда поставить знак не "==" времени включения, а "=>"?

Со стринговыми переменными это не выйдет.

SamFer
Offline
Зарегистрирован: 22.04.2019

qwone пишет:

SamFer пишет:

Может тогда поставить знак не "==" времени включения, а "=>"?

Со стринговыми переменными это не выйдет.

 

А пройдет ли такой финт:

объявить стринговую переменную со временем, далее некая переменная преобразует стринг в юникс и сравнивает юникс время расписания с юникс текущего времени?

 

Или я херню сейчас написал?)

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

qwone пишет:

BOOM пишет:
Однакоесли раньше работало - значит сейчас что то «не даёт работать». Не исключено что погрешности в секунду вносит что из исполнимой цепи. 

Возмите обычный будильник. Вы его поставили на 6 часов. Пусть есть некий механизм который контролирует совпадение. Точно идет звонок. Но если этот механизм проспал. То звонка уже в этот день не будет. Поэтому и проверяют на точно и поздно. Если поздно на секунду то все равно запускают звонок

Так я об этом и говорил, я это понимаю. Только в данной реализации такое «или» не возможно. 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

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

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

qwone пишет:

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

Другими словами - используйте интервалы времени, а не привычные для человека «штампы». 

SamFer
Offline
Зарегистрирован: 22.04.2019

То есть, вы предлагаете использовать millis вместо RTC?

https://youtu.be/kTMjaj7U3RY - вот видео как сейчас работает. Извините за мою ногу и качество видео. Я настроел полив каждый 15 секунд, чтобы проверить. И все включалось четко. Но видимо где-то сбоит.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

А чем вам millis() плохи? )))

b707
Offline
Зарегистрирован: 26.05.2017

SamFer пишет:

То есть, вы предлагаете использовать millis вместо RTC?

 

нет,  вам советуют выкинуть строки и вместо них кодировать время числами.

 

SamFer
Offline
Зарегистрирован: 22.04.2019

Да лично мне ничем не плохи))))

Просто захотелось построить на RTC и вроде как работает, но сбоит по всей видимости )))

Просто если Ардуино выключать чтобы перенастроить или там с электрикой позаниматься придется наверняка помучаться с миллис, так как не всегда ты включишь ардуно в тоже время как и выключил, а полив и свет для растений лучше по расписанию делать. Так вот у RTC своя батарейка и ничего не сбивается после отключения Ардуино ) полагаю с millis() такое не прокатит )

b707
Offline
Зарегистрирован: 26.05.2017

BOOM пишет:

А чем вам millis() плохи? )))

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

Просто непонятно, с чего ТС выбрал такую странную систему условий по времени - строками "08:00:00"

b707
Offline
Зарегистрирован: 26.05.2017

SamFer пишет:

у RTC своя батарейка и ничего не сбивается после отключения Ардуино ) полагаю с millis() такое не прокатит )

все правильно, оставьте RTC, но перейдите на числа в  представлении времени

SamFer
Offline
Зарегистрирован: 22.04.2019

Потому что время в часа сейчас в таком формате выводится, если по сериал порту мониторить, соответствено такой формат и выбрал. Это мне коллеги с формума помогли, я пару месяцев назад советовался по этому скетчу и мне сильно помогли.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

для вас RTC лучше. он не сбивается при  отключении питания 

ПС: посмотрите. #82  Может вам это пригодится.

b707
Offline
Зарегистрирован: 26.05.2017

SamFer пишет:

Потому что время в часа сейчас в таком формате выводится

и что с того? - поменяйте на числовой

SamFer пишет:
Это мне коллеги с формума помогли, я пару месяцев назад советовался по этому скетчу и мне сильно помогли.

это они или задачу не поняли, либо вы их совет по своему переиначили. Этот метод контроля интервалов однозначно плохой

SamFer
Offline
Зарегистрирован: 22.04.2019

Понял, принял, буду курить мат часть. На текущем этапе не умею переводить в числа время ))) буду учиться

SamFer
Offline
Зарегистрирован: 22.04.2019

qwone пишет:

для вас RTC лучше. он не сбивается при  отключении питания 

ПС: посмотрите. #82  Может вам это пригодится.

Буду изучать, спасибо!

b707
Offline
Зарегистрирован: 26.05.2017

SamFer пишет:

Понял, принял, буду курить мат часть. На текущем этапе не умею переводить в числа время ))) буду учиться

изучите свою библиотеку RTC - в любой подобной библиотеке есть методы, возвращающие отдельно часы, отдельно минуты и отдельно секунды в виде целых чисел. А из этих данных, думаю, числовое время в любом удобном вам формате вы рассчитаете сами...

SamFer
Offline
Зарегистрирован: 22.04.2019

Спасибо большое за советы!

Буду изучать.

bwn
Offline
Зарегистрирован: 25.08.2014

SamFer пишет:

Согласен, что программа кривоватая, потому что знания у меня кривоватые. НО она работала несколько месяцев, а тут БАЦ и перестала хорошо работать ))))

Чудес, имхо, не бывает. По личному опыту, если что-то работало без нареканий несколько месяцев, а потом, вдруг (при условии, что действительно софт не трогали), стало работать некорректно - иди тщательно мыть плату и датчики.

SamFer
Offline
Зарегистрирован: 22.04.2019

Согласен! Я в чудеса тоже не верю.

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

Я сейчас грешу на тройник. Раньше все подключал к розетке, а теперь через тройник и возможно что-то там происходит. Но я не уверен. Надо будет копаться, но куда пока не знаю)))

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Если память не тикеть, то вачдог тебе в сумку

SamFer
Offline
Зарегистрирован: 22.04.2019

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

Все же тема в "Песочнице", а значит я нуб)))

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Если вешается не из-за утечек памяти или неверной работы с указателями, а из-за сбоев по питанию, то правильная настройка watchdog может помочь тебе.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Опять нипанятна?

SamFer
Offline
Зарегистрирован: 22.04.2019

Теперь понятно, спасибо!))))

Вот читаю про watchdog. Не все так просто. Оказывается не на всех ардуино он работает корректно и надо с бубнами потанцевать. Но вроде пишут, что на Уно (а у меня именно такая) работает все нормально. Но у меня уно не на оригинальном чипе. Он не вытянутый, то есть не Atmega на сколько я понимаю. Будет ли там работать этот вотчдог. Надо будет протестить. 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Будет. Потестено.

SamFer
Offline
Зарегистрирован: 22.04.2019

Супер! Тогда пойду прописывать код)) спасибо!

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

DetSimen пишет:

Если вешается не из-за утечек памяти или неверной работы с указателями, а из-за сбоев по питанию, то правильная настройка watchdog может помочь тебе.

Старая народная мудрость гласит - "Если у вас была проблема и вы решили использовать ватчдог что бы ее решить, то теперь у вас будет две проблемы."

 

Может попытаться решить проблему с зависанием?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

asam пишет:

DetSimen пишет:

Если вешается не из-за утечек памяти или неверной работы с указателями, а из-за сбоев по питанию, то правильная настройка watchdog может помочь тебе.

Может попытаться решить проблему с зависанием?

Зависит от ТС.  Но если зависания праисходют от искрения в тройнике, который отчего-то поменять трудно, или вапще невозможно, тут то на сцэну и выскочит вачдог, как чорт из табакерки. 

Лопатить чужой код спахмелья, выискивая утечки, как по мне, - так себе занятие. 

DAK
Offline
Зарегистрирован: 15.08.2019

Что то мне подсказывает, что данный код является бедой этого шедевра простоты

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

Вот прям нутром чую.

А как это побороть, для начала надо задать себе вопрос, нужна ли такая точность, до 1 секунды?

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

#include <Wire.h>                                       // Библиотека iarduino_RTC будет использовать методы и функции библиотеки Wire.

#include <iarduino_RTC.h>                                   // Подключаем библиотеку iarduino_RTC для работы с модулями реального времени.
    iarduino_RTC time(RTC_DS3231);                          // Объявляем объект time для работы с RTC модулем на базе чипа DS3231, используется аппаратная шина I2C
                                                            
    int relay = 5; // Определение пина для реле включения насоса полива
    int relay_lights = 3; // Определение пина для реле включения света певрого стеллажа
    int relay_lights2 = 4; // Определение пина для реле включения света второго стеллажа
    String RT = "50";
    String TimeOn = "00:00"; // Время включения первого полива
    String TimeOff = "00:02"; // Время выключения первого полива
    String TimeOn2 = "08:00"; // Время включения второго полива
    String TimeOff2 = "08:02"; // Время выключения второго полива
    String TimeOn3 = "16:00"; // Время включения третьего полива
    String TimeOff3 = "16:02"; // Время выключения третьего полива
    String LightsOn = "05:00"; // Время включения освещения
    String LightsOff = "22:00"; // Время выключения освещения
    #define pumpPin 6 // Определение пина для реле включения дренажного насоса
    #define waterSensorPin 2 //при отсутствии воды замыкается на GND
    #define pump_ON digitalWrite (pumpPin, HIGH)
    #define pump_OFF digitalWrite(pumpPin, LOW)
    #define noWater digitalRead(waterSensorPin) == LOW
    unsigned long timeON;
    unsigned long workTime = 120000; // 2 минуты 
    boolean flag = true;   
    
void setup(){                                               //
    delay(300);                                             // Ждем готовности модуля отвечать на запросы
    Serial.begin(9600);                                     // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бод.
    time.begin();                                           // Инициируем работу с модулем.
    pinMode(relay, OUTPUT);
    pinMode(relay_lights, OUTPUT);
    pinMode(relay_lights2, OUTPUT);
    digitalWrite(relay, LOW);
    digitalWrite(relay_lights, HIGH);
    digitalWrite(relay_lights2, HIGH);
    pinMode(waterSensorPin, INPUT_PULLUP);
    pinMode(pumpPin, OUTPUT);
    
}                                                           //
void loop(){                                                //
    delay(1000) ;                           // Тормозим скетч на 1 секунду, чтобы лишний раз не мучить контроллер бесполезными операциями
    Serial.println(time.gettime("d-m-Y, H:i:s, D"));      // Выводим время.
    RT = time.gettime("H:i");
    if (RT == TimeOn){
     digitalWrite(relay, HIGH);
    }

if (RT == TimeOff){  
  digitalWrite(relay, LOW);
  } 

if (RT == TimeOn2){
  digitalWrite(relay, HIGH);
}
if (RT == TimeOff2){
  digitalWrite(relay, LOW);
}

if (RT == TimeOn3){
  digitalWrite(relay, HIGH);
}

if (RT == TimeOff3){
  digitalWrite(relay, LOW);
}
if (noWater && flag){
      pump_ON;
      timeON = millis();
      flag = false;
    }
if (millis() - timeON > workTime || millis() - timeON < 0){ //ВОТ ТУТ МОЖЕТ ЕЩЁ ОДНА СОБАКА ЖДАТЬ, почитайте про миллис, 
      pump_OFF;                                             //раз в 50 дней он переполняется и начинает работать с нуля
      flag = true;
    }
if (RT == LightsOn){
    digitalWrite(relay_lights, HIGH);
    digitalWrite(relay_lights2, HIGH);
}
if (RT == LightsOff){
    digitalWrite(relay_lights, LOW);
    digitalWrite(relay_lights2, LOW);
}
} 

 

b707
Offline
Зарегистрирован: 26.05.2017

DAK - по комментам в вашем коде о переполнении миллис - если интервалы вычислять правильно, оно(переполнение) никак не влияет на работу программы. И до 50 суток, и после. и прямо во время перехода через ноль интервалы будут работать верно

У вас в коде - правильно

SamFer
Offline
Зарегистрирован: 22.04.2019

Спасибо за комментарий!

Попробуй сегодня протестировать.

 

Еще вопрос. В коде стоит два раза delay. Первый раз на 300, второй (как вы поставили) на 1000.

Вообще имеет смысл два раза delay указывать? И нужен ли он в первом случае?

SamFer
Offline
Зарегистрирован: 22.04.2019

Спасибо за комментарий!

SamFer
Offline
Зарегистрирован: 22.04.2019

asam пишет:

DetSimen пишет:

Если вешается не из-за утечек памяти или неверной работы с указателями, а из-за сбоев по питанию, то правильная настройка watchdog может помочь тебе.

Старая народная мудрость гласит - "Если у вас была проблема и вы решили использовать ватчдог что бы ее решить, то теперь у вас будет две проблемы."

 

Может попытаться решить проблему с зависанием?

 

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

SamFer
Offline
Зарегистрирован: 22.04.2019

DetSimen пишет:

asam пишет:

DetSimen пишет:

Если вешается не из-за утечек памяти или неверной работы с указателями, а из-за сбоев по питанию, то правильная настройка watchdog может помочь тебе.

Может попытаться решить проблему с зависанием?

Зависит от ТС.  Но если зависания праисходют от искрения в тройнике, который отчего-то поменять трудно, или вапще невозможно, тут то на сцэну и выскочит вачдог, как чорт из табакерки. 

Лопатить чужой код спахмелья, выискивая утечки, как по мне, - так себе занятие. 

 

Нет, конечно. Не надо мой код лопатить и я меньше всего хотел бы кого-то напрягать. То, что все присутствующие здесь так или иначе направляют меня давая пищу для размышления и изучения - уже очень ценно. Спасибо! )

DAK
Offline
Зарегистрирован: 15.08.2019

b707 пишет:

DAK - по комментам в вашем коде о переполнении миллис - если интервалы вычислять правильно, оно(переполнение) никак не влияет на работу программы. И до 50 суток, и после. и прямо во время перехода через ноль интервалы будут работать верно

У вас в коде - правильно

Представим, что в исходном коде таймер 71-то строки зафиксируется за 1 секунду до переполнения условия

тогда таймер отключения  (74 строка) не сработает никогда, просто не должно сработать по определению.

millis()-timeON будет отрицательным почти 50 дней.

он бы висел вечно, пока я туда не дописал условие (если я правильно читаю мануалы, то я не зря добавил условие)