- Статус подключения: Подключено
- Категория: Контроллер
- Фирма: MY HEAT
- Модель: MY HEAT SMART, MY HEAT PRO
- Название: Контроллер управления отопительными приборами
- Описание: Контроллер MY HEAT SMART предназначен для управления отопительным котлом по цифровым шинам и в режиме термостата, бойлером косвенного нагрева, насосом, 3-х либо 2-х ходовым клапаном, предоставляет возможность регулировать температурный режим до трех сред отопления включительно. Осуществляет управление типовыми системами отопления в квартирах с индивидуальным отоплением и небольших частных домовладениях.
- Ссылка на сайт каталога производителя: myheat.net
- Тип питания: 12V-
- Магазин:myheat.net
- Приблизительная цена: 11900 руб (10.12.2020)
- Достоинства: Готовый модуль. Поддержка сразу нескольких цифровых шин в одном контроллере: Opentherm, EBUS, Navien, Arderia, LPB. Очень гибкая и простая настройка. Приложение для телефона. API для интеграции в системы умных домов.
- Недостатки: не выявлены
Контроллер MY HEAT управление отопительным котлом
Модератор: immortal
- Bagir
- Сообщения: 1614
- Зарегистрирован: Вт сен 17, 2013 6:46 pm
- Откуда: Ярославская область город Углич
- Благодарил (а): 212 раз
- Поблагодарили: 375 раз
Контроллер MY HEAT управление отопительным котлом
- Вложения
-
- Thermostat.txt
- ver 1.0
- (55.03 КБ) 280 скачиваний
-
- Описание API.pdf
- (167.04 КБ) 277 скачиваний
Последний раз редактировалось Bagir Чт дек 24, 2020 9:46 pm, всего редактировалось 4 раза.
- За это сообщение автора Bagir поблагодарили (всего 2):
- directman66 (Вт мар 02, 2021 2:09 pm) • odinvolk (Сб фев 25, 2023 5:08 am)
- Рейтинг: 2.33%
- Bagir
- Сообщения: 1614
- Зарегистрирован: Вт сен 17, 2013 6:46 pm
- Откуда: Ярославская область город Углич
- Благодарил (а): 212 раз
- Поблагодарили: 375 раз
Описание структуры класса Thermostat
Контроллер полностью самостоятелен. Может управлять температурой подачи котла по погодозависимой кривой и разным режимам работы. При подключении датчиков температуры помещения, они тоже могут влиять на температуру подачи. То есть будет не просто включение и выключение котла, а подбор темрературы подачи для снижения количества отключений и получения заданной t помещения.
А теперь, что интересно именно для нас: у контроллера есть простые API. То есть мы можем получать состояние нашей системы отопления, и задавать нужную температуру подачи. У многих из нас уже есть алгоритмы для расчета целевой температуры системы отопления. Теперь вопрос, как сообщить котлу какую от него температуру мы хотим получить, полностью решен. От сюда у нас есть два пути интеграции контроллера в нашу систему.
Способ 1. Алиса будет полностью управлять котлом. Мы сами рассчитываем нужную температуру подачи, исходя из собственных решений. Температура на улице, ветер, температура дома, режим день/ночь, режим экономии, дома/на работе/в отпуске, и т.д. У меня это делает класс Thermostat. В нем объекты двух газовых котлов и двух электрических котлов. А так же объект смесительного узла для теплых полов.
Уже реализовано:
- Методы turnOn и turnOff для включения и отключения котла, с таймерами минимальной работы/паузы, гистерезисом и суточным термостатом. Я люблю ночью сделать по прохладнее. Суточная температура задана в свойстве объекта одной цифрой, либо последовательностью из 24 цифр. Изменяя свойство можно просто сделать недельный термостат и режимы дома/на работе для экономии ресурсов.
- Метод setTemperature из которого можно сообщить котлу нужную температуру подачи. Тут нам и нужны api контроллера MyHeat. Ранее для этого я обманывал уличный датчик температуры, чтобы добиться от котла нужной t подачи. Способ рабочий, но весьма грубый. При изменении котел часто отключался, т.к. новая целевая температура могла быть сильно меньше текущей, и горелка котла не успевала модулировать мощность в таком диапазоне. Это мне сильно не нравилось. С контроллером я изменяю температуру плавно, и котел лишний раз не отключается.
- Виджет для меню. Теперь на терминалах в доме можно увидеть все параметры работы котла и состояние системы отопления. У контроллера есть своё приложение, и вы всегда будите в курсе о состоянии своего отопителя, даже если ваша Алиса открывается только в локальной сети. Это очень полезно, да и просто не заменимо при поездках в отпуск.
- Метод positionServo позволяет управлять положением сервопривода для контроля температуры радиаторов и теплых полов. Используя два реле, сервопривод управляет трехходовым смесительным клапаном. Кстати, контроллер это тоже умеет делать.
Способ 2. Если полное управление отоплением в Алисе не реализовано, то у Вас по любому есть данные о температурах в комнатах. Если мы сообщим контроллеру эти данные, то нам не придется монтировать дополнительные термодатчики. Что в случае законченного ремонта сделать не так просто. На этот момент у контроллера есть модуль расширения для работы с беспроводными датчиками. Но для нас больший интерес представляет интеграция контроллера в нашу систему, где уже всё и так есть. API для второго варианта пока что в разработке, но я уверен, что в скором времени они тоже будут.
Вернемся к первому варианту. Вот план схема, как работают методы моего класса Thermostat Сейчас я дописываю в коде комментарии чтобы было проще разобраться, и скоро выложу этот класс тут. Класс работает уже более года, и заслужил лимит доверия, по крайней мере с моей стороны. Но с появлением контроллера MyHeat, я внес некоторые корректировки, чтобы задействовать все возможности контроллера. А так же подкорректировал разные коэффициенты расчета температур. Ранее, при грубом рулении котлом, в них не было особой необходимости, т.к. я не имел возможность изменять t подачи котла на 1 градус, а только грубо ступенчато.
На следующий год у меня запланирован бассейн. Так что методы класса будут добавлены. Контроллер и сам может организовать подогрев бассейна, и я уже это делал это на объекте, но если мы хотим рулить всем сами, то без управления t подачи котла просто не обойтись.
А теперь, что интересно именно для нас: у контроллера есть простые API. То есть мы можем получать состояние нашей системы отопления, и задавать нужную температуру подачи. У многих из нас уже есть алгоритмы для расчета целевой температуры системы отопления. Теперь вопрос, как сообщить котлу какую от него температуру мы хотим получить, полностью решен. От сюда у нас есть два пути интеграции контроллера в нашу систему.
Способ 1. Алиса будет полностью управлять котлом. Мы сами рассчитываем нужную температуру подачи, исходя из собственных решений. Температура на улице, ветер, температура дома, режим день/ночь, режим экономии, дома/на работе/в отпуске, и т.д. У меня это делает класс Thermostat. В нем объекты двух газовых котлов и двух электрических котлов. А так же объект смесительного узла для теплых полов.
Уже реализовано:
- Методы turnOn и turnOff для включения и отключения котла, с таймерами минимальной работы/паузы, гистерезисом и суточным термостатом. Я люблю ночью сделать по прохладнее. Суточная температура задана в свойстве объекта одной цифрой, либо последовательностью из 24 цифр. Изменяя свойство можно просто сделать недельный термостат и режимы дома/на работе для экономии ресурсов.
- Метод setTemperature из которого можно сообщить котлу нужную температуру подачи. Тут нам и нужны api контроллера MyHeat. Ранее для этого я обманывал уличный датчик температуры, чтобы добиться от котла нужной t подачи. Способ рабочий, но весьма грубый. При изменении котел часто отключался, т.к. новая целевая температура могла быть сильно меньше текущей, и горелка котла не успевала модулировать мощность в таком диапазоне. Это мне сильно не нравилось. С контроллером я изменяю температуру плавно, и котел лишний раз не отключается.
- Виджет для меню. Теперь на терминалах в доме можно увидеть все параметры работы котла и состояние системы отопления. У контроллера есть своё приложение, и вы всегда будите в курсе о состоянии своего отопителя, даже если ваша Алиса открывается только в локальной сети. Это очень полезно, да и просто не заменимо при поездках в отпуск.
- Метод positionServo позволяет управлять положением сервопривода для контроля температуры радиаторов и теплых полов. Используя два реле, сервопривод управляет трехходовым смесительным клапаном. Кстати, контроллер это тоже умеет делать.
Способ 2. Если полное управление отоплением в Алисе не реализовано, то у Вас по любому есть данные о температурах в комнатах. Если мы сообщим контроллеру эти данные, то нам не придется монтировать дополнительные термодатчики. Что в случае законченного ремонта сделать не так просто. На этот момент у контроллера есть модуль расширения для работы с беспроводными датчиками. Но для нас больший интерес представляет интеграция контроллера в нашу систему, где уже всё и так есть. API для второго варианта пока что в разработке, но я уверен, что в скором времени они тоже будут.
Вернемся к первому варианту. Вот план схема, как работают методы моего класса Thermostat Сейчас я дописываю в коде комментарии чтобы было проще разобраться, и скоро выложу этот класс тут. Класс работает уже более года, и заслужил лимит доверия, по крайней мере с моей стороны. Но с появлением контроллера MyHeat, я внес некоторые корректировки, чтобы задействовать все возможности контроллера. А так же подкорректировал разные коэффициенты расчета температур. Ранее, при грубом рулении котлом, в них не было особой необходимости, т.к. я не имел возможность изменять t подачи котла на 1 градус, а только грубо ступенчато.
На следующий год у меня запланирован бассейн. Так что методы класса будут добавлены. Контроллер и сам может организовать подогрев бассейна, и я уже это делал это на объекте, но если мы хотим рулить всем сами, то без управления t подачи котла просто не обойтись.
Последний раз редактировалось Bagir Сб дек 12, 2020 12:38 am, всего редактировалось 1 раз.
- За это сообщение автора Bagir поблагодарили (всего 3):
- tarasfrompir (Пт дек 11, 2020 8:19 am) • Chainik (Пт дек 11, 2020 11:48 pm) • directman66 (Вт мар 02, 2021 2:11 pm)
- Рейтинг: 3.49%
- Bagir
- Сообщения: 1614
- Зарегистрирован: Вт сен 17, 2013 6:46 pm
- Откуда: Ярославская область город Углич
- Благодарил (а): 212 раз
- Поблагодарили: 375 раз
Описание методов класса
Теперь давайте разбираться, что делают эти методы, да и вообще что нужно рассчитать для полного управления системой отопления.
Для начала нужно периодически рассчитывать среднюю (или минимальную, тут кому как интересно) температуру всех комнат для общих отопителей. Например, если в системе котел работает на несколько комнат, то для расчета температуры подачи нам нужно знать целевую температуру воздуха. Если зонного регулирования в комнатах нет, то лучше рассчитать среднюю температуру комнат, если есть, то нужно обязательно прогреть самую холодную, а остальные ограничат потребление тепла сами. Тек же для работы дневного термостата, нужно периодически пересчитывать целевую температуру воздуха. Я добавил в класс Timer отдельный объект ClockChimeClimate. В нем каждые 5 минут происходит вызов сценария tempHomeChanges. Использование сценария оправдано ещё и вызовом его из объектов класса Rooms при изменении текущей температуры в любой комнате.
Далее идет перебор всех объектов класса Thermostat для выполнение методов airCalculate. В свойстве airRequiredTemp будет текущая целевая температура. Но любая система имеет инерцию. Это время, которое нам требуется на прогрев, и время на остывание. Допустим мы хотим понизить температуру ночью на 1 градус, а утром опять её увеличить. После того, как мы убавим, или даже полностью отключим отопитель, пройдет какое то время, прежде чем комната начнет остывать. Так же и при нагреве. Это и есть инерционность системы. Для каждого объекта это свойство индивидуально, и подбирается опытным путём по графикам. Метод airCalculate запишет свойство airShiftTemp в котором будет целевая температура комнаты с учетом инерции системы, чтобы успеть ее достичь.
Если целевая температура комнаты изменилась, будет вызван метод waterCalculate для расчета температуры подачи. Тут мы вычислим свойство waterRequiredTemp - требуемая температура подачи котла. От чего она зависит? Факторов довольно много. Самый главный это температура на улице. Чем холоднее, тем больше нужна температура подачи, чтобы компенсировать потери тепла. Я использую классический расчет по температурной кривой с коэффициентами наклона и сдвига, как в большинстве котлов. Далее очень весомый фактор будет момент приближения нашей текущей температуры к целевой. И чтобы не перегреть комнату, нужно понизить подачу. Ещё сильное влияние окажет ветер. Он просто выдувает тепло из дома, и мы должны это компенсировать. Ну и под финал - интенсивность освещённости. Когда солнце светит ярко, энергии тепловой требуется меньше, чем в очень пасмурные дни. Всем этим занимается метод pzaCalculate, результаты вычисления которого использует waterCalculate. Но одной погодозависимой автоматикой сыт не будешь, и если помещение холодное, то правильнее будет разогнать отопитель на полную мощность для начального прогрева. В итоге waterCalculate возьмет максимально допустимую температуру по ПЗА если мы опаздываем на три градуса, далее будет работать по ПЗА, а при приближении целевой на 1 градус начнет уменьшать подачу.
Теперь о самом методе pzaCalculate. В нем как раз и происходит расчет температуры по ПЗА. Метод вызывается при изменении уличной температуры. Рассчитывает ПЗА и сразу вызывает waterCalculate для перерасчета подачи. Тут как раз и происходит расчет по температуре улицы, скорости ветра и освещенности. Не все коэффициенты выведены в свойства объектов. Многие из них прописаны в коде. Для точной настройки нужно подгонять их под свой дом индивидуально. В этом очень помогают графики. О них мы тоже попозже поговорим.
Далее по цепочке waterCalculate вызывает методы setTemperature и positionServo. В общем коде этих методов нет ничего интересного. Тут мы прописывает код в методе объектов. Например для объекта котла, подключенного через контроллер MyHeat в методе setTemperature будет отправка температуры подачи котлу, по средствам API контроллера. Код я выложу в самом конце. Сейчас мы продолжим обсуждать работу класса. Метод positionServo используется для объектов смесительных узлов. В нем мы поворачиваем трехходовой кран в нужную сторону для получения нужной t подачи. То есть у котла мы управляем температурой подачи, а у смесительного узла крутим сервопривод.
waterCalculate вызывает ещё один метод. Это WorkDecision. Он примет решение о полном включении или отключении отопителя, или циркуляционного насоса смесительного узла. Будут вызваны методы turnOn и turnOff. их коде устанавливаются таймеры минимальной работы и паузы. Без них, в ситуации нахождения на грани равенства температур, котел может постоянно включаться и выключаться. Тут работает правило, что если включились, то должны работать какое то время. А если выключились, то несколько минут ждем. Это убирает тактование. Очень полезно для электрических котлов, да и для всех в целом.
Для управления объектами класса можно вывести их в меню или на сцены. Код шаблона отображения покажет все необходимые элементы.
Теперь о том, как установить, и обеспечить работу.
Убедимся, что в системе нет одноименного класса Thermostat. Импортируем класс, можно вместе с объектами моих отопителей. Будет проще разобраться. Потом удалите объекты и создадите свои. После импорта можно сразу добавить один из объектов в меню, чтобы убедиться что всё работает. Затем нужно настроить вызов методов класса. Всего будет три точки от куда запускаются методы.
1. Из метода onNewMinute каждые 5 минут происходит вызов методов airCalculate. Пример кода в самом начале. Нужно для суточного термостата. Далее методы класса будут вызываются по цепочке при необходимости.
2. При изменении температуры комнатных датчиков запускается сценарий tempHomeChanges. Он установит свойство airCurrentTemp что приведет к вызову метода waterCalculate.
Если у вас только один датчик температуры, то можно сразу писать его значение в свойство airCurrentTemp. Тогда сценарий tempHomeChanges не нужен. Сценарий только рассчитывает среднюю температуру комнат.
3. При изменении уличной температуры нужно вызвать метод pzaCalculate. Тут есть момент. В коде метода pzaCalculate есть получение свойства уличной температуры weather_now.temperature, скорости ветра weather_now.windSpeed и интенсивности освещённости DrivewayArea.Luminiscence. Замените их на свои. Если в вашей системе нет этих данных, тогда закомментируйте в методе pzaCalculate код поправки температуры подачи на эти факторы. Но без уличной температуры никак не обойтись.
Для ведения логов можно добавить в файл config.php строку Define('THRM_LOG_LEVEL', 2); Тогда все комментарии будут писаться в файл ...\cms\debmes\ГГГГ-ММ-ДД_thrm.log
0 - не писать, 1 - только основные логи, 2 - вся отладочная информация.
Ожидайте продолжение в ближайшее время! Скоро выложу класс целиком для скачивания.
А пока коротенькое резюме. Класс Thermostat может управлять отопителями по средствам их включения и выключения. Суточный термостат. Рассчитывает температуру подачи на основе ПЗА и целевой температуры дома. При подключении контроллера MyHeat может управлять отопителем по цифровой шине для поддержания целевой температуры. Управление сервоприводом смесительного узла.
Для начала нужно периодически рассчитывать среднюю (или минимальную, тут кому как интересно) температуру всех комнат для общих отопителей. Например, если в системе котел работает на несколько комнат, то для расчета температуры подачи нам нужно знать целевую температуру воздуха. Если зонного регулирования в комнатах нет, то лучше рассчитать среднюю температуру комнат, если есть, то нужно обязательно прогреть самую холодную, а остальные ограничат потребление тепла сами. Тек же для работы дневного термостата, нужно периодически пересчитывать целевую температуру воздуха. Я добавил в класс Timer отдельный объект ClockChimeClimate. В нем каждые 5 минут происходит вызов сценария tempHomeChanges. Использование сценария оправдано ещё и вызовом его из объектов класса Rooms при изменении текущей температуры в любой комнате.
класс Timer объект.метод ClockChimeClimate.onNewMinuteПоказать
Код: Выделить всё
$m=date('i',time());
// Расчет средней температуры жилых комнат
if (!($m%5)) {
runScript('tempHomeChanges');
}
// Расчет целевой температуры воздуха всех объектов класса
if (!($m%5)) {
// запуск методов airCalculate
$objects=getObjectsByClass('Thermostat');
foreach($objects as $obj) {
$obj=getObject($obj['TITLE']);
$obj->callMethod('airCalculate');
}
}
сценарий tempHomeChangesПоказать
Код: Выделить всё
/* вычисляет среднюю температуру жилых комнат
для передачи её объектам термостатов котлов
которые работают на всю систему отопления.
*/
$check=array('OfficeRoom','Bedroom','Livingroom','HallArea','KitchenArea');
$t_avg=0; //средняя температура
$r_count=0; //количество принятых комнат
foreach($check as $r) {
$prop_id=getValueIdByName($r, 'Temperature');
$arr_s = SQLSelectOne("SELECT UNIX_TIMESTAMP(UPDATED) as UPDATED, VALUE FROM `pvalues` WHERE ID=$prop_id");
if (time()-$arr_s['UPDATED'] < 6*60*60) {
echo 'температура '.gg("$r.inRoomText").' '.$arr_s['VALUE'].'<br>';
$r_count++;
$t_avg=$t_avg+$arr_s['VALUE'];
} else {
echo 'данные о температуре '.gg("$r.inRoomText").' не актуальны <br>';
}
}
if (!$r_count) {
echo 'Данные не получены. Взять среднее по последним измерениям <br>';
foreach($check as $r) {
$r_count++;
$t_avg=$t_avg+gg("$r.Temperature");
}
}
$t_avg=round($t_avg/$r_count, 1);
echo "Средняя температура в жилых комнатах $t_avg <br>";
// передать данные в объект термостат
// температуру следует передавать и в объекты других термостатов, котлы которых работают на всю систему
// sg('ts_avghome.status',$t_avg);
sg('thrm_alpha.airCurrentTemp', $t_avg);
sg('thrm_beta.airCurrentTemp', $t_avg);
Далее идет перебор всех объектов класса Thermostat для выполнение методов airCalculate. В свойстве airRequiredTemp будет текущая целевая температура. Но любая система имеет инерцию. Это время, которое нам требуется на прогрев, и время на остывание. Допустим мы хотим понизить температуру ночью на 1 градус, а утром опять её увеличить. После того, как мы убавим, или даже полностью отключим отопитель, пройдет какое то время, прежде чем комната начнет остывать. Так же и при нагреве. Это и есть инерционность системы. Для каждого объекта это свойство индивидуально, и подбирается опытным путём по графикам. Метод airCalculate запишет свойство airShiftTemp в котором будет целевая температура комнаты с учетом инерции системы, чтобы успеть ее достичь.
класс Thermostat метод airCalculateПоказать
Код: Выделить всё
$m=date('i',time());
/* Расчет целевой температуры воздуха в зависимости от времени суток
В результате записывается свойство с историей airRequiredTemp
для построения графика и контроля достижения заданной температуры;
и свойство без истории airShiftTemp для расчета температуры подачи
с учетом инерции системы.
*/
if (defined('THRM_LOG_LEVEL') && THRM_LOG_LEVEL != '') { $log_level = THRM_LOG_LEVEL; } else { $log_level = 0; }
if ($log_level>0) { $ot=$this->object_title; }
if ($log_level>1) { DebMes($ot.'.airCalculate','thrm'); }
$h=(int)date('G',time());
$m=date('i',time());
$airFunc=$this->getProperty('airFunc');
// свойство airFunc может содержать массив из 24 цифр разделенных пробелом, либо только одну цифру.
if (is_numeric($airFunc)) {
$t_desire = $airFunc;
// логи
if ($log_level>1) { DebMes("$ot Свойство airFunc задано числом $t_desire",'thrm'); }
} else {
// логи
if ($log_level>1) { DebMes("$ot Свойство airFunc задано массивом",'thrm'); }
// Преобразовать строку в массив
$arrTemp=explode(' ', $airFunc);
// Проверить корректность массива температур
if (count($arrTemp)<>24) {
if ($log_level>0) { DebMes("$ot ИСКЛЮЧЕНИЕ в методе airCalculate объекта ".$this->object_title.' не корректный массив в свойстве airFunc','thrm'); }
say("$ot Исключение в методе airCalculate объекта ".$this->object_title);
return;
}
// Получить значение температуры текущего часа
$t_desire=$arrTemp[$h];
// следующий элемент массива
$hn=$h+1;
if ($hn>23) {$hn-=24;}
// пропорционально изменить на разницу значения следующего часа
$t_desire+=($arrTemp[$hn]-$arrTemp[$h])*$m/60;
$t_desire=round($t_desire, 1);
// логи
if ($log_level>1) {
DebMes("$ot Установленная температура текущего часа $arrTemp[$h]",'thrm');
DebMes("$ot Установленная температура следующего часа $arrTemp[$hn]",'thrm');
}
}
// логи
if ($log_level>0) {
DebMes("$ot Требуемая температура $t_desire",'thrm');
}
// airRequiredTemp используется в основном для построения графиков
// и показа желаемого значения температуры на элементах термостатов
$this->setProperty('airRequiredTemp', $t_desire);
// пересчитать со сдвигом значение $t_desire если $airFunc не число
// иначе $t_desire останется равным числу в $airFunc
if (!is_numeric($airFunc)) {
// Смотреть в будущее чтобы успеть по причине инерционности системы
$h+=$this->getProperty('timeShift');
if ($h>23) {$h-=24;}
// Получить значение температуры текущего часа
$t_desire=$arrTemp[$h];
// следующий элемент массива
$hn=$h+1;
if ($hn>23) {$hn-=24;}
// пропорционально изменить на разницу значения следующего часа
$t_desire+=($arrTemp[$hn]-$arrTemp[$h])*$m/60;
$t_desire=round($t_desire, 1);
// логи
if ($log_level>1) {
DebMes("$ot Установленная температура будущего часа $arrTemp[$h]",'thrm');
DebMes("$ot Установленная температура следующего часа $arrTemp[$hn]",'thrm');
}
if ($log_level>0) {
DebMes("$ot Требуемая будущая температура $t_desire",'thrm');
}
}
// сохраненная будущая температура не равна расчетной будущей
// перезапись новой температуры, вызов метода расчета t подачи воды
if ($this->getProperty('airShiftTemp') <> $t_desire) {
$this->setProperty('airShiftTemp', $t_desire);
$this->callMethod('waterCalculate', array('airShiftTemp'=>$t_desire));
}
Если целевая температура комнаты изменилась, будет вызван метод waterCalculate для расчета температуры подачи. Тут мы вычислим свойство waterRequiredTemp - требуемая температура подачи котла. От чего она зависит? Факторов довольно много. Самый главный это температура на улице. Чем холоднее, тем больше нужна температура подачи, чтобы компенсировать потери тепла. Я использую классический расчет по температурной кривой с коэффициентами наклона и сдвига, как в большинстве котлов. Далее очень весомый фактор будет момент приближения нашей текущей температуры к целевой. И чтобы не перегреть комнату, нужно понизить подачу. Ещё сильное влияние окажет ветер. Он просто выдувает тепло из дома, и мы должны это компенсировать. Ну и под финал - интенсивность освещённости. Когда солнце светит ярко, энергии тепловой требуется меньше, чем в очень пасмурные дни. Всем этим занимается метод pzaCalculate, результаты вычисления которого использует waterCalculate. Но одной погодозависимой автоматикой сыт не будешь, и если помещение холодное, то правильнее будет разогнать отопитель на полную мощность для начального прогрева. В итоге waterCalculate возьмет максимально допустимую температуру по ПЗА если мы опаздываем на три градуса, далее будет работать по ПЗА, а при приближении целевой на 1 градус начнет уменьшать подачу.
класс Thermostat метод waterCalculateПоказать
Код: Выделить всё
/* Расчет температуры подачи
если фактическая температура воздуха +3 <= заблаговременной расчетной
т.е. запаздываем на 3 градуса, то берем максимальную температуру подачи из ПЗА.
иначе если температура воздуха +1 <= заблаговременной расчетной
т.е. меньше заданной на 1 градус, то берем температуру по ПЗА
иначе начинаем приближаться к заблаговременной температуре воздуха +5
*/
if (defined('THRM_LOG_LEVEL') && THRM_LOG_LEVEL != '') { $log_level = THRM_LOG_LEVEL; } else { $log_level = 0; }
if ($log_level>0) { $ot=$this->object_title; }
if ($log_level>1) { DebMes($ot.'.waterCalculate','thrm'); }
//$pzat = $this->getProperty('pzaTemp'); // температура по ПАЗ
if (isset($params['pzaTemp'])) { $pzat=$params['pzaTemp']; } else { $pzat=$this->getProperty('pzaTemp'); }
$act = $this->getProperty('airCurrentTemp'); // текущая температура воздуха (возможно выцепить без обращения к db)
//$ast = $this->getProperty('airShiftTemp'); // заблаговременный расчет требуемой температуры воздуха
if (isset($params['airShiftTemp'])) { $ast=$params['airShiftTemp']; } else { $ast=$this->getProperty('airShiftTemp'); }
if ($act+3<=$ast) {
$t='максимальная t подачи из ПЗА';
$wrt=$this->callMethod('pzaCalculate', array('t'=>-30)); // Получить максимальную температуру по ПЗА;
}
elseif ($act+1<=$ast) {
$t='t подачи по ПЗА';
$wrt=$pzat;
}
else {
$t='коррекция t при приближении';
$wrt=$pzat;
$wrt-=$pzat*17/100 * min(max((1-$ast+$act),0),1);
$wrt=round($wrt);
}
if ($log_level>0) { DebMes("$ot $t $wrt",'thrm'); }
if ($this->getProperty('waterRequiredTemp') <> $wrt) {
$this->setProperty('waterRequiredTemp', $wrt);
// Запуск исполняющих методов
$this->callMethod('setTemperature', array('t'=>$wrt));
$this->callMethod('positionServo');
}
// подумать когда и при каких условиях вызывать чтобы сократить выполнение кода
$this->callMethod('workDecision');
Теперь о самом методе pzaCalculate. В нем как раз и происходит расчет температуры по ПЗА. Метод вызывается при изменении уличной температуры. Рассчитывает ПЗА и сразу вызывает waterCalculate для перерасчета подачи. Тут как раз и происходит расчет по температуре улицы, скорости ветра и освещенности. Не все коэффициенты выведены в свойства объектов. Многие из них прописаны в коде. Для точной настройки нужно подгонять их под свой дом индивидуально. В этом очень помогают графики. О них мы тоже попозже поговорим.
класс Thermostat метод pzaCalculateПоказать
Код: Выделить всё
/* Расчет требуемой температуры подачи по ПЗА
Учитывается уличная температура, скорость ветра, яркость солнца
Коэффициенты влияния этих факторов указаны в коде
*/
if (defined('THRM_LOG_LEVEL') && THRM_LOG_LEVEL != '') { $log_level = THRM_LOG_LEVEL; } else { $log_level = 0; }
if ($log_level>0) { $ot=$this->object_title; }
if ($log_level>1) { DebMes($ot.'.pzaCalculate','thrm'); }
// температура улица. ВНИМАНИЕ данные берутся с объекта улицы
if (isset($params['t'])) { $t =$params['t']; } else { $t = gg('DrivewayArea.Temperature'); }
// коэффициент выбора кривой. Поднимает хвост графика. Увеличить для + в морозы
if (isset($params['k1'])) { $k1 =$params['k1']; } else { $k1 = $this->getProperty('K1'); }
// коэффициент правки всей кривой. Перемещает вверх/вниз весь график
if (isset($params['k2'])) { $k2 =$params['k2']; } else { $k2 = $this->getProperty('K2'); }
// значение по умолчанию
if (!$k1) { $k1=1.5; }
if (!$k2) { $k2=20; }
// Рассчитать изгиб кривой
$Tp = sqrt((20-$t)*$k1)*10;
if (!isset($params['t']) && $log_level>1) { DebMes("$ot Изгиб кривой $Tp",'thrm'); }
// При увеличении желаемой комнатной температуры на 1°C кривая традиционно смещается на 5°C:
$Tp = $Tp + ($k2-20)*5;
if (!isset($params['t']) && $log_level>1) { DebMes("$ot Смещение кривой $Tp",'thrm'); }
// Правка на ветер
// <3 Слабый <6 Сильный <9 Очень сильный Иначе Шквальный
// поправку вносим от 0 до 10 м*с. Корректировка на 25%
$Tp+=$Tp*25/100 * min(max(gg('weather_now.windSpeed')/10,0),1);
if (!isset($params['t']) && $log_level>1) { DebMes("$ot Поправка на ветер $Tp",'thrm'); }
// Правка на солнце
// Освещенность наблюдается от 0 до 600 пунктов. Понижать t будет от 200 до 600
// Корректировка на 10%
$Tp-=$Tp*10/100 * min(max((gg('DrivewayArea.Luminiscence')-200)/400,0),1);
if (!isset($params['t']) && $log_level>1) { DebMes("$ot Поправка на солнце $Tp",'thrm'); }
// округлить, ограничить и записать
$Tp = round($Tp);
$Tp = min($Tp,85);
$Tp = max($Tp,20);
if (!isset($params['t']) && $log_level>0) { DebMes("$ot Итоговая t по ПЗА $Tp",'thrm'); }
// при передаче параметра t вернуть ответ для графиков. Иначе запуск метода
if (isset($params['t'])) {
if ($log_level>0) { DebMes("$ot На запрос уличной $t отправлен ответ $Tp",'thrm'); }
return($Tp);
} else {
$this->setProperty('pzaTemp', $Tp);
$this->callMethod('waterCalculate', array('pzaTemp'=>$Tp));
}
Далее по цепочке waterCalculate вызывает методы setTemperature и positionServo. В общем коде этих методов нет ничего интересного. Тут мы прописывает код в методе объектов. Например для объекта котла, подключенного через контроллер MyHeat в методе setTemperature будет отправка температуры подачи котлу, по средствам API контроллера. Код я выложу в самом конце. Сейчас мы продолжим обсуждать работу класса. Метод positionServo используется для объектов смесительных узлов. В нем мы поворачиваем трехходовой кран в нужную сторону для получения нужной t подачи. То есть у котла мы управляем температурой подачи, а у смесительного узла крутим сервопривод.
waterCalculate вызывает ещё один метод. Это WorkDecision. Он примет решение о полном включении или отключении отопителя, или циркуляционного насоса смесительного узла. Будут вызваны методы turnOn и turnOff. их коде устанавливаются таймеры минимальной работы и паузы. Без них, в ситуации нахождения на грани равенства температур, котел может постоянно включаться и выключаться. Тут работает правило, что если включились, то должны работать какое то время. А если выключились, то несколько минут ждем. Это убирает тактование. Очень полезно для электрических котлов, да и для всех в целом.
класс Thermostat метод workDecisionПоказать
Код: Выделить всё
/* Принимает решение о работе котла или насоса, на основе текущей и требуемой температуры воздуха
Запускается из метода waterCalculate, а так же может быть вызван при необходимости проверки решения
о работе котла из других элементов системы
*/
if (defined('THRM_LOG_LEVEL') && THRM_LOG_LEVEL != '') { $log_level = THRM_LOG_LEVEL; } else { $log_level = 0; }
if ($log_level>0) { $ot=$this->object_title; }
if ($log_level>1) { DebMes($ot.'.workDecision','thrm'); }
// Не выполнять логику если установлен ручной режим
if (!$this->getProperty('auto')) {
if ($log_level>0) { DebMes("$ot Выполнение запрещено. auto режим не выбран",'thrm'); }
return;
}
// Сбор данных
$s = $this->getProperty('status');
$t = $this->getProperty('Title');
$n = $this->object_title;
$t_desire = $this->getProperty('airShiftTemp');
// гистерезис и значение по умолчанию
$hyst = $this->getProperty('hysteresis');
if (!is_numeric($hyst)) {$hyst = 0.2;}
// предельные температуры подачи и значения по умолчанию
$waterMaxTemp = $this->getProperty('waterMaxTemp');
$waterMinTemp = $this->getProperty('waterMinTemp');
if (!is_numeric($waterMaxTemp)) {$waterMaxTemp = 75;}
if (!is_numeric($waterMinTemp)) {$waterMinTemp = 10;}
// Текущая температура подачи. Если данных нет, то принять за 40
$waterCurrentTemp = $this->getProperty('waterCurrentTemp');
if (!is_numeric($waterCurrentTemp)) {$waterCurrentTemp = 40;}
// Получить значение метода, запрещающего работу
$mayBanOn = intval($this->callmethod('mayBanOn'));
// При запрете метод вернет 2. Преобразовать ответ в true / false
if ($log_level>1) { DebMes("$ot метод mayBanOn вернул $mayBanOn",'thrm'); }
if ($mayBanOn == 2) {$mayBanOn = true;} else {$mayBanOn = false;}
if ($s) { // *** котел сейчас работает, проверка решения на Отключение
// текущая t воздуха >= заблаговременной требуемой + гистерезис
if ($this->getProperty('airCurrentTemp') >= $t_desire + $hyst || $mayBanOn || $waterCurrentTemp > $waterMaxTemp) {
// Если существует таймер
if (timeOutExists($n.'_work') && !$mayBanOn && $waterCurrentTemp < $waterMaxTemp) {
if ($log_level>0) { DebMes("$ot Обеспечение минимального времени работы котла $t",'thrm'); }
} else {
$this->callMethod('turnOff');
}
}
} else { // *** котел сейчас НЕ работает, проверка решения на Включение
// текущая t воздуха <= заблаговременной требуемой - гистерезис
if (($this->getProperty('airCurrentTemp') <= $t_desire - $hyst || $waterCurrentTemp < $waterMinTemp) && !$mayBanOn) {
// Если существует таймер паузы
if (timeOutExists($n.'_nowork')) {
if ($log_level>0) { DebMes("$ot Обеспечение минимальной паузы перед включением котла $t",'thrm'); }
} else {
$this->callMethod('turnOn');
}
}
}
класс Thermostat методы turnOn и turnOffПоказать
Код: Выделить всё
if (defined('THRM_LOG_LEVEL') && THRM_LOG_LEVEL != '') { $log_level = THRM_LOG_LEVEL; } else { $log_level = 0; }
if ($log_level>0) { $ot=$this->object_title; }
if ($log_level>1) { DebMes($ot.'.turnOff','thrm'); }
$this->setProperty('status',0);
$n = $this->object_title;
// Время минимальной работы
$mintimeoff = $this->getProperty('mintimeoff');
if ( !is_numeric($mintimeoff) ) {$mintimeoff = 20*60;}
// установить таймер паузы
setTimeOut($n.'_nowork', "debmes('Tаймер $n закончен'); cm('$n.workDecision');", $mintimeoff);
// Удалить таймер работы
clearTimeOut($n.'_work');
Код: Выделить всё
if (defined('THRM_LOG_LEVEL') && THRM_LOG_LEVEL != '') { $log_level = THRM_LOG_LEVEL; } else { $log_level = 0; }
if ($log_level>0) { $ot=$this->object_title; }
if ($log_level>1) { DebMes($ot.'.turnOn','thrm'); }
$this->setProperty('status',1);
$n = $this->object_title;
// Время минимальной работы
$mintimeon = $this->getProperty('mintimeon');
if ( !is_numeric($mintimeon) ) {$mintimeon = 15*60;}
//установить таймер работы
setTimeOut($n.'_work', "debmes('Tаймер $n закончен'); cm('$n.workDecision');", $mintimeon);
// Удалить таймер паузы
clearTimeOut($n.'_nowork');
Для управления объектами класса можно вывести их в меню или на сцены. Код шаблона отображения покажет все необходимые элементы.
класса Thermostat Шаблон отображенияПоказать
Код: Выделить всё
<svg width="100%" height="155px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="fg%.object_id%">
<feGaussianBlur in="SourceGraphic" stdDeviation="1" />
</filter>
<clipPath id="cut%.object_id%" >
<rect x="0" y="0" rx="4" ry="4" width="60" height="35" />
</clipPath>
</defs>
<! -- Название термостата по описанию объекта -->
<text x="0" y="14" fill="rgb(48, 48, 48)" stroke="none" font-size="16px">%.object_description%</text>
<! -- Текущая температура воздуха -->
<g transform="translate(194,25)">
<title>Текущая температура воздуха</title>
<rect x="0" y="1" rx="4" ry="4" width="60" height="35" fill="none" stroke="#999999" stroke-width="1" filter="url(#fg%.object_id%)" clip-path="inset(-0.2px 0px 0.2px 0px round 1.2px)"/>
<rect x="0" y="0" rx="4" ry="4" width="60" height="35" fill="none" stroke="#dddddd" stroke-width="1"/>
<text x="7" y="11" fill="rgb(150, 150, 150)" font-size="10px">Текущая</text>
<text x="7" y="30" fill="rgb(48, 48, 48)" font-weight="bold" font-size="17px">%.airCurrentTemp%<tspan font-size="12px">°C</tspan></text>
</g>
<! -- Индикатор работы и таймеров -->
<g transform="translate(1,70)">
<title>Индикатор работы и таймеров</title>
<rect x="0" y="1" rx="4" ry="4" width="39" height="35" fill="none" stroke="#999999" stroke-width="1" filter="url(#fg%.object_id%)" clip-path="inset(-0.2px 0px 0.2px 0px round 1.2px)"/>
<g style='display:%.status|"none;inline"%' onClick='callMethod("%.turnOff");'>
<rect x="0" y="0" rx="4" ry="4" width="39" height="35" fill="white" stroke="#dddddd" stroke-width="1"/>
<! -- Значок пламени -->
<g fill="none" stroke="black" stroke-width="1.5">
<path d="m 13,6 c 6,10 -6,10 0,20" />
<path d="m 20,6 c 6,10 -6,10 0,20" />
<path d="m 27,6 c 6,10 -6,10 0,20" />
<path d="m 7,28 25,0" />
</g>
</g>
<g style='display:%.status|"inline;none"%' onClick='callMethod("%.turnOn");'>
<rect x="0" y="0" rx="4" ry="4" width="39" height="35" fill="white" stroke="#dddddd" stroke-width="1"/>
</g>
<! -- Рамки таймеров -->
<rect id="greentimer%.object_id%" x="3" y="3" rx="1" ry="1" width="33" height="29" fill="none" stroke="gold" stroke-width="4" style='display:none'/>
<rect id="redtimer%.object_id%" x="3" y="3" rx="1" ry="1" width="33" height="29" fill="none" stroke="red" stroke-width="4" style='display:none'/>
</g>
<! -- ПЗА температура воды -->
<g transform="translate(52,70)">
<title>температура по ПЗА</title>
<rect x="0" y="1" rx="4" ry="4" width="60" height="35" fill="none" stroke="#999999" stroke-width="1" filter="url(#fg%.object_id%)" clip-path="inset(-0.2px 0px 0.2px 0px round 1.2px)"/>
<rect x="0" y="0" rx="4" ry="4" width="60" height="35" fill="none" stroke="#dddddd" stroke-width="1"/>
<text x="7" y="11" fill="rgb(150, 150, 150)" font-size="10px">ПЗА вода</text>
<text x="6" y="30" fill="rgb(48, 48, 48)" font-weight="bold" font-size="17px">%.pzaTemp%<tspan font-size="13px">°C</tspan></text>
</g>
<! -- Расчетная температура воды -->
<g transform="translate(123,70)">
<title>Расчетная температура теплоносителя</title>
<rect x="0" y="1" rx="4" ry="4" width="60" height="35" fill="none" stroke="#999999" stroke-width="1" filter="url(#fg%.object_id%)" clip-path="inset(-0.2px 0px 0.2px 0px round 1.2px)"/>
<rect x="0" y="0" rx="4" ry="4" width="60" height="35" fill="none" stroke="#dddddd" stroke-width="1"/>
<text x="7" y="11" fill="rgb(150, 150, 150)" font-size="10px">Расчетная</text>
<text x="6" y="30" fill="rgb(48, 48, 48)" font-weight="bold" font-size="17px">%.waterRequiredTemp%<tspan font-size="13px">°C</tspan></text>
</g>
<! -- Текущая температура воды -->
<g transform="translate(194,70)">
<title>Текущая температура теплоносителя</title>
<rect x="0" y="1" rx="4" ry="4" width="60" height="35" fill="none" stroke="#999999" stroke-width="1" filter="url(#fg%.object_id%)" clip-path="inset(-0.2px 0px 0.2px 0px round 1.2px)"/>
<rect x="0" y="0" rx="4" ry="4" width="60" height="35" fill="none" stroke="#dddddd" stroke-width="1"/>
<text x="7" y="11" fill="rgb(150, 150, 150)" font-size="10px">Текущая</text>
<text x="6" y="30" fill="rgb(48, 48, 48)" font-weight="bold" font-size="17px">%.waterCurrentTemp%<tspan font-size="13px">°C</tspan></text>
</g>
<! -- Сообщения -->
<g transform="translate(78,115)">
<title>Сообщения</title>
<rect x="0" y="1" rx="4" ry="4" width="105" height="35" fill="none" stroke="#999999" stroke-width="1" filter="url(#fg%.object_id%)" clip-path="inset(-0.2px 0px 0.2px 0px round 1.2px)"/>
<rect x="0" y="0" rx="4" ry="4" width="105" height="35" fill="none" stroke="#dddddd" stroke-width="1"/>
<text x="4" y="14" fill="rgb(150, 150, 150)" font-size="10px">вкл по температуре</text>
<text x="4" y="25" fill="rgb(150, 150, 150)" font-size="10px">уст. таймер работы</text>
</g>
<! -- Гистерезис -->
<g transform="translate(194,115)">
<title>Отклонение вверх и вниз</title>
<g onClick='callMethod("%.workDecision");' >
<rect x="0" y="1" rx="4" ry="4" width="60" height="35" fill="none" stroke="#999999" stroke-width="1" filter="url(#fg%.object_id%)" clip-path="inset(-0.2px 0px 0.2px 0px round 1.2px)"/>
<rect x="0" y="0" rx="4" ry="4" width="60" height="35" fill="none" stroke="#dddddd" stroke-width="1"/>
<text x="4" y="11" fill="rgb(150, 150, 150)" font-size="10px">Гистерезис</text>
<text x="6" y="30" fill="rgb(48, 48, 48)" font-weight="bold" font-size="17">%.hysteresis%<tspan font-size="13px">°C</tspan></text>
</g>
</g>
<! -- Авто -->
<g transform="translate(1,115)">
<title>Автоматическое или ручное управление</title>
<g style='display:%.auto|"none;block"%' onClick='ajaxSetGlobal("%.auto", 0); callMethod("%.workDecision");'>
<rect x="0" y="1" rx="4" ry="4" width="66" height="35" fill="#2f89cd" stroke="#999999" stroke-width="1" filter="url(#fg%.object_id%)" clip-path="inset(-0.2px 0px 0.2px 0px round 1.2px)"/>
<rect x="0" y="0" rx="4" ry="4" width="66" height="35" fill="none" stroke="#dddddd" stroke-width="1"/> <! -- тонкий контур рамки по середине -->
<rect x="44" y="2" rx="3" ry="3" width="20" height="31" fill="#f6f6f6" stroke="#999999" stroke-width="1" filter="url(#fg%.object_id%)"/> <! -- размытая рамка наружу и во внутрь -->
<rect x="44" y="2" rx="3" ry="3" width="20" height="31" fill="#f6f6f6" stroke="#dddddd" stroke-width="1"/> <! -- контур с заливкой внутри -->
<text x="4" y="23" fill="white" font-weight="bold" font-size="17">auto</text>
</g>
<g style='display:%.auto|"block;none"%' onClick='ajaxSetGlobal("%.auto", 1); callMethod("%.workDecision");'>
<rect x="0" y="1" rx="4" ry="4" width="66" height="35" fill="#e9e9e9" stroke="#999999" stroke-width="1" filter="url(#fg%.object_id%)" clip-path="inset(-0.2px 0px 0.2px 0px round 1.2px)"/>
<rect x="0" y="0" rx="4" ry="4" width="66" height="35" fill="none" stroke="#dddddd" stroke-width="1"/>
<rect x="2" y="2" rx="3" ry="3" width="20" height="31" fill="#f6f6f6" stroke="#999999" stroke-width="1" filter="url(#fg%.object_id%)"/>
<rect x="2" y="2" rx="3" ry="3" width="20" height="31" fill="#f6f6f6" stroke="#dddddd" stroke-width="1"/>
<text x="25" y="21" fill="rgb(48, 48, 48)" font-weight="bold" font-size="11">manual</text>
</g>
<!-- размытая и обрезанная общая рамка -->
</g>
<! -- График расчетной температуры воздуха -->
<g transform="translate(1,59)" >
<title>Расчет температуры воздуха по суточному термостату</title>
<rect x="0" y="-33" rx="4" ry="4" width="182" height="35" fill="none" stroke="#999999" stroke-width="1" filter="url(#fg%.object_id%)" clip-path="inset(-0.2px 0px 0.2px 0px round 1.2px)"/>
<rect x="0" y="-34" rx="4" ry="4" width="182" height="35" fill="none" stroke="#dddddd" stroke-width="1"/>
<text x="7" y="-23" fill="rgb(150, 150, 150)" font-size="10px">Расчетная температура воздуха</text>
<text x="129" y="-4" fill="rgb(48, 48, 48)" font-weight="bold" font-size="17px">%.airRequiredTemp%<tspan font-size="13px">°C</tspan></text>
<g transform="rotate(270)" fill="rgb(90, 90, 90)" >
<rect id="gr%.object_id%0" width="0" height="4" y="2" />
<rect id="gr%.object_id%1" width="0" height="4" y="7" />
<rect id="gr%.object_id%2" width="0" height="4" y="12" />
<rect id="gr%.object_id%3" width="0" height="4" y="17" />
<rect id="gr%.object_id%4" width="0" height="4" y="22" />
<rect id="gr%.object_id%5" width="0" height="4" y="27" />
<rect id="gr%.object_id%6" width="0" height="4" y="33" />
<rect id="gr%.object_id%7" width="0" height="4" y="38" />
<rect id="gr%.object_id%8" width="0" height="4" y="43" />
<rect id="gr%.object_id%9" width="0" height="4" y="48" />
<rect id="gr%.object_id%10" width="0" height="4" y="53" />
<rect id="gr%.object_id%11" width="0" height="4" y="58" />
<rect id="gr%.object_id%12" width="0" height="4" y="64" />
<rect id="gr%.object_id%13" width="0" height="4" y="69" />
<rect id="gr%.object_id%14" width="0" height="4" y="74" />
<rect id="gr%.object_id%15" width="0" height="4" y="79" />
<rect id="gr%.object_id%16" width="0" height="4" y="84" />
<rect id="gr%.object_id%17" width="0" height="4" y="89" />
<rect id="gr%.object_id%18" width="0" height="4" y="95" />
<rect id="gr%.object_id%19" width="0" height="4" y="100" />
<rect id="gr%.object_id%20" width="0" height="4" y="105" />
<rect id="gr%.object_id%21" width="0" height="4" y="110" />
<rect id="gr%.object_id%22" width="0" height="4" y="115" />
<rect id="gr%.object_id%23" width="0" height="4" y="120" />
</g>
</g>
</svg>
<script type="text/javascript">
var url=ROOTHTML;
url+='objects/?script='+encodeURIComponent('scriptTimeOutExists')+'&timername=%.object_title%_nowork';
$.ajax({
url: url
}).done(function(data) {
if (data==0) {
document.getElementById('redtimer%.object_id%').setAttribute('style', 'display:none');
} else {
document.getElementById('redtimer%.object_id%').setAttribute('style', 'display:block');
}
});
url+='objects/?script='+encodeURIComponent('scriptTimeOutExists')+'&timername=%.object_title%_work';
$.ajax({
url: url
}).done(function(data) {
if (data==0) {
document.getElementById('greentimer%.object_id%').setAttribute('style', 'display:none');
} else {
document.getElementById('greentimer%.object_id%').setAttribute('style', 'display:block');
}
});
// Получить значение аир функции и разбить на массив
//var tstring = '23 23 23 23 23 23.5 24 24 24 24 23.5 23.5 23.5 23.5 23.5 23.5 23.7 24 24 24 24 24 23.5 23';
var tstring = '%.airFunc%';
var tarr = tstring.split(' ');
// Дополнить массив до 24 последним элементов
var i = tarr.length + 1;
while (i <= 24) {
tarr.push(tarr[tarr.length-1]);
i++;
}
// Перебрать массив для установки графика
var h = new Date();
tarr.forEach(function(item, i, temparr) {
document.getElementById('gr%.object_id%' + i).setAttribute('width', (item - Math.max.apply(null, tarr) + 2) * 9);
if (h.getHours() == i) {
document.getElementById('gr%.object_id%' + i).setAttribute('fill', "gold");
}
});
</script>
Теперь о том, как установить, и обеспечить работу.
Убедимся, что в системе нет одноименного класса Thermostat. Импортируем класс, можно вместе с объектами моих отопителей. Будет проще разобраться. Потом удалите объекты и создадите свои. После импорта можно сразу добавить один из объектов в меню, чтобы убедиться что всё работает. Затем нужно настроить вызов методов класса. Всего будет три точки от куда запускаются методы.
1. Из метода onNewMinute каждые 5 минут происходит вызов методов airCalculate. Пример кода в самом начале. Нужно для суточного термостата. Далее методы класса будут вызываются по цепочке при необходимости.
2. При изменении температуры комнатных датчиков запускается сценарий tempHomeChanges. Он установит свойство airCurrentTemp что приведет к вызову метода waterCalculate.
Если у вас только один датчик температуры, то можно сразу писать его значение в свойство airCurrentTemp. Тогда сценарий tempHomeChanges не нужен. Сценарий только рассчитывает среднюю температуру комнат.
3. При изменении уличной температуры нужно вызвать метод pzaCalculate. Тут есть момент. В коде метода pzaCalculate есть получение свойства уличной температуры weather_now.temperature, скорости ветра weather_now.windSpeed и интенсивности освещённости DrivewayArea.Luminiscence. Замените их на свои. Если в вашей системе нет этих данных, тогда закомментируйте в методе pzaCalculate код поправки температуры подачи на эти факторы. Но без уличной температуры никак не обойтись.
Для ведения логов можно добавить в файл config.php строку Define('THRM_LOG_LEVEL', 2); Тогда все комментарии будут писаться в файл ...\cms\debmes\ГГГГ-ММ-ДД_thrm.log
0 - не писать, 1 - только основные логи, 2 - вся отладочная информация.
Ожидайте продолжение в ближайшее время! Скоро выложу класс целиком для скачивания.
А пока коротенькое резюме. Класс Thermostat может управлять отопителями по средствам их включения и выключения. Суточный термостат. Рассчитывает температуру подачи на основе ПЗА и целевой температуры дома. При подключении контроллера MyHeat может управлять отопителем по цифровой шине для поддержания целевой температуры. Управление сервоприводом смесительного узла.
Последний раз редактировалось Bagir Вс дек 13, 2020 10:08 pm, всего редактировалось 2 раза.
- За это сообщение автора Bagir поблагодарили (всего 3):
- timurufa86 (Пт дек 25, 2020 8:55 am) • Chainik (Вт дек 29, 2020 5:41 pm) • Nail (Вт мар 02, 2021 5:45 pm)
- Рейтинг: 3.49%
-
- Сообщения: 264
- Зарегистрирован: Чт ноя 08, 2018 5:51 am
- Благодарил (а): 10 раз
- Поблагодарили: 83 раза
Re: Контроллер MY HEAT управление отопительным котлом
переименуйте класс пока не поздно. иначе будут проблемы с совместимостью.
классов с таким названием целое множество.
классов с таким названием целое множество.
- Bagir
- Сообщения: 1614
- Зарегистрирован: Вт сен 17, 2013 6:46 pm
- Откуда: Ярославская область город Углич
- Благодарил (а): 212 раз
- Поблагодарили: 375 раз
Re: Контроллер MY HEAT управление отопительным котлом
Да поздно уже. Конечно можно поправить в коде имя, но зачем? Класс полностью соответствует своему названию. Да и зачем в системе два класса с таким именем? У меня тут есть всё, от расчетов до визуального представления. Да и с ходу управлять другими термостатами этим классом всё равно не получится. Придется делать много поправок. Я намерено выложил в начале код, если кто то захочет взять себе какие то отдельные расчеты температур. Думаю, что успею завтра выложить файлы с классом. Ну а если уж у кого то получится такая ситуация, что в системе будет одноименный класс, и нужно его оставить, то переименовать можно и в файле перед импортом.
- Bagir
- Сообщения: 1614
- Зарегистрирован: Вт сен 17, 2013 6:46 pm
- Откуда: Ярославская область город Углич
- Благодарил (а): 212 раз
- Поблагодарили: 375 раз
Re: Контроллер MY HEAT управление отопительным котлом
Выложил класс. Интересная эта штука. Чем дальше лезешь в расчеты температур, тем больше переделываешь. Если раньше я мог управлять котлом, можно сказать ступенями, то сейчас, с контроллером MyHeat, полная свобода. Поправил расчеты и коэффициенты. Я думаю, что можно добиться идеальной точности для любой системы отопления, подправив настройки для себя.
В начале можно просто поиграться с классом без управления реальным котлом, чтобы посмотреть на сколько отличаются расчеты.
В начале можно просто поиграться с классом без управления реальным котлом, чтобы посмотреть на сколько отличаются расчеты.
-
- Сообщения: 2801
- Зарегистрирован: Пн дек 26, 2016 9:51 am
- Откуда: Екатеринбург
- Благодарил (а): 380 раз
- Поблагодарили: 694 раза
- Контактная информация:
Re: Контроллер MY HEAT управление отопительным котлом
Может все таки подготовить модуль для установки через маркет? Из ваших наработок может получиться отличный модуль plug and play!
Совсем не понял, как подружить класс с котлом, API облачный/локальный? Где что прописать требуется?
Совсем не понял, как подружить класс с котлом, API облачный/локальный? Где что прописать требуется?
Если вам помогло данное сообщение, не поленитесь нажать кнопку "спасибо".
CONNECT | Оборудование | Блог | Дополнения | Email | Telegram
CONNECT | Оборудование | Блог | Дополнения | Email | Telegram
- Bagir
- Сообщения: 1614
- Зарегистрирован: Вт сен 17, 2013 6:46 pm
- Откуда: Ярославская область город Углич
- Благодарил (а): 212 раз
- Поблагодарили: 375 раз
Re: Контроллер MY HEAT управление отопительным котлом
С модулями я работал, но серьёзно эту тему не изучал. Наверное по этому и делаю у себя всё на классах. Возможно в будущем перейду на модули.
Увы, пока только облачный, но обещают сделать и локальный. Когда это произойдет, я конечно перейду, и покажу где что поправить.
Класс в основном занимается расчетами температур подачи по ПЗА и целевой t дома, работой с сервоприводами трехходовых клапанов, и включением отопителя. Контроллер MyHeat, или любой другой, используется для получения данных котла и установки t подачи. Код работы с контроллером есть в личном методе setTemperature.
Пожалуйста поконкретнее о чем именно речь, и я обязательно отвечу.
На сегодняшний день класс у меня отработал уже три зимы. Первый сезон конечно был пристрелочный. Второй год подбирал коэффициенты для моего дома. В эту зиму в структуре класса ничего серьезного уже не менял.
Управляет двумя ступенями электрического котла дома. Долго думал стоит ли ступени реализовывать в классе, но в итоге просто завел два разные объекта котла для первой и второй ступени.
Газовый энергонезависимый котел. Управление вкл/выкл через контакты домашнего термостата.
Газовый настенный котел. Управление через контроллер MyHeat.
Электрический котел в бане. Тоже вкл/выкл.
- Nail
- Сообщения: 376
- Зарегистрирован: Пн мар 05, 2018 7:09 am
- Откуда: Самара
- Благодарил (а): 174 раза
- Поблагодарили: 28 раз
Re: Контроллер MY HEAT управление отопительным котлом
Я так понимаю связанно с Opentherm? Тут игрушка появилась интересная по цене чуть выгоднее , два в одном Zigbee и Opentherm.Bagir писал(а): ↑Вс май 02, 2021 4:49 pmС модулями я работал, но серьёзно эту тему не изучал. Наверное по этому и делаю у себя всё на классах. Возможно в будущем перейду на модули.
Увы, пока только облачный, но обещают сделать и локальный. Когда это произойдет, я конечно перейду, и покажу где что поправить.
Класс в основном занимается расчетами температур подачи по ПЗА и целевой t дома, работой с сервоприводами трехходовых клапанов, и включением отопителя. Контроллер MyHeat, или любой другой, используется для получения данных котла и установки t подачи. Код работы с контроллером есть в личном методе setTemperature.
Пожалуйста поконкретнее о чем именно речь, и я обязательно отвечу.
На сегодняшний день класс у меня отработал уже три зимы. Первый сезон конечно был пристрелочный. Второй год подбирал коэффициенты для моего дома. В эту зиму в структуре класса ничего серьезного уже не менял.
Управляет двумя ступенями электрического котла дома. Долго думал стоит ли ступени реализовывать в классе, но в итоге просто завел два разные объекта котла для первой и второй ступени.
Газовый энергонезависимый котел. Управление вкл/выкл через контакты домашнего термостата.
Газовый настенный котел. Управление через контроллер MyHeat.
Электрический котел в бане. Тоже вкл/выкл.
Не плохо бы потестить.
https://t.me/slsys/69346
Mini AMD A6 1450 Quad-core.Ubuntu Server 18.04 (64-bit). MegaD. Zigbee2mqtt+SLS DIN Mini. Broadlink.
-
- Сообщения: 2801
- Зарегистрирован: Пн дек 26, 2016 9:51 am
- Откуда: Екатеринбург
- Благодарил (а): 380 раз
- Поблагодарили: 694 раза
- Контактная информация:
Re: Контроллер MY HEAT управление отопительным котлом
Эту игрушку тестируем, поддержка в мажоре будет обязательно.
Если вам помогло данное сообщение, не поленитесь нажать кнопку "спасибо".
CONNECT | Оборудование | Блог | Дополнения | Email | Telegram
CONNECT | Оборудование | Блог | Дополнения | Email | Telegram