Прерывание прерывания

krosslove
Offline
Зарегистрирован: 12.06.2015
int rele = 6;
int rele2 = 7;
volatile int state = HIGH;

void setup()
{
   
pinMode(rele, OUTPUT);
pinMode(rele2, OUTPUT);
 attachInterrupt(1, grink, RISING);
 attachInterrupt(0, srink, RISING);
}
 
void loop()
{
 digitalWrite(rele, state);
 digitalWrite(rele2, state);
}
 
void grink()
{
 digitalWrite(rele, LOW);   
   delay(10000);
    digitalWrite(rele, HIGH);  
   delay(10000); digitalWrite(rele, LOW);  
   delay(10000);
    digitalWrite(rele, HIGH);  
   delay(10000); digitalWrite(rele, LOW);   
   delay(10000);
    digitalWrite(rele, HIGH);  
   delay(10000); digitalWrite(rele, LOW); 
   delay(10000);
    digitalWrite(rele, HIGH);  
   delay(10000); digitalWrite(rele, LOW);  
   delay(10000);
    digitalWrite(rele, HIGH);  
   delay(10000); digitalWrite(rele, LOW);   
   delay(10000);
    digitalWrite(rele, HIGH);  
   delay(10000); digitalWrite(rele, LOW);   
   delay(10000);
    digitalWrite(rele, HIGH);  
   delay(10000);
}

void srink()
{
 digitalWrite(rele2, LOW); 
   delay(10000);
    digitalWrite(rele2, HIGH);  
   delay(10000);
    digitalWrite(rele2, LOW);   
   delay(10000);
    digitalWrite(rele2, HIGH);  
   delay(10000); digitalWrite(rele2, LOW); 
   delay(10000);
    digitalWrite(rele2, HIGH);  
   delay(10000); digitalWrite(rele2, LOW);  
   delay(10000);
    digitalWrite(rele2, HIGH);  
   delay(10000); digitalWrite(rele2, LOW);  
   delay(10000);
    digitalWrite(rele2, HIGH);  
   delay(10000); digitalWrite(rele2, LOW);  
   delay(10000);
    digitalWrite(rele2, HIGH);  
   delay(10000); digitalWrite(rele2, LOW); 
   delay(10000);
    digitalWrite(rele2, HIGH);  
   delay(10000); digitalWrite(rele2, LOW);   
   delay(10000);
    digitalWrite(rele2, HIGH);  
   delay(10000); digitalWrite(rele2, LOW);  
   delay(10000);
    digitalWrite(rele2, HIGH);  
   delay(10000);
}

Есть такой код, скажите, пожалуйста, можно ли как то сделать так, чтобы при выполнении функции grink при нажатии на кнопку второго прерывания тут же активизировлась бы функция srink. Или такое дело решается по другому? Задача такая - 12 датчиков, при срабатывании любого из них активизируется подпрограмма, которая в запрограммированном порядке обрабатывает четыре реле. Нужно, чтобы при работе подпрограммы, при срабатывании другого датчика сразу же выполнялась бы дргая подпрограмма а эта завершалась.

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Нельзя прервать одно прерывание другим. Второе прерывание не сработает, пока не вышли из обработчика первого. Точнее взведётся флаг второго прерывания и будет ждать в очереди завершения первого, т.е. второе прерывание не потеряется.

У Вас неправильная концепция. Нельзя в обработчики прерывания пихать большие задержки, они должны выполняться как можно быстрее. Заведите переменные-флаги и только меняйте их состояние в обработчике прерывания. А в цикле loop проверяйте состояние этих переменных и в зависимости от него выполняйте нужные действия, например вызов функций. Но всё равно, пока не завершиться функция с кучей delay, другая не вызовется. Отказывайтесь от delay и используйте millis. И не обязательно кучу раз подряд повторять digitalWrite(rele, HIGH); digitalWrite(rele, LOW), можно просто инвертировать уровень.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Можно, но не так. И да, концепция неверна.

krosslove
Offline
Зарегистрирован: 12.06.2015

Тогда смысла нет заводить переменные - флаги, раз всё равно ждать конца обработки подпрограммы. А делей стоит просто для наглядности - примерно столько времени будет работать каждая из 12 подпрограмм - там ничего сложного - просто последовательное включение мощных нагрузок. Если вместо делей использовать миллис - будет ли работать прерывание как нужно? Можно даже не завершать предыдущую полпрограмму - главное, при пересечении датчика включить следующую, а та пусть завершается. Жека-M, не могли бы выслать свой идентификатор личной связи в одной из доступных для общения систем на почту krosslove@gmail.com? У меня для вас есть предложение.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

ТС привёл шедевральный пример того, как не надо работать с прерываниями вообще :) Ничего, что в прерываниях millis не работает? А вы там delay устраивать пытаетесь?

Читать до посинения: https://www.arduino.cc/en/Reference/AttachInterrupt

krosslove
Offline
Зарегистрирован: 12.06.2015

Это я что первое в голову пришло написал. Значит в этом случае нужно делать код в лупе, плата дуе, хватит мощности всё быстро обрабатывать? Почитал про прерывания - получается, что никак нельзя сделать многозадачность.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

krosslove, вам нужно СИ подучить, хотя бы основные операторы if, for, while. Тогда и мощности сразу на всё хватит, и многозадачность заработает :)

krosslove
Offline
Зарегистрирован: 12.06.2015
// Объявление номера пина для каждого из реле
int rele1 = 1;
int rele2 = 2; 
int rele3 = 3;

// Задаем первоначальный уровень (значение) выхода каждого из реле, которое будет устанавливаться при включении или сбросе платы контроллера. В данном случае все реле в положении "Выкл"
int rele1State = LOW;
int rele2State = LOW;
int rele3State = LOW;

// Объявляем переменные последнего значения прошедшего с начала запуска программы времени ( перед лупом делаем ее 0 - а надо ли? ).

long prevtime1 = 0;
long prevtime2 = 0;
long prevtime3 = 0;

// Обозначаем переменные, отвечающие за время задержки переключения реле.
long time1 = 1000;
long time2 = 2000;
long time3 = 3000;



void setup() {
  // Обозначаем физические разъемы платы контроллера как "Выход" для того, чтобы можно было подавать один из логических (0 вольт или 5 вольт) уровней для управления реле.
pinMode(rele1, OUTPUT);
pinMode(rele2, OUTPUT);
pinMode(rele3, OUTPUT);

}

void loop() {

  // Присваиваем переменной значение времени, прошедшего с начала включения платы контроллера для последующего сравнения.
  
unsigned long nexttime = millis();

// Сравниваем - если время с начала включения платы (nexttime) минус время последнего включения rele1 (prevtime1) больше значения (а оно станет больше в тот момент, когда функция millis отсчитает 1000 миллисекунд ) установленной ( в time1 ) задержки то...

if (nexttime - prevtime1 > time1) {
  
// ... присваиваем переменной prevtime1 (последнее время включения реле) значение nexttime (настоящее время, прошедшее с начала включения платы) для того, чтобы отсчет времени следующего включения реле начался с момента его последнего включения. 

prevtime1 = nexttime;

// Включаем реле, подачей на выход rele1State высокого уровня.

rele1State = HIGH;

}
// Если же условие в if не выполняется - программа доходит вот до этого места и выполняется снова, до тех пор, пока миллис не даст нам 1000 отсчетов.


// Тот же самый, с поправками по адресам исполнения, код, для двух других реле.

if (nexttime - prevtime2 > time2)
{
  prevtime2 = nexttime;
  rele2State = HIGH;
}

if (nexttime - prevtime3 > time3)
{
  prevtime3 = nexttime;
  rele3State = HIGH;
}

}

Вот, почитав по теме материалов, сделал вот такой код - пока для того, чтобы управлять временем включения каждого реле без использования делей. На плате не проверял еще - правильно ли я сделал? Достаточно ли будет быстродействия платы для отслеживания еще 12 таких блоков? Теперь мне надо объединить эти реле в группу (функцию?), чтобы вызывать их поочередное включение с помощью нажатия кнопки...

Logik
Offline
Зарегистрирован: 05.08.2014

А ведь можете, когда хотите.  Быстродействия хватит и на 120. А если еще заметить 3 однотипных куска кода (а должно быть вроде 12), которые так и просят чтоб с ними чтото сделали... можна функцию, но в данном случае лучше массив и цикл.

krosslove
Offline
Зарегистрирован: 12.06.2015

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

krosslove
Offline
Зарегистрирован: 12.06.2015
// Задаем имя класса

class Reles

// Объявляем переменные (почему нельзя объявить переменные до объявления имени класса?)

{
  int rele ; // Номер выхода для управления реле
  long prevtime ; // Время последнего включения реле для правильного отсчета следующих циклов включения.
  int releState ; // Объявление переменной для управления состоянием реле.
  long times ; // Обозначаем переменную, отвечающую за время задержки переключения реле.

// Объявляем так называемый "спецификатор доступа" - "public" -  в данном случае он означает, что все данные и тип их выполнения будут доступны всем функциям в программе, в противном случае, если указать, например "private" вместо "public", то данные и методы их выполнения будут доступны только внутри объявленного класса.

public:

// Инициализируем переменные для последующей с ними работы. "int pin" - это переменная для последующего указания номера выхода контроллера, "long times" - это переменная для указания времени задержки включения реле
  
  Reles (int pin, long times){
  
// Присваиваем переменной "rele" значение "pin" 

  rele = pin;

// Объявляем выходы управления реле

 pinMode(rele, OUTPUT);


// Объявляем значения остальных переменных для того, чтобы программа предсказуемо запустилась.

releState=LOW; // Устанавливаем начальную позицию реле в положение "Выкл".
prevtime=0; // Устанавливаем начльное время отсчета для задержки включения реле.

}

// Пишем функцию (WkluchenieRele) с переменными, которые уже обозначены (кроме переменной "nextime") и инициализированы, значения которых будут потом подставляться при вызове этой самой функции в нужном месте программы (стр. 64 и 78). 

void WkluchenieRele() {

 unsigned long nexttime = millis(); // Присваиваем переменной "nexttime" значение времени, прошедшее с момента включения платы с помощью функции "millis".
 
 if (nexttime - prevtime > times) // Если время, прошедшее со времени включения платы минус время последнего включения реле больше обозначенного значения "times" то...
{
  
  //... присваиваем значение времени с начала включения платы переменной "prevtime" для дальнейшего правильного счета времени задержки включения реле (хотя зачем, если нет кода отключения реле?)
  
  prevtime = nexttime;
  
  // Присваиваем переменной "releState" высокое значение (Вкл).
  
  releState = HIGH;

  // "Включаем" нужный вывод командой "releState" - на данном этапе он не включится, потому что это не LOOP место программы плюс не объявлены точные цифровые значения переменных.

  digitalWrite(rele, releState);
}
}
};


// Присваиваем переменным "rele1", "rele2" и "rele3" значения номеров портов и задержки.

Reles rele1(1, 1000);
Reles rele2(2, 1000);
Reles rele3(3, 1000); 


void setup() {
  

}

void loop() {

// Включаем или не включаем реле с помощью вызова функции "WkluchenieRele()", в которую подставляются данные из строчек "Reles rele1 (1, 1000);Reles rele2 (2, 1000);Reles rele3 (3, 1000);"

rele1.WkluchenieRele();
rele2.WkluchenieRele(); 
rele3.WkluchenieRele();
}

Вот с помощью классов убрал повторяющийся код - так называемое объектно-ориентированное программирование в С++. Не могу пока проверить, интересно - заработает на железе?

Вопрос по 62 строке - могут имена классов объявлять переменные?

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

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

и, правда, почему нельзя? кто запретил?

лично мне разрешено объявлять переменные хоть на соседском заборе - пишу "Обама-чмо", но оно-зараза работает внутри класса Великая Россия, но никак не Америка.

кто знает, на каком заборе нужно написать, что бы в классе "Цивилизованное человечество" заработало?

krosslove
Offline
Зарегистрирован: 12.06.2015

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

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

krosslove пишет:

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

походу, сам себя запутал... переменные с разными именами и, внезапно, перехлёст. чего с чем перехлёст?

*почему бы самому себе не ответить на свой простой вопрос, написав два класса и заюзав в этих классах переменные с разными и совпадающими именами?

чисто теоретически, смогут ли как-то конфликтовать две переменные class1.а и class2.а или class1.а и class2.b ?

krosslove
Offline
Зарегистрирован: 12.06.2015

Пока проверить не могу. Но чисто теоретически конфликта быть не может - программа при работе читает имена переменных. Но пример с одного из сайтов на с++ показывает, что переменные объявляются а классе. Хоя, там не написано, что это обязательно. Вот я и пытаюсь выяснить, пока руки не дошли самому проверить, имеет ли это значение, раз в примере было сделано именно так.

krosslove
Offline
Зарегистрирован: 12.06.2015

Еще мне непонятно, что происходит в строках 19-27. Для чего нужно присваивать в 23 строке переменной rele значение переменной pin, если в 27 строке можно вместо rele просто вставить pin?

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

krosslove пишет:
Пока проверить не могу. Но чисто теоретически конфликта быть не может - программа при работе читает имена переменных. Но пример с одного из сайтов на с++ показывает, что переменные объявляются а классе. Хоя, там не написано, что это обязательно. Вот я и пытаюсь выяснить, пока руки не дошли самому проверить, имеет ли это значение, раз в примере было сделано именно так.

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

krosslove
Offline
Зарегистрирован: 12.06.2015

Клапауций 232 пишет:

krosslove пишет:
Пока проверить не могу. Но чисто теоретически конфликта быть не может - программа при работе читает имена переменных. Но пример с одного из сайтов на с++ показывает, что переменные объявляются а классе. Хоя, там не написано, что это обязательно. Вот я и пытаюсь выяснить, пока руки не дошли самому проверить, имеет ли это значение, раз в примере было сделано именно так.

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


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

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

krosslove пишет:
здесь не место...

здесь не место для публикации своего бреда.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

krosslove пишет:
Пока проверить не могу. Но чисто теоретически конфликта быть не может - программа при работе читает имена переменных. Но пример с одного из сайтов на с++ показывает, что переменные объявляются а классе. Хоя, там не написано, что это обязательно. Вот я и пытаюсь выяснить, пока руки не дошли самому проверить, имеет ли это значение, раз в примере было сделано именно так.

Давайте закругляться с холиварами, мало их тут было? Я вам выделил то, что предыдущий автор назвал "бредом". Это иначе - не называется, и обижаться тут не на что. Никакая скомпилированная (а тут это только так) программа никогда не читает имена никаких переменных. Имена замещаются адресами в ОЗУ ещё на стадии компиляции. Собственно они нужны только автору, а никак не "вычислителю".

И далее. Переменные конечно могут "объявляться в классе", но только статические глобалы всего класса, то бишь "единые" для всех объектов этого класса. У объектов в классах объявляются СВОЙСТВА (поля структуры переменной - объекта) и методы работы с ними.

Про такое в объявлении класса "писать не принято".. в смысле это некий "нонсенс" в целом.

Отсюда, давайте отделим "мух от котлет":

1. Имя переменной - это человекоудобное представление АДРЕСА некоторого места в памяти, где можно "что-то хранить" и возможно даже "изменять" через оператор присваивания .. некий "ящичек" в комоде всего ОЗУ микроконтроллера.

2. Размещение имен в памяти (назначение им адресов) производится постепенно, в процессе компиляции, сборки и даже выполнения программы (локальные переменные и/или динамическая куча). И, чем раньше в этом процессе возникает решение "куда поместить" - тем лучше, и в этом смысле: глобальные и статические в блоках переменные - предпочтительней динамического размещения, в т.ч. и неявным размещением через new. Локалы, как обычно разговор отдельный и "тихо курят в сторонке".

3. статические, общие переменные класса, а равно как свойства объектов класса - создаются (учитываются компилятором и системой сборки) автоматически, как только Вы указываете использование того или иного класса. Так сказать и вовсе "без спросу": обязательно оно вам или нет.

krosslove
Offline
Зарегистрирован: 12.06.2015

Arhat109-2 пишет:

krosslove пишет:
Пока проверить не могу. Но чисто теоретически конфликта быть не может - программа при работе читает имена переменных. Но пример с одного из сайтов на с++ показывает, что переменные объявляются а классе. Хоя, там не написано, что это обязательно. Вот я и пытаюсь выяснить, пока руки не дошли самому проверить, имеет ли это значение, раз в примере было сделано именно так.

Давайте закругляться с холиварами, мало их тут было? Я вам выделил то, что предыдущий автор назвал "бредом". Это иначе - не называется, и обижаться тут не на что. Никакая скомпилированная (а тут это только так) программа никогда не читает имена никаких переменных. Имена замещаются адресами в ОЗУ ещё на стадии компиляции. Собственно они нужны только автору, а никак не "вычислителю".

И далее. Переменные конечно могут "объявляться в классе", но только статические глобалы всего класса, то бишь "единые" для всех объектов этого класса. У объектов в классах объявляются СВОЙСТВА (поля структуры переменной - объекта) и методы работы с ними.

Про такое в объявлении класса "писать не принято".. в смысле это некий "нонсенс" в целом.

Отсюда, давайте отделим "мух от котлет":

1. Имя переменной - это человекоудобное представление АДРЕСА некоторого места в памяти, где можно "что-то хранить" и возможно даже "изменять" через оператор присваивания .. некий "ящичек" в комоде всего ОЗУ микроконтроллера.

2. Размещение имен в памяти (назначение им адресов) производится постепенно, в процессе компиляции, сборки и даже выполнения программы (локальные переменные и/или динамическая куча). И, чем раньше в этом процессе возникает решение "куда поместить" - тем лучше, и в этом смысле: глобальные и статические в блоках переменные - предпочтительней динамического размещения, в т.ч. и неявным размещением через new. Локалы, как обычно разговор отдельный и "тихо курят в сторонке".

3. статические, общие переменные класса, а равно как свойства объектов класса - создаются (учитываются компилятором и системой сборки) автоматически, как только Вы указываете использование того или иного класса. Так сказать и вовсе "без спросу": обязательно оно вам или нет.

 

Cпасибо большое, про классы более менее понял, читаю усиленно, когда время есть. На очереди статические-динамические переменные.

Проверил последний код - не заработал на железе, пришлось подправить и немного модернизировать. Вот, что получилось. В этом коде  - должно:

 - при замыкании датчика на 8 ноге платы последовательно включиться 4 реле с заданным пользователем временем.

Сейчас же это происходит только если датчик включить сразу, после подачи питания на плату. Это из - за того, что  привязка отсчета сделана на millis. Соответственно, если мы подождем после включения платы некоторое время, которое равняется сумме установленного пользователем времени на всех 4 реле - то при нажатии датчика они сработают все одновременно. А нужно так, что если даже плата стояла включенной час - реле начинали отсчет времени относительно датчика и друг друга только по срабатыванию датчика. Копаю в этом направлении сейчас, но пока туго((...

 

// Задаем имя класса

class Reles

// Объявляем переменные (почему нельзя объявить переменные до объявления имени класса?)

{
  int rele ; // Номер выхода для управления реле
  int releState ; // Объявление переменной для управления состоянием реле.
 long times ; // Обозначаем переменную, отвечающую за время задержки переключения реле.

 
// Объявляем так называемый "спецификатор доступа" - "public" -  в данном случае он означает, что все данные и тип их выполнения будут доступны всем функциям в программе, в противном случае, если указать, например "private" вместо "public", то данные и методы их выполнения будут доступны только внутри объявленного класса.

public:

// Инициализируем переменные для последующей с ними работы. "int pin" - это переменная для последующего указания номера выхода контроллера, "long timese" - это переменная для указания времени задержки включения реле
  
  Reles (int pin, long timese){
  
// Присваиваем переменной "rele" значение "pin" 

  rele = pin;

// Присваиваем переменной "times" значение "timese" 
  
  times = timese;

  
// Объявляем выходы управления реле

 pinMode(rele, OUTPUT);
 
 // Задаем начальное значение реле при включении платы ( в этом случае "HIGH" - это выключено )
 
digitalWrite(rele, HIGH);

}

// Пишем функцию (WkluchenieRele) с переменными, которые уже обозначены (кроме переменной "nextime") и инициализированы, значения которых будут потом подставляться при вызове этой самой функции в нужном месте программы. 

void WkluchenieRele() {
 
  if(digitalRead(8) == LOW){
 
 unsigned long nexttime = millis(); // Присваиваем переменной "nexttime" значение времени, прошедшее с момента включения платы с помощью функции "millis".
 
 if (nexttime > times) // Если время, прошедшее со времени включения платы больше установленного времени включения реле (задается в строках 69-72) то...
{
  
  
  // Присваиваем переменной "releState" низкое значение (Вкл).
  
  releState = LOW;

  // "Включаем" нужный вывод командой "releState" 
  
  digitalWrite(rele, releState);
}
}}
};


// Присваиваем переменным "rele1", "rele2" ,"rele3" и "rele4" значения номеров портов и задержки.

Reles rele1(2, 1000);
Reles rele2(3, 2000);
Reles rele3(4, 3000); 
Reles rele4(5, 4000); 

void setup() {
   
  

}

void loop() {

// Включаем или не включаем реле с помощью вызова функции "WkluchenieRele()", в которую подставляются данные из строчек "Reles rele1 (1, 1000);Reles rele2 (2, 1000);Reles rele3 (3, 1000);"

rele1.WkluchenieRele();
rele2.WkluchenieRele(); 
rele3.WkluchenieRele();
rele4.WkluchenieRele();
 
}

 

krosslove
Offline
Зарегистрирован: 12.06.2015
  int flag=0;

// Задаем имя класса

class Reles

// Объявляем переменные (почему нельзя объявить переменные до объявления имени класса?)

{
  int rele ; // Номер выхода для управления реле
  int releState ; // Объявление переменной для управления состоянием реле.
 long times ; // Обозначаем переменную, отвечающую за время задержки переключения реле.

 
// Объявляем так называемый "спецификатор доступа" - "public" -  в данном случае он означает, что все данные и тип их выполнения будут доступны всем функциям в программе, в противном случае, если указать, например "private" вместо "public", то данные и методы их выполнения будут доступны только внутри объявленного класса.

public:

// Инициализируем переменные для последующей с ними работы. "int pin" - это переменная для последующего указания номера выхода контроллера, "long timese" - это переменная для указания времени задержки включения реле
  
  Reles (int pin, long timese){
  
// Присваиваем переменной "rele" значение "pin" 

  rele = pin;

// Присваиваем переменной "times" значение "timese" 
  
  times = timese;

  
// Объявляем выходы управления реле

 pinMode(rele, OUTPUT);
 
 // Задаем начальное значение реле при включении платы ( в этом случае "HIGH" - это выключено )
 
digitalWrite(rele, HIGH);

}

// Пишем функцию (WkluchenieRele) с переменными, которые уже обозначены (кроме переменной "nextime") и инициализированы, значения которых будут потом подставляться при вызове этой самой функции в нужном месте программы. 

void WkluchenieRele() {
 
  if(digitalRead(8) == LOW){flag=1;}
    
  if (flag==1) {
 
 unsigned long nexttime = millis()+times; // Присваиваем переменной "nexttime" значение времени, прошедшее с момента включения платы с помощью функции "millis" + заданное время включения реле.

 if (millis()>nexttime) // Если время, прошедшее со времени включения платы больше установленного времени включения реле (задается в строках 69-72) то...
{
  
  
  // Присваиваем переменной "releState" низкое значение (Вкл).
  
  releState = LOW;

  // "Включаем" нужный вывод командой "releState" 
  
  digitalWrite(rele, releState);
}
}}
};


// Присваиваем переменным "rele1", "rele2" ,"rele3" и "rele4" значения номеров портов и задержки.

Reles rele1(2, 1000);
Reles rele2(3, 2500);
Reles rele3(4, 3700); 
Reles rele4(5, 800); 

void setup() {
   
  

}

void loop() {

// Включаем или не включаем реле с помощью вызова функции "WkluchenieRele()", в которую подставляются данные из строчек "Reles rele1 (1, 1000);Reles rele2 (2, 1000);Reles rele3 (3, 1000);"

rele1.WkluchenieRele();
rele2.WkluchenieRele(); 
rele3.WkluchenieRele();
rele4.WkluchenieRele();
 
}

Почему не работает включение реле с дежурного режима?  То есть, если подождать после включения минуту, например и нажать кнопку - то включаться все реле, вместо того, чтобы включаться согласно задержкам в строках 70-73.

Почему не работает вот этот участок кода? Всю голову сломал...

unsigned long nexttime = millis()+times; // Присваиваем переменной "nexttime" значение времени, прошедшее с момента включения платы с помощью функции "millis" + заданное время включения реле.

 if (millis()>nexttime) // Если время, прошедшее со времени включения платы больше установленного времени включения реле (задается в строках 70-73) то...
{
  
  
  // Присваиваем переменной "releState" низкое значение (Вкл).
  
  releState = LOW;

  // "Включаем" нужный вывод командой "releState" 
  
  digitalWrite(rele, releState);
}