<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[RemoteXY community — Выполнение скрипта с задержками выполнения программы]]></title>
		<link>https://forum.remotexy.com/viewtopic.php?id=182</link>
		<atom:link href="https://forum.remotexy.com/extern.php?action=feed&amp;tid=182&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[The most recent posts in Выполнение скрипта с задержками выполнения программы.]]></description>
		<lastBuildDate>Tue, 30 May 2017 08:43:42 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Re: Выполнение скрипта с задержками выполнения программы]]></title>
			<link>https://forum.remotexy.com/viewtopic.php?pid=688#p688</link>
			<description><![CDATA[<p>Скажу вам ответ из своей практики почему использование задержек это плохо.<br />Как то давно автоматизировали насосную станцию. Программа была написана точно также, при пуске насоса отрабатывался алгоритм пуска с различными переключениями и паузами между ними. Выключатель включили, подождали, задвижку открыли подождали и т.д. Все это привело к тому, что в эти моменты переставала работать программа контроля аварийных ситуаций. Т.е. контроль аварий не работал несколько секунд. Программа аварийных ситуаций анализирует токи, вибрацию установки и еще ряд параметров и может аварийно остановить насос. И вот если в момент пуска, в течении этих нескольких секунд происходит аварийная ситуация, программа ее просто не видит. В итоге пока весь алгоритм старта не отработает, установка не отключается по аварии. А надо признать что аварии чаще всего бывают в момент пуска. И даже если оператор нажимал кнопку экстренного останова - ничего не происходило, ведь устройство контроля на &quot;паузе&quot;.<br />Рекомендую такой подход.<br />1. Ваша программа должна постоянно крутиться в цикле. чем короче цикл, тем лучше.<br />2. В каждом цикле должны вызываться соответствующие обработчики задач. Задача контроля аварийных параметров, задача пуска, задача останова и обработчик RemoteXY так же.<br />3. Каждая задача должна получить текущее время, проанализировать текущее время и состояние выполнения задачи, если пришло время - выполнить задачу (чего нибудь включить, выключить), запомнить свое состояние для следующего вызова и отдать управление (выйти из процедуры).</p><p>Как реализовать процедуру обработчика? Например пуска?<br />1. Ввести переменную состояния процесса пуска.<br />2. Ввести переменную отсчета временного интервала.</p><div class="codebox"><pre><code>int start_state = 0; //=0 - нет пуска, =1, рубильник замкнули, =2 рубильник разомкнули
long start_time;

void start () {
  if (start_state==0) {
    if (RemoteXY.start==1) { // нажата кнопка пуска
      ... замыкаем рубильник
      start_state = 1;
      start_time = millis ();  // запомнили время замыкания рубильника  
    }
  }
  else  if (start_state==1) {
    if (start_time+1000&gt;millis ()) { // пришло время размыкания рубильника
      ... размыкаем рубильник
      start_state = 2;
      start_time = millis ();  // запомнили время размыкания рубильника  
    }
  }
  else  if (start_state==2) {
    ... установка включена
  }

}</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (remotexy)]]></author>
			<pubDate>Tue, 30 May 2017 08:43:42 +0000</pubDate>
			<guid>https://forum.remotexy.com/viewtopic.php?pid=688#p688</guid>
		</item>
		<item>
			<title><![CDATA[Выполнение скрипта с задержками выполнения программы]]></title>
			<link>https://forum.remotexy.com/viewtopic.php?pid=684#p684</link>
			<description><![CDATA[<p>Добрый день. В рамках реализации проекта удаленного управления водонагревателем, написал скрипт автовключения водонагревателя. Если включен переключатель ВКЛ.таймер и в поле ввода введено время и температура нагрева в формате HH:MM:TT - каждый цикл производится вызов одной из функций автовключения.&nbsp; Скриншот интерфейса ниже.</p><p><a target="_blank" href="http://radikal.ru"><span class="postimg"><img src="http://s46.radikal.ru/i111/1705/b6/08711c0758f2.png" alt="http://s46.radikal.ru/i111/1705/b6/08711c0758f2.png" /></span></a></p><p>В теле функции schedule_func_ON()&nbsp; необходимо совершать несколько последовательных действий. Чтобы установить температуру нагрева, допустим с текущего значения 35 градусов на значение 75 градусов, нужно 9 раз замкнуть и разомкнуть реле temp_relay (первое замыкание - холостое, а далее температура меняется при нажатии с инкрементом 5 градусов). Каждое замыкание-размыкание реле имитирует нажатие человеком на кнопку на передней панели водонагревателя.&nbsp; После замыкания и размыкания необходимо на некоторое время остановить выполнение программы для того, чтобы реле успевало реагировать и не &quot;залипало&quot;.&nbsp; <br />Когда я писал программу без использования remoteXY - просто использовал delay(). С RemoteXY использование delay() недопустимо, как понял из документации. Попробовал с пустым циклом while() - программа ведет себя не корректно. Видимо в силу той же причины - пока закончится несколько циклов while() - RemoteXY_Handler теряет связь. <br />В&nbsp; void loop() у меня уже есть задержки включения-выключения реле. Но там на каждое действие - свой условный оператор if. Поэтому программа работает по циклу корректно и без задержек. Пример ниже:<br />___________________________________________________________<br />&nbsp; if ((RemoteXY.button_1 !=0) &amp;&amp; (millis() - button_1_time &gt; 500))<br />&nbsp; // если кнопка нажата (состояние 1) и с момента последнего нажатия прошло не менее 500 мс (исключение многократного срабатывания при долгом нажатии на кнопку) выполняем код ниже<br />&nbsp; {&nbsp; <br />&nbsp; &nbsp; digitalWrite(ON_OFF_relay, LOW);<br />&nbsp; &nbsp; button_1_time = millis();&nbsp; &nbsp; &nbsp; &nbsp;//актуализируем значение button_1_time<br />&nbsp; }&nbsp; <br />&nbsp; <br />&nbsp; //через 200-300 мс после замыкания реле (может выполниться несколько раз за 100 мс) выполняем код ниже<br />&nbsp; if ((millis() - button_1_time &gt; 200) &amp;&amp; (millis() - button_1_time &lt; 300))<br />&nbsp; {<br />&nbsp; &nbsp; digitalWrite(ON_OFF_relay, HIGH);<br />&nbsp; }<br />___________________________________________________________________________</p><br /><p>А при выполнении описанного мной скрипта в функции schedule_func_ON() возникает проблема потому что я не могу вызывать эту функцию каждый цикл. Мне нужно вызвать ее единожды и выполнить код внутри функции. <br />Собственно вопрос в том, как можно такое реализовать, учитывая некоторые ограничения с использование задержек.</p><p>Ниже код. В функции schedule_func_ON() для простоты показан код только на 1 замыкание-размыкание реле.<br />________________________________________________________________________<br />void loop()<br />{<br />&nbsp; &nbsp;..........</p><p>&nbsp; if ((RemoteXY.switch_1 != 0) &amp;&amp; (strlen(RemoteXY.edit_1) == 8)) //если переключатель таймера в положении ВКЛ и в строку таймера вписаны значения в формате HH:MM:TT - выполняем код ниже<br />&nbsp; {<br />&nbsp; &nbsp; if (ON_OFF_state == 1)<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; //вызов функции включения водонагревателя по расписанию с изначально включенным водонагревателем<br />&nbsp; &nbsp; &nbsp; schedule_func_ON();&nbsp; &nbsp; <br />&nbsp; &nbsp; }<br />&nbsp; &nbsp; else<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; //вызов функции включения водонагревателя по расписанию с изначально выключенным водонагревателем<br />&nbsp; &nbsp; &nbsp; schedule_func_OFF();&nbsp; &nbsp; <br />&nbsp; &nbsp; }<br />&nbsp; }<br />}</p><p>void schedule_func_ON() <br />{&nbsp; <br />&nbsp; int Hrs = (RemoteXY.edit_1[0] - 48)*10 + (RemoteXY.edit_1[1] - 48);&nbsp; <br />&nbsp; int Min = (RemoteXY.edit_1[3] - 48)*10 + (RemoteXY.edit_1[4] - 48);<br />&nbsp; int Temp = (RemoteXY.edit_1[5] - 48)*10 + (RemoteXY.edit_1[6] - 48);<br />&nbsp; <br />&nbsp; //получаем данные от часов<br />&nbsp; get3231Date();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />&nbsp; if ((Hrs == hours) &amp;&amp; (Min == minutes)) </p><p>&nbsp; //если настал &quot;час X&quot; - запускаем код ниже&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; {<br />&nbsp; &nbsp; Serial.println(&quot;Heater autoON operation start!!&quot;);<br />&nbsp; &nbsp; Serial.println(&quot;IDLE pressing of TEMP button&quot;);<br />&nbsp; &nbsp; Serial.print(&quot;Heat TEMP is: &quot;); Serial.print(temp_state); Serial.println(&#039;°С&#039;); <br />&nbsp; &nbsp; digitalWrite(temp_relay,LOW);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //замыкаем реле (замкнуто при LOW)&nbsp; &nbsp;<br />&nbsp; &nbsp; &nbsp;<br />&nbsp; &nbsp; //бегаем в цикле while, пока не пройдет не менее 300мс&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />&nbsp; &nbsp; unsigned long relay_time = 0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; while (millis() - relay_time &lt; 300)&nbsp; &nbsp; &nbsp;<br />&nbsp; &nbsp; {&nbsp; &nbsp;<br />&nbsp; &nbsp; }<br />&nbsp; &nbsp; relay_time = millis();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// актуализируем значение relay_time<br />&nbsp; &nbsp; digitalWrite(temp_relay,HIGH);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // размыкаем реле (разомкнуто при HIGH)</p><p>&nbsp; &nbsp; //Чтобы реле успело произвести размыкание перед следующим замыканием<br />&nbsp; &nbsp; // (а у реле SRD-05VDC время release равно 5 мсек) - снова бегаем в цикле while 50 мсек<br />&nbsp; &nbsp; while (millis() - relay_time &lt; 50)<br />&nbsp; &nbsp; {&nbsp; &nbsp;<br />&nbsp; &nbsp; }&nbsp; <br />}<br />__________________________________________________________________________________</p>]]></description>
			<author><![CDATA[null@example.com (jaymzys)]]></author>
			<pubDate>Mon, 29 May 2017 08:45:14 +0000</pubDate>
			<guid>https://forum.remotexy.com/viewtopic.php?pid=684#p684</guid>
		</item>
	</channel>
</rss>
