Задержка выполнения millis при условии

Thorn
Offline
Зарегистрирован: 07.11.2014

Добрый день форумчане.

Часто, очень чатсто требуетсяя чтолибо завершить при условии (поднялся флаг, поменялся уровень с low на high НО не сразу а по истечении millis (времени).

Однако никак неполучается подружить его, к примеру вывод информации или запуск с использованием таймера (без delay) я уже освоил а вот тут засада. В примере скетчик который

Включает\отключает нагрев и вентиляцию в инкубаторе. Однако если со включением вентиляции ПЕРЕД включением обогрева я разобрался то вот ОТКЛЮЧЕНИЕ вентиляции после отключения нагрева нет.Отключение происходит одновременно. Хтелось бы иметь разрыв (хоть единый :) )

   unsigned long prvMlsfanOff=0;                        //Предыдущее показания вентиляции
 //   
    
    if (powerOn==1){                                    //Если питание включено
  if (temp <= heatOn) {digitalWrite(relay1,HIGH);       //Если температура меньше температуры включения
  digitalWrite(relay2,HIGH);relay1State="ON";           //Включаем обогрев и вентиляцию
  relay2State="ON";}                                    //На страничку выводим состояния
  if (temp >= heatOff) {digitalWrite(relay1,LOW);relay1State="OFF";}    //Если температура больше температуры вЫключения, вЫключаем обогрев
  if (relay1State=="OFF"){                              //И состояние обогрева вЫключено
  if (millis()-prvMlsfanOff>5000){                      //Проверяем интервал 
    prvMlsfanOff=millis(); 
    {digitalWrite(relay2,LOW);relay2State="OFF";}       //И вЫключаем вентиляцию
    }
  }  
  if ((temp-0.48) <= heatOn) {digitalWrite(relay2,HIGH);
  relay2State="ON";}      //Если температура больше на 0.48 град чем температура включения, включаем вентиляцию заранее 
}

Несмотря на указанную задержку в 5 сек (она на самом деле задается на страничке, тут просто дляудобства сделал 5 сек) - отключаются оба реле и нагрева и обдува нагревателя (вентиляции)

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

нужно задать время с какого момента отсчитывать ваши 5 секунд

prvMlsfanOff=millis(); 

и еще есть такой оператор "И"

if (relay1State=="OFF" &&  (millis()-prvMlsfanOff>5000))
{
бла.
}

 

ven-til
Offline
Зарегистрирован: 13.02.2018

prvMlsfanOff=millis();  //должно быть в восьмой строке

Thorn
Offline
Зарегистрирован: 07.11.2014

Учитывая замечания получилось вот:

    if (powerOn==1){                                    //Если питание включено
  if (temp <= heatOn) {digitalWrite(relay1,HIGH);       //Если температура меньше температуры включения
  digitalWrite(relay2,HIGH);relay1State="ON";           //Включаем обогрев и вентиляцию
  relay2State="ON";}                                    //На страничку выводим состояния
  if (temp >= heatOff) {digitalWrite(relay1,LOW);relay1State="OFF";prvMlsfanOff=millis();}    //Если температура больше температуры вЫключения, вЫключаем обогрев
  if ((relay1State=="OFF") && (millis()-prvMlsfanOff>5000)){                             //И состояние обогрева вЫключено
    prvMlsfanOff=millis();                      //Проверяем интервал 
    {digitalWrite(relay2,LOW);relay2State="OFF";}       //И вЫключаем вентиляцию
    }
  if ((temp-0.48) <= heatOn) {digitalWrite(relay2,HIGH);
  relay2State="ON";}      //Если температура больше на 0.48 град чем температура включения, включаем вентиляцию заранее 
}

Однако :)  я подобное пробовал, и отключение вентиляции происходит не спустя 5 сек а лиш после снижения температуры до того же значения в 0,48 град но от его Отключения (temp-0.48) >= heatOff

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

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

вам нужно при включении вентилятора также запускать таймер. А при истечении таймера (если он был включен) выключать вентилятор. 

Thorn
Offline
Зарегистрирован: 07.11.2014

Ох, вот это уже наталкивает меня на нужное.

Итак  таймер запускаем :

if (temp >= heatOff) {digitalWrite(relay1,LOW);relay1State="OFF";prvMlsfanOff=millis();}

после выключения вентилятора обнуляем таймер:

{digitalWrite(relay2,LOW);relay2State="OFF";prvMlsfanOff=0;}

В итоге код такой Но всё также вентилятор отключается не по времени а как мне кажется по разнице температур.

  if (temp <= heatOn) {digitalWrite(relay1,HIGH);digitalWrite(relay2,HIGH);
relay1State="ON";relay2State="ON";}  
  if (temp >= heatOff) {digitalWrite(relay1,LOW);relay1State="OFF"; prvMlsfanOff=millis();}
  if ((relay1State=="OFF") && (millis()-prvMlsfanOff>3000)){           
    prvMlsfanOff=millis(); 
    {digitalWrite(relay2,LOW);relay2State="OFF";prvMlsfanOff=0;}
  }

 

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

А если так?

if (temp <= heatOn) {
  digitalWrite(relay1, HIGH); digitalWrite(relay2, HIGH);
  relay1State = "ON"; relay2State = "ON";
}
if (temp >= heatOff) {
  digitalWrite(relay1, LOW);
  relay1State = "OFF";
  prvMlsfanOff = millis();
}
if ((relay1State == "OFF") && (millis() - prvMlsfanOff > 3000)) {
  //prvMlsfanOff = millis();
  //{
    digitalWrite(relay2, LOW);
    relay2State = "OFF";
    //prvMlsfanOff = 0;
  //}
}

P/S Ошибочка вышла, в 5 строку еще условие, relay1State = "ON", а то при каждом проходе с высокой температурой будет миллису приравнивать.

Thorn
Offline
Зарегистрирован: 07.11.2014

Господа - всё получилсоь :), итак выглядит благодаря вам вышло так:

if (powerOn == 1) {
  if (temp <= heatOn) {
    digitalWrite(relay1, HIGH); digitalWrite(relay2, HIGH);
    relay1State = "ON"; relay2State = "ON";
  }
  if (temp >= heatOff && relay1State == "ON") {
    digitalWrite(relay1, LOW);
    relay1State = "OFF";
    prvMlsfanOff = millis();
  }
  if ((relay1State == "OFF") && (millis() - prvMlsfanOff > 3000)) {
    digitalWrite(relay2, LOW); relay2State = "OFF";
  }
  if ((temp - 0.48) <= heatOn) {
    digitalWrite(relay2, HIGH);
    relay2State = "ON";
  }
}

Однако :( время задержки равно 5000 милисекунд, тоесть 5 сек а не трём, что немного печалит. Поиграю сейчас с разными значениями, проверю есть ли закономерность какая. Но главное код рабочий, малоли кому пригодится :) Логика такова, упала температура - заранее (за 0,48град) включаем вентилятор обдува лампы, смешиваем чуток воздух в зоне нагрева, далее с падением температуры включаем обогрев.... Греем и по достижении верхней температуры - отключаем нагреватель и спустя несколько секунд выключаем уже и вентилятор, некоторая инерция всеже есть в лампе (в моем случае это 12В галогенка, мелкая но её достаточно для 8 яиц в инкубаторе на подоконнике к примеру). Решил к весне добавить немного к хозяйству.

Thorn
Offline
Зарегистрирован: 07.11.2014

И ещё одно, для чего решил все включать отключать не сразу а последовательно чуток. Так как вся система силовая (вентилятор обдува лампы, вентиялтор увлажения, сервпориводы проветривания и перемешивания (через стаб на 5В) это уже повышенные токи при запуске так ещё и лампа 20Вт галогеночка потреьляет почти 2А, хотелось использовать стандартный БП на 12В и 2А - так во тего хватает как раз  и если всё включается разом то частенко esp8266 модуль перезагружается (нестрашно не малоли... вдруг подвиснет)

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

Thorn пишет:

И ещё одно, для чего решил все включать отключать не сразу а последовательно чуток. Так как вся система силовая (вентилятор обдува лампы, вентиялтор увлажения, сервпориводы проветривания и перемешивания (через стаб на 5В) это уже повышенные токи при запуске так ещё и лампа 20Вт галогеночка потреьляет почти 2А, хотелось использовать стандартный БП на 12В и 2А - так во тего хватает как раз  и если всё включается разом то частенко esp8266 модуль перезагружается (нестрашно не малоли... вдруг подвиснет)

ИМХО, лучше все делать на 220в - устройства дешевле и доступнее, токи получаются никакие, коммутировать их на порядок проще. Та же галогенка 20вт будет жрать всего 0.1А - ее любым оптосимистором включать-выключать можно.

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

в 11 строке >3000, пусть 3010, но никак не 5000. Либо секундомер такой, либо кварц паленый. И поддержу b707, нагреватели лучше через 220 коммутировать, провода в палец, не айс.))))

Thorn
Offline
Зарегистрирован: 07.11.2014

Секундомер простой :), D2 pin (gpio4) на плате распаян, в сериал у меня выводятся показатели отладочные. Вот п онему (по его активности) я и сравнивал заданные и получаемые секунды. Вобщем несильно и важно, респект что помогли - чесно говоря своим умом бился долго и никак (а начинал с электрокотла, нужно было поочередно ключать\отключать 6 тэнов) и если включать можно по температуре то отключались они разом... вот там был скаок нарпяжения) - в мастерскую ставил на ремя его.

А по инкубатору он мелкий очень на 8-10 яиц, можно сказать десктопный. Потмоу и пошёл по пути что было под рукой (все было кроме лампочки-нагревателя) в итоге. А большой если пойдёт это дело у меня коненчое по уму и с переворотом в лотках (сейчас сетка пластиковая сдвигает сервой по времени4-6 раз в день) и подготовку воздуха в отдельной камере.

и скрин управения

И есть у меня самый большой косяк в управлении. Температура у меня float в коде. В eeprom записывается в 4-ре ячейки. Считывается как float :) НО страничка то работет с int и в частности кусочек кода который я никак и несмог переделать и оставил как есть:

////////////////////////////////////////////////////////////////////
//***Обогрев Вкл\Выкл      
      if (server.argName(i) == "heatOn") {
        if (server.arg(i) != "")
        {
          if (isValidNumber(server.arg(i)) )
            heatOn = server.arg(i).toInt();
          else
            webMessage += "Heat On must be a number<br>";
        }
        else
          webMessage += "Heat On is required<br>";
      }
      if (server.argName(i) == "heatOff") {
        if (server.arg(i) != "")
        {
          if (isValidNumber(server.arg(i)) )
            heatOff = server.arg(i).toInt();
          else
            webMessage += "Heat Off must be a number<br>";
        }
        else
          webMessage += "Heat Off is required<br>";
      }
////////////////////////////////////////////////////////////////////

 

и в частности  heatOn = server.arg(i).toInt();

А косяк какой при заполнении параметров температуру нужно указывать вида 2778 а не как положено 27.78.

И если меняется к примеру параметр контроля влажности то температура уже считана и имеет вид 27.78 и при сохранении (submit) огна сохраняется в eeprom уже как 0,27 и приходится быть начеку меняя остальные параметры. (проверку при записи в eeprom пока неделал - проверку на были ли измененияи стоит ли перезаписывать).

Смотерь за температурой и влажностью (не нужно ли долить воды) - сегодня как раз за ночь и ушёл уровень - с утра доливал. Тут в свободном доступе графики https://thingspeak.com/channels/437831

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

(проверку при записи в eeprom пока неделал - проверку на были ли измененияи стоит ли перезаписывать).

EEPROM.update.)))

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

Thorn пишет:

и скрин управения

про этот скрин можно подробнее? - это что-то самописное или готовое?

Thorn
Offline
Зарегистрирован: 07.11.2014

За основу взята эта статейка https://github.com/dmainmon/ESP8266-12E-DHT-Thermostat/blob/master/ESP8266-DHT.ino

Задача была простая, неиспользовать ни кнопок ни дисплейчика НО иметь возможно всё настраивать. Веб-мордочка подходила идеально потому и пришлось изучать чутку nodeMcu и её вебсервер.

Из исходника в итоге остался именно вебсервер, а все остальное (термерегулятор, работу с #include <FS.h> // FOR SPIFFS файловой системкой выбросил.

Такчто вёрстка полностью стала моей в итоге и сейчас я её периодически переделываю.

Добавил ds18b20, 1320 .... и первым делом сделал плату управления котлом ProtermScat16kWt а счас вот переделал полностью под инкубатор. В котле нужно было управлять двумя скоростями насоса, 6 тэнами, давление я пока неконтролирую а тольк осмотрю чтобы не ниже 0,5 и не выше 3,0атм - некогда было заниматься (второго датчика нет а тот что есть если вынуть из котла разгерметизирует систему а счас зима)и

Да вариант что сейчас ещё неимеет настроек проветриваний (нужно будет с 18 по 21 день инкубации) и вообще красоты и выравниваний.

Thorn
Offline
Зарегистрирован: 07.11.2014

Есчо один мелкий вопрос про ьшддшы но уже применительно к сервоприводу. Надобы добавить плавности в движении, нашел про стороннюю библу с возможностью устанавливать именно скорость при изменении угла http://arduino.ru/forum/apparatnye-voprosy/plavnoe-servo

но она не компилиться с 8266 платформой. Стандартная библиотчечка servo использует servo при переборе угла - надобы заменить его на millis.

Перемешивание сейчас определяет этот скетчик:

  servoOn=EEPROM.read(11);
    if (servoOn==1){
  if (fulTime==fulTimeS1) {valveServo.write(45);}   //Проверяем интервал
  if (fulTime==fulTimeS2) {valveServo.write(90);}   //Проверяем интервал
  if (fulTime==fulTimeS3) {valveServo.write(135);}  //Проверяем интервал
  if (fulTime==fulTimeS4) {valveServo.write(90);}   //Проверяем интервал
  }

тоесть ограничился 45град чтобы нетак сильно трясло яйца при переворачивании. На сейчас самый прсотой вариант это

  val_C=map(hours,0,23,0,180);

  valveServo.write(val_C);

тоесть вращать их в течении суток плавно без указания конкретного времени как сейчас. Однако если неотключать серву (в случае с применением val_C=map - этог делать нельзя - серва дёргается сволочь (она обычная аналоговая) и постоянно постукивает сеткой по скорлупе тем самым подрывая нервную систему потомства :) Есть ли у кого како опыт в подобном несешном перемещении сервоприводов.