“灰,吹,凉...”,或智能家居中气候控制的逻辑

智能家居

最近,智能家居的话题越来越流行,越来越多的文章,评论,讨论以及几乎任何问题都可以立即找到一些意见和答案。但是在整个信息世界中,仍然存在一个空白区域,即工作逻辑。我们并不害怕,并决定将有关此问题的准备工作提交给公众。

首先,简要介绍一下要配备自动化系统的对象。这是一栋小公寓楼,每间公寓均配有独立的空调,通风,供暖和地暖系统。

作为主要要求,客户指出:一个用于管理所有智能家居系统的界面,有限的预算和最少的附加布线量。在对自动化系统市场进行了一些研究之后,我们选择了Fibaro的解决方案,因为该解决方案的主要优势几乎可以完美地重复我们的条件。

在本文中,我们将描述基于Z-Wave协议为公寓创建HVAC系统外观的过程。我们希望从社区中获得大量评论,以使我们的决定进入可食用状态。如果取得了预期的结果,那么我们将很高兴与其他出版物一起继续这个周期,在这些出版物中我们将分享使用Z-Wave设备的经验。

因此,我们将描述系统的初始数据和操作条件。

首先,我们想知道如何管理所有系统。作为主机,我们选择了Home Center 2控制器,最初计划创建一个由5个控制器组成的网络并组织该系统,以便由一个控制器来控制建筑物一层中的所有公寓。但是很快就知道,无法通过这种方式构建系统,因为HC2限制了所连接的z波设备的数量,并且将控制器组合到一个网络中只会扩大z波网络的覆盖范围,而不会增加所允许的最大连接设备数量。同时,一个控制器最多只能连接230个设备。因此,仍然只有230个设备可以连接到集成到单个网络中的五个控制器。因此,我们不得不将项目中的控制器数量加倍,并拒绝将它们集成到单个网络中。现在,一台HC2将可用于4-5套公寓,这使我们有机会在每套公寓中使用46到57个Z波设备。

在确定主控制器后,出现了一个问题,即应该收集哪些数据以及如何进行收集。要管理气候,您需要了解公寓的当前状况,即:室内和室外的温度,湿度,二氧化碳水平,门窗的位置,房屋居民的身影。由于项目预算有限,我们拒绝监控湿度和二氧化碳水平。

为了监视室内温度,许多z-wave设备都包含内置的温度传感器,以补充设备的基本功能。当然,还有单独版本的温度传感器。根据我们的项目,每间公寓中将有大约35种设备以某种方式显示温度值。对于每个地板加热回路和加热系统,分别是三个泄漏传感器FIB_FGFS-101,三个红外变送器REM_ZXT120,恒温器RS 014G0160,运动传感器和三个温度传感器DS 18B20。首先,必须监控地板加热回路的温度,以防止镶木地板过热,因为实木复合地板的最高允许温度不超过27度。

温度控制以防止地板过热


温度控制以防止镶木地板过热

由于所有这些温度值都可能彼此严重不同,具体取决于设备的安装位置-为了确定房间中的温度,我们将计算该房间中所有指示器的平均值。

有两种确定室外温度的方法。在HC2中,具有获取城市天气预报的功能,该功能是在初始控制器设置期间设置的。但是,这种确定温度的方法在可接受的精度上并没有不同,因此,出于这些目的,我们将使用安装在建筑物外墙的多个传感器DS 18B20。应当牢记,不得将传感器直接放在立面上,并避免阳光直射。

在任何智能家居中,其创建的主要目标之一就是降低供暖和冷藏室的成本,因此了解门窗的当前位置非常重要。为了关闭暖气和空调,如果窗户或门打开,我们将使用常规的电磁接触传感器,并将其集成到z波网络中,将它们连接到通用二进制传感器FIB_FGBS-001。

连接DS18B20温度传感器

连接DS18B20温度传感器

为了确定居民的身影,我们创建了一个虚拟设备,它是一个按钮。通过单击该按钮,用户通知系统在家中没有人。

虚拟设备-家庭/工作模式启用按钮


虚拟设备-家庭/工作模式启用按钮

收到系统为空的信号后,控制器将关闭所有HVAC系统并切换到节能模式,直到用户准备回家为止。在节能模式下,系统将继续控制温度,并且不允许房间冷却且温度降至18度以下。

客厅中气候控制的另一个重要元素是温度设置。在我们的解决方案中,用户可以通过两种方式进行更改。使用壁式恒温器或通过智能手机或平板电脑使用专门创建的虚拟设备。

在处理了监视公寓中小气候的当前状态之后,我们开始直接研究那些我们必须控制的设备。

每间公寓将配备三菱电机制造的3台空调。计划使用IR转换器REM_ZXT120对其进行控制。这些设备具有预定义的设置,用于控制领先制造商生产的最常见的空调模型,并具有从遥控器学习IR命令的能力。

除空调外,每间公寓还将配备独立的供气和排气通风系统,并使用两通道继电器FIB_FGS-222进行控制。

此外,所有公寓都将有七个加热地板和一个中央加热回路。每个回路均配有带伺服执行器的三位阀。它由RGBW模块FIB_FGRGB-101控制。

在选择并研究了所有必需的设备之后,我们的下一个任务是开发最有效和自给自足的气候控制算法。

可点击的:

公寓中带有气候控制算法的框图

该流程图显示了代表整个HVAC控制系统的基本逻辑的算法。

生成的算法被实现为一个主脚本和多个辅助脚本。在HC2中,这些脚本称为场景,用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


这就是我们计划解决问题的方式。议程上仍有许多问题,有待解决的许多问题,有待克服的许多困难。这是我们对笔的测试,请您善待并理解。

Source: https://habr.com/ru/post/zh-CN398391/


All Articles