[Из песочницы] «Грей, дуй, охлаждай…», или логика управления климатом в умном доме
В последнее время тематика умного дома набирает все большую популярность, появляются все новые и новые статьи, отзывы, обсуждения, и практически на любой вопрос можно сходу найти несколько мнений и ответов. Но во всем этом мире информации по-прежнему остается одна белая область, а именно логика работы. Мы не побоялись и решили представить на суд общественности наши заготовки по этому вопросу.
Для начала пару слов об объекте, который предстоит оснастить системами автоматизации. Это небольшой многоквартирный дом, каждая квартира которого оснащается независимыми системами кондиционирования, вентиляции, отопления и теплого пола.
В качестве основных требований заказчик отметил: единый интерфейс для управления всеми системами умного дома, ограниченный бюджет и минимальное количество дополнительной проводки. После небольшого исследования рынка систем автоматизации мы остановились на решении от Fibaro, так как основные преимущества этого решения практически идеально повторяют наши условия.
В этой статье мы опишем процесс создания подобия HVAC системы для квартиры на базе протокола Z-Wave. Надеемся получить кучу замечаний от сообщества, чтобы довести наше решение до съедобного состояния. Если ожидаемый результат будет достигнут, то мы с удовольствием продолжим этот цикл другими публикациями, в которых будем делиться своим опытом использования Z-Wave устройств.
Итак, опишем исходные данные и условия функционирования нашей системы.
В первую очередь мы задались вопросом, что будет управлять всеми системами. В качестве головного устройства мы остановились на контроллере Home Center 2. Изначально планировалось создать сеть из пяти контроллеров и организовать систему таким образом, чтобы один контроллер управлял всеми квартирами на одном этаже здания. Но вскоре выяснилось, что таким образом построить систему не получится, так как у HC2 есть ограничение на количество подключенных z-wave устройств, а объединение контроллеров в одну сеть дает только расширение зоны действия z-wave сети, но не увеличивает предельно допустимое количество подключенных устройств. Одновременно к одному контроллеру можно подключить не больше 230 устройств. Соответственно, к пяти контроллерам, объединенным в единую сеть, по-прежнему можно подключить лишь 230 устройств. Поэтому нам пришлось увеличить количество контроллеров в проекте в два раза и отказаться от объединения их в единую сеть. Теперь один HC2 будет работать на 4–5 квартир, что дает нам возможность использовать от 46 до 57 z-wave устройств в каждой квартире.
После того, как мы определились с главным контроллером, встал вопрос, какие данные необходимо собирать, и как это делать. Для управления климатом необходимо знать текущее положение дел в квартире, а именно: температуру внутри и снаружи помещения, влажность, уровень CO2, положение окон и дверей, наличие жильцов дома. Поскольку бюджет проекта ограничен, мы отказались от мониторинга влажности и уровня CO2.
Для мониторинга температуры внутри помещения многие z-wave устройства содержат встроенные датчики температуры, дополняющие основной функционал устройства. И, конечно же, существуют датчики температуры в отдельном исполнении. Согласно нашему проекту, в каждой квартире будет примерно 35 устройств, которые так или иначе будут показывать значение температуры. Это три датчика протечки FIB_FGFS-101, три IR преобразователя REM_ZXT120, термостат RS 014G0160, датчики движения, и по три датчика температуры DS 18B20 на каждый контур теплого пола и контур системы отопления. Мониторинг температуры контура теплого пола необходим в первую очередь для того, чтобы не допустить перегрева паркета, т.к. максимально допустимая температура паркета не превышает 27 градусов.
Контроль температуры для защиты паркета от перегрева
Поскольку все эти значения температуры могут достаточно серьезно отличаться друг от друга, в зависимости от того, где устройство установлено — для определения температуры в помещении мы будем высчитывать среднее значение по всем показателям из данного помещения.
Для определения температуры снаружи помещения существуют два варианта. В HC2 есть функция получения прогноза погоды для города, который задается при первоначальной настройке контроллера. Однако такой метод определения температуры не отличается приемлемой точностью, поэтому мы для этих целей будем использовать несколько датчиков DS 18B20, установленных на внешнем фасаде здания. При этом следует учесть, что датчики нужно располагать не напрямую на фасаде и избегать попадания на них прямых солнечных лучей.
В любом умном доме одной из главных целей его создания является снижение затрат на обогрев и охлаждение помещений, поэтому очень важным становится понимание текущего положения окон и дверей. Для того чтобы отключать отопление и кондиционирование, если открыто окно или дверь, мы будем использовать обычные магнитно-контактные датчики, а для их интеграции в сеть z-wave они будут подключены к универсальным бинарным датчикам FIB_FGBS-001.
Подключение датчиков температуры DS18B20
Для определения наличия жильцов дома мы создали виртуальное устройство, которое представляет собой кнопку. При нажатии на эту кнопку пользователь сообщает системе, что дома никого нет.
Виртуальное устройство — кнопки включения режимов дом/работа
Когда в систему поступает сигнал, что дома никого нет, контроллер отключает все системы HVAC и переходит в режим энергосбережения до тех пор, пока пользователь не соберется домой. Находясь в режиме энергосбережения, система продолжает контролировать температуру, и не допустит переохлаждения помещений и снижения температуры ниже отметки в 18 градусов.
Еще один немаловажный элемент управления климатом в жилом помещении это уставка температуры. В нашем решении пользователи смогут изменять ее двумя способами. С помощью настенного термостата или при помощи специально созданного виртуального устройства используя смартфон или планшет.
Разобравшись с мониторингом текущего состояния микроклимата в квартире, мы перешли к изучению непосредственно тех устройств, которыми нам предстояло управлять.
Каждая квартира будет оборудована 3 кондиционерами производства Mitsubishi Еlectric. Управление ими планируется осуществлять при помощи IR преобразователей REM_ZXT120. Эти устройства имеют предустановленные настройки для управления наиболее распространенными моделями кондиционеров от ведущих производителей, а так возможность обучения IR командам с пульта дистанционного управления.
Помимо кондиционеров каждая квартира будет оснащена независимой системой приточно-вытяжной вентиляции, и управление ей будет организовано с использованием двухканальных реле FIB_FGS-222.
Также во всех квартирах будут установлены семь контуров теплого пола и один контур центрального отопления. Каждый контур оснащается трехпозиционным клапаном с сервоприводом. Управляется при помощи RGBW модуля FIB_FGRGB-101.
После подбора и изучения всего необходимого оборудования нашей следующей задачей стала разработка наиболее эффективного и самодостаточного алгоритма управления климатом.
Кликабельно:
На блок-схеме приведен алгоритм, который представляет собой основную логику работы всей системы управления HVAC.
Получившийся алгоритм реализован в виде одного главного скрипта и нескольких вспомогательных. В НС2 эти скрипты называются сценами и пишутся на lua.
Для того чтобы не сильно загружать контроллер, сцены запускаются только при срабатывании так называемых триггеров.
Для основной сцены в качестве триггеров выступают следующие события:
- один из показателей температуры изменится более чем на один градус
- пользователь изменил уставку температуры
- пользователь включил/выключил режим на работе
- окно или дверь (на лоджию или входная) были открыты/закрыты
--[[
%% properties
3 Temperature --температура за окном
85 value --датчик температуры 1
86 value --датчик температуры 2
87 value --датчик температуры 3
%% events
%% globals
tempSet
--]]
local temp1 = tonumber(fibaro:getValue(85, "value")) -- датчик температуры 1
local temp2 = tonumber(fibaro:getValue(86, "value"))-- датчик температуры 2
local temp3 = tonumber(fibaro:getValue(87, "value"))-- датчик температуры 3
local tempOUT = tonumber(fibaro:getValue(3, "Temperature"))-- датчик температуры за окном
local IDCooler = 99 -- вентиляция
local IDCond = 100 -- кондиционер
local IDCondHeat = 102 -- кондиционер обогрев (для тестирования)
local IDFloor = 23 -- теплый пол
local IDHeat = 24 -- радиатор
local tempset = fibaro:getGlobalValue("tempSet")
local workmode = fibaro:getGlobalValue("Workmode")
local tempInside = (temp1 + temp2 + temp3) / 3
local date = os.date("!*t", now)
local currtime = date.hour*60 + date.min --текущее время в минутах
local d = tempset - tempInside
local w = tempset - tempOUT
--globals:
-- Workmode
-- TempSet
-- WinStatus
-- Isventnow
-- CHeating
local cHeating = "on"
local winStatus = "closed"
print("Starting Climate Control")
print("t в помещении = "..tempInside..", t целевая = "..tempset)
print("Workmode: "..workmode..", Windows: "..winStatus,", Central Heating: "..cHeating)
--режим на работе включен
if (fibaro:getGlobalValue("Workmode1") == "At work")
then
--если прохладно
if (tempInside < 18)
then --включить подогрев
if (cHeating == "on")
then -- включить радиаторы
print("включить радиаторы")
fibaro:call(IDHeat, "turnOn")
if(Isventnow == "no")
then
fibaro:call(IDCooler, "turnOff")
end
fibaro:call(IDCondHeat, "turnOff")
fibaro:call(IDCond, "turnOff")
fibaro:call(IDFloor, "turnOff")
elseif (windows == "closed")
then -- включить кондиционер наобогрев
print("включить обогрев кондиционера")
fibaro:call(IDCondHeat, "turnOn")
fibaro:call(IDCond, "turnOn")
fibaro:call(IDFloor, "turnOff")
if(Isventnow == "no")
then
fibaro:call(IDCooler, "turnOff")
end
fibaro:call(IDHeat, "turnOff")
end
--если жарко и радиаторы включены
elseif (tempInside > 21)
then --выключить радиаторы
if(fibaro:getValue(IDHeat, value) >0)
then
print("выключить радиаторы")
fibaro:call(IDHeat, "turnOff")
else
fibaro:call(IDCondHeat, "turnOn")
fibaro:call(IDCond, "turnOn")
fibaro:call(IDFloor, "turnOff")
if(Isventnow == "no")
then
fibaro:call(IDCooler, "turnOff")
end
end
end
-- если достигли нужной температуры
elseif d < 1 and d > -1
then
print("выключаем всё")
--выключить кондиционер
fibaro:call(IDCondHeat, "turnOff")
fibaro:call(IDCond, "turnOff")
--выключить вентиляцию
if(Isventnow == "no")
then
fibaro:call(IDCooler, "turnOff")
end
--выключить радиаторы
fibaro:call(IDHeat, "turnOff")
--выключить теплый пол
fibaro:call(IDFloor, "turnOff")
-- если включено центральное отопление
elseif (cHeating == "on")
then --включено центральное отопление
if (d >= 1)
then --обогрев
if (d <= 3)
then
print("включить теплый пол")
--включить теплый пол
fibaro:call(IDFloor, "turnOn")
fibaro:call(IDCondHeat, "turnOff")
fibaro:call(IDCond, "turnOff")
fibaro:call(IDHeat, "turnOff")
fibaro:call(IDCooler, "turnOff")
elseif (d > 3)
then
print("включить теплый пол и радиаторы")
--включить теплый пол
fibaro:call(IDFloor, "turnOn")
--включить радиаторы
fibaro:call(IDHeat, "turnOn")
fibaro:call(IDCondHeat, "turnOff")
fibaro:call(IDCond, "turnOff")
if(Isventnow == "no")
then
fibaro:call(IDCooler, "turnOff")
end
end
elseif (d <= -1)
then --охлаждение
print("включить вентиляцию")
-- включить вентиляцию
if(Isventnow == "no")
then
fibaro:call(IDCooler, "turnOn")
end
lastCondition = currTime
end
--если выключено центральное отопление
elseif (cHeating == "off")
then --обогрев
if (d >= 1)
then
if (w <= 0)
then
print("включить вентиляцию")
-- включить вентиляцию
if(Isventnow == "no")
then
fibaro:call(IDCooler, "turnOn")
end
fibaro:call(IDCondHeat, "turnOff")
lastCondition = currTime
elseif (d < 4)
then
print("включить вентиляцию")
-- включить вентиляцию
fibaro:call(IDCondHeat, "turnOff")
if(Isventnow == "no")
then
fibaro:call(IDCooler, "turnOn")
end
lastCondition = currTime
elseif (winStatus == "closed")
then
print("включить кондиционер на обогрев")
-- включить кондиционер на обогрев
fibaro:call(IDCondHeat, "turnOn")
fibaro:call(IDCond, "turnOn")
if(Isventnow == "no")
then
fibaro:call(IDCooler, "turnOff")
end
end
elseif (d <= -1)
then --охлаждение
if(w >= 0)
then
if(d > -4)
then
print("включить вентиляцию")
-- включить вентиляцию
if(Isventnow == "no")
then
fibaro:call(IDCooler, "turnOn")
end
fibaro:call(IDCondHeat, "turnOff")
fibaro:call(IDCond, "turnOff")
elseif (winStatus == "closed")
then
print("включить кондиционер")
-- включить кондиционер
fibaro:call(IDCond, "turnOn")
fibaro:call(IDCondHeat, "turnOff")
if(Isventnow == "no")
then
fibaro:call(IDCooler, "turnOff")
end
end
elseif (winStatus == "closed")
then
print("включить кондиционер")
-- включить кондиционер
fibaro:call(IDCond, "turnOn")
fibaro:call(IDCondHeat, "turnOff")
if(Isventnow == "no")
then
fibaro:call(IDCooler, "turnOff")
end
end
end
end
Как видно из кода основной сцены, в своей работе она использует глобальные переменные:
- Workmode {«at work», «at home»} //режим на работе
- TempSet //температура уставки
- WinStatus {'opened», «closed»} //открыты ли окна и двери на лоджию (нужны для ограничения работы кондиционеров)
- CHeating {«on», «off»} //включено ли центральное отопление
Мониторинг текущего положения окон и дверей в квартире будет осуществляться вспомогательной сценой. Результат ее работы хранится в глобальной переменной WinStatus. Так же отдельная сцена контролирует изменение температуры датчиков возле насосов центрального отопления в подвале здания и определяет включено ли центральное отопление. Результат ее работы хранится в глобальной переменной CHeating.
Так как для комфорта очень важно чтобы воздух в квартире был свежий, мы решили, что будет правильно сделать систему принудительного проветривания помещений через приточно-вытяжную вентиляцию. Если в течение последних трех часов вентиляция не работала, то автоматически запустится сценарий проветривания помещения длительностью 15 минут. Принудительное проветривание не осуществляется если включен режим «на работе».
function vent_forced()
local workmode = fibaro:getGlobal('Workmode')
local isventnow = fibaro:getGlobal('Isventnow')
local lastModified = fibaro:getGlobalModificationTime('Isventnow')
if ((os.time() - lastModified) < 10800) then
print ("время с последнего проветривания в секундах "..(os.time() - lastModified))
print ("с последнего проветривания прошло меньше 3-х часов")
end
if ( workmode == 'At home' and isventnow == 'no' and (os.time() - lastModified) > 10800 ) then
print ("время с последнего проветривания в секундах "..(os.time() - lastModified))
fibaro:call(99, "turnOn")
fibaro:setGlobal('Isventnow', 'yes')
print ("с последнего проветривания прошло больше 3 часов")
print ("принудительное проветривание помещения включено")
fibaro:sleep(900000)
fibaro:call(99, "turnOff")
fibaro:setGlobal('Isventnow', 'no')
print ("принудительное проветривание помещения выключено")
end
end
local sourceTrigger = fibaro:getSourceTrigger()
if (sourceTrigger["type"] == "autostart") then
while true do
fibaro:debug('Сцена запущена автоматически')
local currentDate = os.date("*t")
if (currentDate.min >= 0 and currentDate.min <= 60) then
vent_forced()
end
fibaro:debug('Сцена отработала, следующий запуск через 1 час')
fibaro:sleep(3600*1000)
end
end
Вот так мы планируем решать поставленную задачу. На повестке дня стоит еще много вопросов, предстоит решить много проблем и преодолеть множество трудностей. Это наша проба пера, просим вас отнестись с добротой и пониманием.