Задержка включения и отключения реле

Oscar
Offline
Зарегистрирован: 10.04.2020

Всем доброго времени суток! При создании моего проекта появилась необходимость в реализации задержек при срабатывании реле. При превышение некоторого порога реле должно отключится с определенной выдержкой по времени, потом через некоторое время реле должно включится и если порог на отключения выше снова отключится и больше не реле не должно включится. Delay - здесь не подойдет. Потому что нужно постоянно снимать данные с датчиков и исключается возможность редактирования временных уставок из меню, что важно. Хотя с помощью delay удалось что то подобное, но не понимаю как сделать однократное включения реле. Вроде подходит функция millis, но она у меня почему то не работает, хотя компилируется и делаю вроде все правильно. Возможно тема не новая, но думаю уже несколько дней. Возможно у вас есть какие нибуть наработки или посоветуете библиотеки, которыми пользуетесь. Заранее всем спасибо. Часть скетча прикреплю ниже.

 long timer1=3000;
 long timer2=10000;

 unsigned long  timer;

 void setup() 
 {
 }

 void loop()
 {
 if(Irms1 > Delta2 && millis() - timer >= timer1)
 {
 timer=millis();
 digitalWrite (relay_pin, HIGH);
 if(millis() - timer >= timer2)
 {
 timer=millis();
 digitalWrite (relay_pin, LOW);
 }
 }
 }

 

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

вас при прошлой регистрации на форуме не iliar звали?

по коду - обьясните, как он должен работать и что не устраивает в работе

nik182
Offline
Зарегистрирован: 04.05.2015

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

Oscar
Offline
Зарегистрирован: 10.04.2020

Нет, я зарегистрировался впервые т.к. недавно начал учится работать с ардуино.

По коду не срабатывает задержка с millis, а точнее не включается реле. Хотелось бы узнать ещё как сделать однократное включение.

Oscar
Offline
Зарегистрирован: 10.04.2020

Впринципе вариант. Флаг состояния реле у меня есть, но используется не здесь. Получается нужно сделать во втором if добавить условие состояния реле?

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

Oscar пишет:

Хотелось бы узнать ещё как сделать однократное включение.

заведите флаг, как вам выше сказали.

А что до вашего кода - он и не будет работать. потому что у вас второе условие миллис вызывается внутри первого. Это все равно что delay

Oscar
Offline
Зарегистрирован: 10.04.2020

А в первом if реально сделать задержку на подобии как в автоматических выключателях. Где ток превышает намного больше чем номинальный на некоторое время. Там необходимая задержка что бы не было лишних отключений?

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

Oscar пишет:

А в первом if реально сделать задержку

все реально. Надо только внимательно подумать над примером "блинк без делей"

nik182
Offline
Зарегистрирован: 04.05.2015

Делаете флаг превышения и проверяете ток. Если ток упал сбрасываете флаг и таймер. Повторное превышение запустит таймер с нуля. 

MaksVV
Offline
Зарегистрирован: 06.08.2015

Может это поможет

Duino A.R.
Offline
Зарегистрирован: 25.05.2015

Oscar, функция millis() возвращает значение типа unsignet long, переменную timer Вы также определили как unsignet long, а переменные timer1 и timer2, участвующих в операциях и сравнениях с timer, Вы определили как long. Зачем это так?

sadman41
Offline
Зарегистрирован: 19.10.2016

А так веселее будет через 24 дня.

Oscar
Offline
Зарегистрирован: 10.04.2020

Переменные timer1 и timer2 я определил как long потому что их значение будет меняться в меню. Я думал сделать также как и для борьбы с дребезгом контактов. Функция та же, но реализовать нужно по другому.

Oscar
Offline
Зарегистрирован: 10.04.2020

sadman41 пишет:

А так веселее будет через 24 дня.

а почему через 24?

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

Oscar пишет:

Переменные timer1 и timer2 я определил как long потому что их значение будет меняться в меню.

в чем логика? unsigned long в меню менять нельзя?

Oscar
Offline
Зарегистрирован: 10.04.2020

b707 пишет:

в чем логика? unsigned long в меню менять нельзя?

[/quote]

Возможно и можно, я ещё такого не делал. Я пробую разобраться с флагами, но не знаю как обнулить millis, судя по информации из сети это не просто.

sadman41
Offline
Зарегистрирован: 19.10.2016

А Вы из секты Обнуления Миллиса? С какой целью вступили в нее?

Oscar
Offline
Зарегистрирован: 10.04.2020

nik182 пишет:

Делаете флаг превышения и проверяете ток. Если ток упал сбрасываете флаг и таймер. Повторное превышение запустит таймер с нуля. 

Ваш способ я понял и он вроде рабочий. Но есть проблема, как сбросить таймер, ведь в сети однозначного решения я не нашел.

nik182
Offline
Зарегистрирован: 04.05.2015

Обнулять миллис не надо. Достаточно флаг события обнулить-сбросить. Интервал проверять только при поднятом флаге. При установке флага запоминать миллис в переменной времени соответствующего события. Этим автоматически обнуляется таймер события. Это только один из вариантов.  Дед давал ссылку на библиотеку таймеров. Работает отлично. Телодвижений меньше, чем выдумывать самому. 

Oscar
Offline
Зарегистрирован: 10.04.2020

Да, я читаю сейчас что он умеет. Буду пробовать прикрутить его в свой код. Я напишу тогда что получилось.

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

Oscar пишет:

не знаю как обнулить millis, судя по информации из сети это не просто.

этого просто не нужно делать

Oscar
Offline
Зарегистрирован: 10.04.2020

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

#include <GyverTimer.h>

boolean flagAPV = 1;                        
boolean flag = 0;                          

GTimer myTimer(MS);
GTimer myTimerAPV(MS);

void setup() {
pinMode(relay_pin,OUTPUT);
myTimer.setInterval(3000); 
myTimerAPV.setInterval(5000);
}

void loop() {

 if(flag==0 && I1 > I2  && myTimer.isReady() )
  {
  digitalWrite (relay_pin, HIGH);
  
  flag=1;
  myTimerAPV.start();
  }
  else if ( I1 < I2)
  {
  myTimer.reset();
  }
   
  
  if (flag==1 && flagAPV==0 && myTimerAPV.isReady())
  {
  flag=0;
  flagAPV=1;
  digitalWrite (relay_pin, LOW);
  
  }
}