Управление газовым котлом, бойлером, теплым полом < MegaD-2561 + MjD

Не требует установки программ или изменения файлов

Модераторы: immortal, newz20

Ответить
Kirch
Сообщения: 31
Зарегистрирован: Чт июл 26, 2018 4:50 pm
Благодарил (а): 6 раз
Поблагодарили: 4 раза

Управление газовым котлом, бойлером, теплым полом < MegaD-2561 + MjD

Сообщение Kirch » Вт янв 26, 2021 11:05 pm

Выкладываю свой код управления
  • газовым напольным котлом Лемакс,
  • насосом бойлера косвенного нагрева,
  • насосом теплого пола,
  • сервоприводом теплого пола.
Используются датчики:
  • температура на подаче/обратке из теплого пола
  • температура выхода из газового котла
  • температура внутри бойлера
Из всех фич, сделано только 2 - №2 и №5.
// 1 выдерживание температуры в комнатах
// 2 выдерживание температуры подачи и обратки пола
// 3 быстрый нагрев комнат
// 4 энергосберегающий режим в отъездах
// 5 прогрев воды в бойлере до 80 гр.

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

Код: Выделить всё

  
// код управления режимами котла и нагрева
// -1 выдерживание температуры в комнатах
// +2 выдерживание температуры подачи и обратки пола
// -3 быстрый нагрев комнат
// -4 энергосберегающий режим в отъездах
// +5 прогрев воды в бойлере до 80 гр.

//exit;// ("Управление теплом отключено"); // когда нужно отключить работу скрипта, убираю комментирование
// DebMes ("Управление сервера теплом"); // включаем, если в логе нужно выводить строку по запуску скрипта

$TimeOutMax = 300; // максимальное время отсутствия данных датчиков в сек
$TimeOut = time() - $TimeOutMax; // крайнее время достоверности данных датчиков, раньше которого - ошибка
$NuzhnaGV = 1; // нужна 1 или нет 0 горячая вода
function CheckSensor($a) // проверка датчиков на ошибки, возврат имени датчика при ошибке
// приходится проверять показания датчиков, т.к. они часто врут на общей шине 1wire
{
   if ($a == '') {return '';}
   if (gg("$a.alive") == 0) {return $a.".Al";} // если не живой
   if (gg("$a.updated") < $TimeOut) {return $a.".up";} // если устарели данные
   if (gg("$a.value") > 100 ) {return $a.">100";} // если ошибка питания DS18B20
   if (gg("$a.value") == 80 ) {return $a."=80";} // если ошибка питания DS18B20
    return '';
}

//1 напишу позже

// 2 выдерживание температуры подачи и обратки пола
$TPin1=28; // нижняя температура подачи пола,
$TPin2=35; // верхняя температура подачи пола, 
$TPret1=27; // нижняя температура обратки пола, 
$TPret2=31; // верхняя температура обратки пола, 
$TKout2=70; // верхняя температура котла, 
$TKout1=55; // нижняя температура котла
$TGV1=40; // нижняя температура горячей воды, 
$TGV2=75; // верхняя температура горячей воды, 

//проверка датчиков
$Error = '';
$Error .= CheckSensor('Sensor_temp06'); // в пол
$Error .= CheckSensor('Sensor_temp07'); // обратка с пола
$Error .= CheckSensor('Sensor_temp12'); // выход из газ котла
$Error .= CheckSensor('Sensor_temp08'); // горячая вода в бойлере
$Error .= (gg('Relay12.alive')==0) ? 'Relay12(активный котел) ':''; // активный котел
$Error .= (gg('Relay11.alive')==0) ? 'Relay11(активный сервопривод) ':''; // активный сервопривод
$Error .= (gg('Relay09.alive')==0) ? 'Relay09(активный насос пола) ':''; // активный насос пола
$Error .= (gg('Relay10.alive')==0) ? 'Relay10(активный насос бойлера) ':''; // активный насос бойлера
// лишний раз убеждаемся в корректности уставок
$Error .= ($TPin1 > $TPin2) ? "TPin1 $TPin1>$TPin2 TPin2":''; // неправильные границы max<min
$Error .= ($TPret1 > $TPret2) ? "TPret1 $TPret1>$TPret2 TPret2":''; // неправильные границы max<min
if ($Error >'') {
   DebMes ("Ошибки датчиков и устройств: $Error");
    say ("Ошибки датчиков и устройств: $Error");
   //exit;
}
// текущие значения
$TPin0 = gg('Sensor_temp06.value'); // факт температура подачи в пол
$TPret0 = gg('Sensor_temp07.value'); // факт температура обратки из пола
$TKout0 = gg('Sensor_temp12.value'); // факт температура выхода из газ котла
$TGV0 = gg('Sensor_temp08.value'); // факт температура горячей воды в бойлере

// очищаем переменные и будем в них накапливать финальные целевые значения и пояснения текстом
$P=0;
$K=0;
$B=0;
$Ps='';
$Ks='';
$Bs='';
// выдерживаем режим t на гребенке пола
if ($TPret2 < $TPret0) {$P=-2; $Ps .=$P."=закрыть пол при превышении обратки выше max t $TPret2; ";} // закрыть пол при превышении обратки выше max t
if ($TPret1 > $TPret0) {$P=2; $Ps .=$P."=открыть пол при снижении обратки ниже min t $TPret1; ";} // 
if (($TPin1)/1 > $TPin0) {$P=1; $Ps .=$P."=открыть пол при снижении ниже t $TPin1; ";} // 
if ($TPin2+2 < $TPin0) {$P=-1; $Ps .=$P."=закрыть пол, превышен max t ".($TPin2+2)."; ";}  // 
if ($TPret0-2 > $TPret2 AND $TPin0 > $TPret2) {$P=-2; $Ps .=$P."=закрыть пол, если превышен max t обратки ".($TPret2+2)." и подача $TPin0 > обратки $TPret2; ";} // 

if ($TKout0 < $TPin1 +10) {$K=1; $Ks .=$K."=нагревать, если котел $TKout0 меньше min t $TPin1 подачи в пол + 10 градусов потерь; ";} // 
if ($TKout0 < $TPin0) {$K=2; $Ks .=$K."=нагревать, если котел $TKout0 меньше $TPin0 тек.t подачи в пол; ";} // 
if ($P>0 AND $TKout0 < $TPin2) {$K=3; $Ks .=$K."=нагревать, если открылся пол и t котла $TKout0 меньше max подачи в пол $TPin2; ";} // 
if ($TKout0 > $TPin2 +50) {$K=-1; $Ks .=$K."=перестать нагревать, если котел $TKout0 больше $TPin2 max t подачи в пол + 50 градусов потерь; ";} // 

// поддерживаем котел
if ($TKout1 > $TKout0) {$K=4; $Ks .=$K."=включить котел - не дать остывать $TKout0 ниже $TKout1 min котла; ";} // 
if ($TKout2 < $TKout0) {$K=-2; $Ks .=$K."=выключить котел - не дать $TKout0 нагреваться $TKout2 выше max котла; ";} // 

// поддерживаем горячую воду в бойлере
if ($NuzhnaGV ==1 and $TGV1 > $TGV0) {$K=5; $Ks .=$K."=включить котел - не дать остывать гвс $TGV0 ниже min $TGV1; ";} //  
//if ($TGV0 > ($TKout0 + 5)) {$B=-1; $Bs .=$B."=выключить насос бойлера, если t в бойлере $TGV0 больше, чем на 5 градусов, чем t котла $TKout0 ; ";} // 
if ($K < 0) {$B=-2; $Bs .=$B."=выключить насос бойлера, если выключился нагрев ; ";} // 
if ($NuzhnaGV ==1 and $K > 0) {$B=2; $Bs .=$B."=включить насос бойлера, если включился нагрев ; ";} // 
if ($NuzhnaGV ==1 and $TGV0 < ($TKout0 + 0)) {$B=1;  $Bs .=$B."=включить насос бойлера, если t в бойлере $TGV0 опустится ниже, чем t котла $TKout0 плюс 0 градусов; ";} // включить насос бойлера

$RepP = $Ps; // переключаем сервопривод пола
if ($P>0 AND gg('Relay11.status') == 0) {cm('Relay11.turnOn');} 
elseif ($P<0 AND gg('Relay11.status') == 1) {cm('Relay11.turnOff');} 
else  {$RepP = '';}
if ($RepP > '') {
 DebMes ("Отопление: Сервопривод $RepP");
// say ("Команда отопления Сервопривод $Rep"); // say - иногда полезно получать сообщения по мессенджерам (если включены модули связи)
}
 
$RepK = $Ks; // переключаем котел
if ($K>0 AND gg('Relay12.status') == 1) {cm('Relay12.turnOff');} // включаем котел
elseif ($K<0 AND gg('Relay12.status') == 0) {cm('Relay12.turnOn');} // выключаем котел
else  {$RepK = '';}
if ($RepK > '') {
 DebMes ("Отопление: $RepK");
// say ("Команда отопления Котел $Rep");
}

$RepB = $Bs; // переключаем насос бойлера
if ($B<0 AND gg('Relay10.status') == 1) {cm('Relay10.turnOff');} // выключаем подачу в бойлер
elseif ($B>0 AND gg('Relay10.status') == 0) {cm('Relay10.turnOn');} // включаем подачу в бойлер
else  {$RepB = '';}
if ($RepB > '') {
 DebMes ("Отопление: $RepB");
// say ("Команда отопления насос бойлера $Rep");
}

// переключаем насос пола
if (gg('Relay09.status') == 0) {
 cm('Relay09.turnOn');
 DebMes ("Вкл насос пола");
// say ("Вкл насос пола");
} 

//$RepP="проверка"; // если раскомментировать, то в лог раз в минуту будет выводиться состояние переменных
if ($RepP.$RepK.$RepB <> '') {
 $Rep = "Kotel:".(1-gg('Relay12.status'))." ServoPol:".gg('Relay11.status')." NasosP:".gg('Relay09.status')." NasosB:".gg('Relay19.status')."  TPin:$TPin1<$TPin0<$TPin2 TPret:$TPret1<$TPret0<$TPret2 TKout:".$TKout1."<".$TKout0."<(".($TPin1 +10)."|".($TPin0 +0)."|".($TPin2 +20)."|$TKout2) TGV:$TGV1<$TGV0<$TGV2";
 DebMes ($Rep);
// Say ($Rep);
}
Скрипт вызывается runScript('KotelAndPolMgm'); // управление котлом и полом
из ClockChime Метод объекта:onNewMinute

Эксплуатировался одну зиму.
За это сообщение автора Kirch поблагодарили (всего 2):
tarasfrompir (Ср янв 27, 2021 3:28 pm) • Chainik (Ср янв 27, 2021 3:51 pm)
Рейтинг: 2.35%
Аватара пользователя
tarasfrompir
Сообщения: 3115
Зарегистрирован: Ср мар 02, 2016 8:18 pm
Откуда: Украина Пирятин
Благодарил (а): 209 раз
Поблагодарили: 771 раз

Re: Управление газовым котлом, бойлером, теплым полом < MegaD-2561 + MjD

Сообщение tarasfrompir » Ср янв 27, 2021 3:28 pm

Kirch писал(а):
Вт янв 26, 2021 11:05 pm
Выкладываю свой код управления
  • газовым напольным котлом Лемакс,
  • насосом бойлера косвенного нагрева,
  • насосом теплого пола,
  • сервоприводом теплого пола.
Используются датчики:
  • температура на подаче/обратке из теплого пола
  • температура выхода из газового котла
  • температура внутри бойлера
Из всех фич, сделано только 2 - №2 и №5.
// 1 выдерживание температуры в комнатах
// 2 выдерживание температуры подачи и обратки пола
// 3 быстрый нагрев комнат
// 4 энергосберегающий режим в отъездах
// 5 прогрев воды в бойлере до 80 гр.

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

Код: Выделить всё

  
// код управления режимами котла и нагрева
// -1 выдерживание температуры в комнатах
// +2 выдерживание температуры подачи и обратки пола
// -3 быстрый нагрев комнат
// -4 энергосберегающий режим в отъездах
// +5 прогрев воды в бойлере до 80 гр.

//exit;// ("Управление теплом отключено"); // когда нужно отключить работу скрипта, убираю комментирование
// DebMes ("Управление сервера теплом"); // включаем, если в логе нужно выводить строку по запуску скрипта

$TimeOutMax = 300; // максимальное время отсутствия данных датчиков в сек
$TimeOut = time() - $TimeOutMax; // крайнее время достоверности данных датчиков, раньше которого - ошибка
$NuzhnaGV = 1; // нужна 1 или нет 0 горячая вода
function CheckSensor($a) // проверка датчиков на ошибки, возврат имени датчика при ошибке
// приходится проверять показания датчиков, т.к. они часто врут на общей шине 1wire
{
   if ($a == '') {return '';}
   if (gg("$a.alive") == 0) {return $a.".Al";} // если не живой
   if (gg("$a.updated") < $TimeOut) {return $a.".up";} // если устарели данные
   if (gg("$a.value") > 100 ) {return $a.">100";} // если ошибка питания DS18B20
   if (gg("$a.value") == 80 ) {return $a."=80";} // если ошибка питания DS18B20
    return '';
}

//1 напишу позже

// 2 выдерживание температуры подачи и обратки пола
$TPin1=28; // нижняя температура подачи пола,
$TPin2=35; // верхняя температура подачи пола, 
$TPret1=27; // нижняя температура обратки пола, 
$TPret2=31; // верхняя температура обратки пола, 
$TKout2=70; // верхняя температура котла, 
$TKout1=55; // нижняя температура котла
$TGV1=40; // нижняя температура горячей воды, 
$TGV2=75; // верхняя температура горячей воды, 

//проверка датчиков
$Error = '';
$Error .= CheckSensor('Sensor_temp06'); // в пол
$Error .= CheckSensor('Sensor_temp07'); // обратка с пола
$Error .= CheckSensor('Sensor_temp12'); // выход из газ котла
$Error .= CheckSensor('Sensor_temp08'); // горячая вода в бойлере
$Error .= (gg('Relay12.alive')==0) ? 'Relay12(активный котел) ':''; // активный котел
$Error .= (gg('Relay11.alive')==0) ? 'Relay11(активный сервопривод) ':''; // активный сервопривод
$Error .= (gg('Relay09.alive')==0) ? 'Relay09(активный насос пола) ':''; // активный насос пола
$Error .= (gg('Relay10.alive')==0) ? 'Relay10(активный насос бойлера) ':''; // активный насос бойлера
// лишний раз убеждаемся в корректности уставок
$Error .= ($TPin1 > $TPin2) ? "TPin1 $TPin1>$TPin2 TPin2":''; // неправильные границы max<min
$Error .= ($TPret1 > $TPret2) ? "TPret1 $TPret1>$TPret2 TPret2":''; // неправильные границы max<min
if ($Error >'') {
   DebMes ("Ошибки датчиков и устройств: $Error");
    say ("Ошибки датчиков и устройств: $Error");
   //exit;
}
// текущие значения
$TPin0 = gg('Sensor_temp06.value'); // факт температура подачи в пол
$TPret0 = gg('Sensor_temp07.value'); // факт температура обратки из пола
$TKout0 = gg('Sensor_temp12.value'); // факт температура выхода из газ котла
$TGV0 = gg('Sensor_temp08.value'); // факт температура горячей воды в бойлере

// очищаем переменные и будем в них накапливать финальные целевые значения и пояснения текстом
$P=0;
$K=0;
$B=0;
$Ps='';
$Ks='';
$Bs='';
// выдерживаем режим t на гребенке пола
if ($TPret2 < $TPret0) {$P=-2; $Ps .=$P."=закрыть пол при превышении обратки выше max t $TPret2; ";} // закрыть пол при превышении обратки выше max t
if ($TPret1 > $TPret0) {$P=2; $Ps .=$P."=открыть пол при снижении обратки ниже min t $TPret1; ";} // 
if (($TPin1)/1 > $TPin0) {$P=1; $Ps .=$P."=открыть пол при снижении ниже t $TPin1; ";} // 
if ($TPin2+2 < $TPin0) {$P=-1; $Ps .=$P."=закрыть пол, превышен max t ".($TPin2+2)."; ";}  // 
if ($TPret0-2 > $TPret2 AND $TPin0 > $TPret2) {$P=-2; $Ps .=$P."=закрыть пол, если превышен max t обратки ".($TPret2+2)." и подача $TPin0 > обратки $TPret2; ";} // 

if ($TKout0 < $TPin1 +10) {$K=1; $Ks .=$K."=нагревать, если котел $TKout0 меньше min t $TPin1 подачи в пол + 10 градусов потерь; ";} // 
if ($TKout0 < $TPin0) {$K=2; $Ks .=$K."=нагревать, если котел $TKout0 меньше $TPin0 тек.t подачи в пол; ";} // 
if ($P>0 AND $TKout0 < $TPin2) {$K=3; $Ks .=$K."=нагревать, если открылся пол и t котла $TKout0 меньше max подачи в пол $TPin2; ";} // 
if ($TKout0 > $TPin2 +50) {$K=-1; $Ks .=$K."=перестать нагревать, если котел $TKout0 больше $TPin2 max t подачи в пол + 50 градусов потерь; ";} // 

// поддерживаем котел
if ($TKout1 > $TKout0) {$K=4; $Ks .=$K."=включить котел - не дать остывать $TKout0 ниже $TKout1 min котла; ";} // 
if ($TKout2 < $TKout0) {$K=-2; $Ks .=$K."=выключить котел - не дать $TKout0 нагреваться $TKout2 выше max котла; ";} // 

// поддерживаем горячую воду в бойлере
if ($NuzhnaGV ==1 and $TGV1 > $TGV0) {$K=5; $Ks .=$K."=включить котел - не дать остывать гвс $TGV0 ниже min $TGV1; ";} //  
//if ($TGV0 > ($TKout0 + 5)) {$B=-1; $Bs .=$B."=выключить насос бойлера, если t в бойлере $TGV0 больше, чем на 5 градусов, чем t котла $TKout0 ; ";} // 
if ($K < 0) {$B=-2; $Bs .=$B."=выключить насос бойлера, если выключился нагрев ; ";} // 
if ($NuzhnaGV ==1 and $K > 0) {$B=2; $Bs .=$B."=включить насос бойлера, если включился нагрев ; ";} // 
if ($NuzhnaGV ==1 and $TGV0 < ($TKout0 + 0)) {$B=1;  $Bs .=$B."=включить насос бойлера, если t в бойлере $TGV0 опустится ниже, чем t котла $TKout0 плюс 0 градусов; ";} // включить насос бойлера

$RepP = $Ps; // переключаем сервопривод пола
if ($P>0 AND gg('Relay11.status') == 0) {cm('Relay11.turnOn');} 
elseif ($P<0 AND gg('Relay11.status') == 1) {cm('Relay11.turnOff');} 
else  {$RepP = '';}
if ($RepP > '') {
 DebMes ("Отопление: Сервопривод $RepP");
// say ("Команда отопления Сервопривод $Rep"); // say - иногда полезно получать сообщения по мессенджерам (если включены модули связи)
}
 
$RepK = $Ks; // переключаем котел
if ($K>0 AND gg('Relay12.status') == 1) {cm('Relay12.turnOff');} // включаем котел
elseif ($K<0 AND gg('Relay12.status') == 0) {cm('Relay12.turnOn');} // выключаем котел
else  {$RepK = '';}
if ($RepK > '') {
 DebMes ("Отопление: $RepK");
// say ("Команда отопления Котел $Rep");
}

$RepB = $Bs; // переключаем насос бойлера
if ($B<0 AND gg('Relay10.status') == 1) {cm('Relay10.turnOff');} // выключаем подачу в бойлер
elseif ($B>0 AND gg('Relay10.status') == 0) {cm('Relay10.turnOn');} // включаем подачу в бойлер
else  {$RepB = '';}
if ($RepB > '') {
 DebMes ("Отопление: $RepB");
// say ("Команда отопления насос бойлера $Rep");
}

// переключаем насос пола
if (gg('Relay09.status') == 0) {
 cm('Relay09.turnOn');
 DebMes ("Вкл насос пола");
// say ("Вкл насос пола");
} 

//$RepP="проверка"; // если раскомментировать, то в лог раз в минуту будет выводиться состояние переменных
if ($RepP.$RepK.$RepB <> '') {
 $Rep = "Kotel:".(1-gg('Relay12.status'))." ServoPol:".gg('Relay11.status')." NasosP:".gg('Relay09.status')." NasosB:".gg('Relay19.status')."  TPin:$TPin1<$TPin0<$TPin2 TPret:$TPret1<$TPret0<$TPret2 TKout:".$TKout1."<".$TKout0."<(".($TPin1 +10)."|".($TPin0 +0)."|".($TPin2 +20)."|$TKout2) TGV:$TGV1<$TGV0<$TGV2";
 DebMes ($Rep);
// Say ($Rep);
}
Скрипт вызывается runScript('KotelAndPolMgm'); // управление котлом и полом
из ClockChime Метод объекта:onNewMinute

Эксплуатировался одну зиму.
Ничего не хочу сказать - но вопрос простой - насколько сильно нагружен Ваш МДМ?
Спасибо нам ПОМОЖЕТ..!
Ответить