摘要:介紹一種利用組態(tài)軟件MCGS 和OPC 服務(wù)器ZOPC_SERVER 以及ZLGCAN 接口卡實現(xiàn)基于CAN-bus 總線的模擬空調(diào)溫/濕度控制系統(tǒng)的方法。
一、系統(tǒng)結(jié)構(gòu)
本系統(tǒng)是一個室內(nèi)空調(diào)溫/濕度控制系統(tǒng)的模擬系統(tǒng)數(shù)據(jù)采集及控制中心通過CAN-bus 總線定時采集各個房間的溫/濕度數(shù)據(jù),并對各個房間的溫/濕度進行控制。系統(tǒng)的數(shù)據(jù)采集及控制中心由上位機的硬件即任一款ZLGCAN 系列接口卡和PC 構(gòu)成,軟件由組態(tài)軟件MCGS 和ZOPC_Server 組成??刂剖壹聪挛粰C由DP-668 實驗儀和ZLGCAN 系列接口卡中的PCI-9810 接口卡模擬。
[align=center][IMG=系統(tǒng)結(jié)構(gòu)圖]/uploadpic/tech/2007/7/20070730154418131747.jpg[/IMG]
圖 1 系統(tǒng)結(jié)構(gòu)圖[/align]
二、MCGS 工程框架
本空調(diào)溫/濕度控制系統(tǒng)需要對各個控制室及風道的溫/濕度值進行監(jiān)控,因此工程需要有實時顯示和記錄各控制室溫/濕度值、修改房間溫/濕度SV 值、報警顯示、報警顯示瀏覽記錄等功能、工程框架如下:
用戶窗口:封面窗口、主控窗口、控制室窗口1~6、風道平面圖、狀態(tài)條、修改控制室1~6 SV值、修改SV 值消息窗口、風道電加熱段消息窗口、修改風道溫度表1~2 SV 值、修改風道濕度表1~2 SV 值、風道內(nèi)三級加熱報警窗口。
[align=center][IMG=用戶窗口]/uploadpic/tech/2007/7/2007073015595627257E.jpg[/IMG]
圖 2 用戶窗口[/align]
運行策略:啟動策略、退出策略、循環(huán)策略、卡車運動策略、控制柜燈閃爍策略、顯示控制室1~6策略、顯示時間策略、主控窗口中提示塊顯示策略。
主菜單:用戶登錄、封面窗口、打開主控窗口、打開各控制室、風道平面圖、修改SV 值、歷史記錄、通信錯誤記錄、溫/濕度異常記錄、退出系統(tǒng)
子菜單:第一~六控制室、修改一~六號房間、SV 值修改風道溫度、表1~2 SV 值、修改風道濕度表1~2 SV 值
[align=center][IMG=系統(tǒng)菜單]/uploadpic/tech/2007/7/2007073016061396309W.jpg[/IMG]
圖 3 系統(tǒng)菜單[/align]
三、主要數(shù)據(jù)對象
建立好一個空調(diào)溫/濕度控制系統(tǒng)的MCGS 工程后,實現(xiàn)上位機的主要任務(wù)就是建立組態(tài)工程與OPC設(shè)備的連接,實現(xiàn)上位機的主要任務(wù)就是建立組態(tài)工程與OPC設(shè)備的連接,并對采集到的數(shù)據(jù)進行處理和顯示。在這個工程的實時數(shù)據(jù)庫中,要進行顯示、操作的數(shù)據(jù)對象如表1 所示。由于風道的數(shù)據(jù)對象較多,為了統(tǒng)一管理,將風道當作兩個房間節(jié)點來處理。這樣,每個房間都只有1 個溫度值對象、1 個濕度之對象、1 個溫度SV 值對象和1 個濕度SV 值對象。
[align=center]表 1 系統(tǒng)主要數(shù)據(jù)對象
[IMG=系統(tǒng)主要數(shù)據(jù)對象]/uploadpic/tech/2007/7/20070730161302396331R.jpg[/IMG][/align]
為了使系統(tǒng)具備記錄數(shù)據(jù)及瀏覽歷史數(shù)據(jù)、錯誤數(shù)據(jù)和異常數(shù)據(jù)的能力,在實時數(shù)據(jù)庫中建立了save、ErrorSave 和exception 三個數(shù)據(jù)對象組。其中ErrorSave 和exception 的組對象成員有:RoomID1 、ErrorTemp、ErrorHum 、ErrorTempSV 和ErrorHumSV ,save 的組成員對象如表1 所示。在運行過程中,系統(tǒng)會定時保存save 組對象到數(shù)據(jù)庫。當通信產(chǎn)生錯誤和房間溫/濕度異常時,系統(tǒng)會將ErrorSave 和exception 保存到數(shù)據(jù)庫。
在此系統(tǒng)中的OPC 設(shè)備使用的是ZOPC_Server 服務(wù)器。ZOPC_Server 是一個OPC 服務(wù)器軟件本軟件,支持操作全系列的ZLGCAN 系列接口卡,只要在一臺PC 機上插上ZLGCAN 系列接口卡中的任何一種或幾種,再運行本服務(wù)器軟件,就可以使用任何一種支持OPC 協(xié)議的客戶端軟件(比如組態(tài)軟件:組態(tài)王KingView、昆侖通態(tài)MCGS 和Intouch 等)來連接到此服務(wù)器通過此服務(wù)器,來跟CAN-bus 網(wǎng)絡(luò)進行數(shù)據(jù)的傳輸。
本設(shè)計中,ZOPC_Server 在數(shù)值存儲模式下和字符串存儲模式下提供的數(shù)據(jù)項都不能直接連接到實時數(shù)據(jù)庫中的數(shù)據(jù)對象,因此必須編寫腳本程序?qū)?shù)據(jù)進行處理。關(guān)于數(shù)據(jù)項存儲模式,這里選用被推薦的字符串存儲模式;但是,使用數(shù)值存儲模式會更容易實現(xiàn)此系統(tǒng)。
在實時數(shù)據(jù)庫添加字符型數(shù)據(jù)對象In_CANData 和Out_CANData,字符數(shù)為30,將In_CANData 和Out_CANData 分別連接到OPC 設(shè)備的輸入通道和輸出通道,In_CANData 的讀寫屬性為只讀,Out_CANData的讀寫屬性為只寫。由于這兩個數(shù)據(jù)對象是字符型的,不便于進行數(shù)據(jù)處理,所以應(yīng)該先將它們轉(zhuǎn)換為數(shù)值型對象。在MCGS 腳本程序中,用戶不能定義子程序、子函數(shù)和變量,而數(shù)據(jù)對象可以看作是腳本程序中的全局變量,在所有的程序段共用。這給編寫較復雜的腳本程序帶來不便。要進行類似子程序和子函數(shù)的操作,只能用先將要處理的數(shù)據(jù)放入全局變量,然后調(diào)用策略行中的腳本進行處理,最后將返回的數(shù)據(jù)放入全局變量的方法進行處理。在實時數(shù)據(jù)庫加添以下數(shù)值型對象作為中間變量:
然后,在運行策略中新建一個名為StringToObject 的用戶策略,新增一策略行并添加以下腳本程序,用于將In_CANData 轉(zhuǎn)換到數(shù)值型對象:
In_Flag = !Hex2I(!mid(In_CANData, 1, 2))
In_Extern = !Hex2I(!mid(In_CANData, 3, 1))
In_Remote = !Hex2I(!mid(In_CANData, 4, 1))
In_ID = !Hex2I(!mid(In_CANData, 5, 8))
In_DataLen = !Hex2I(!mid(In_CANData, 13 , 2))
In_Data0 = !Hex2I(!mid(In_CANData, 15, 2))
In_Data1 = !Hex2I(!mid(In_CANData, 17, 2))
In_Data2 = !Hex2I(!mid(In_CANData, 19, 2))
In_Data3 = !Hex2I(!mid(In_CANData, 21, 2))
In_Data4 = !Hex2I(!mid(In_CANData, 23, 2))
In_Data5 = !Hex2I(!mid(In_CANData, 25, 2))
In_Data6 = !Hex2I(!mid(In_CANData, 27, 2))
In_Data7 = !Hex2I(!mid(In_CANData, 29, 2))
同樣,在運行策略中新建一個名為ObjectToString 的用戶策略,新增一策略行并添加下面的腳本程序,用于將數(shù)值型對象轉(zhuǎn)換到Out_CANData 。在下面的程序中,Out_SendID 進行自加是因為ZOPC_Server 要判斷寫入的Out_SendID 和上一次寫入的Out_SendID 是否相同,如果不同才將報文發(fā)出。
‘ 轉(zhuǎn)換 Out_SendID 到字符型
if Out_SendID <= 255 then
Out_SendID = Out_SendID + 1
else
Out_SendID = 0
endif
Out_CANData1 = !I2Hex(Out_SendID)
if !Len(Out_CANData1) <> 2 then Out_CANData1 = "0" + Out_CANData1
Out_CANData2 = Out_CANData1
‘ 轉(zhuǎn)換 Out_Extern 和 Out_Remote 到字符型
Out_CANData1 = !I2Hex(Out_Extern) + !I2Hex(Out_Remote)
Out_CANData2 = Out_CANData2 + Out_CANData1
‘ 轉(zhuǎn)換 Out_ID 到字符型
Out_CANData1 = !I2Hex(Out_ID)
Lenght = !Len(Out_CANData1)
while Lenght < 8
Out_CANData1 = "0" + Out_CANData1
Lenght = !Len(Out_CANData1)
endwhile
Out_CANData2 = Out_CANData2 + Out_CANData1
‘ 轉(zhuǎn)換 Out_DataLen 到字符型
Out_CANData1 = !I2Hex(Out_DataLen)
if !Len(Out_CANData1) <> 2 then Out_CANData1 = "0" + Out_CANData1
Out_CANData2 = Out_CANData2 + Out_CANData1
‘ 轉(zhuǎn)換 Out_Data0 7 到字符型
Out_CANData1 = !I2Hex(Out_Data0)
if !Len(Out_CANData1) <> 2 then Out_CANData1 = "0" + Out_CANData1
Out_CANData2 = Out_CANData2 + Out_CANData1
Out_CANData1 = !I2Hex(Out_Data1)
if !Len(Out_CANData1) <> 2 then Out_CANData1 = "0" + Out_CANData1
Out_CANData2 = Out_CANData2 + Out_CANData1
Out_CANData1 = !I2Hex(Out_Data2)
if !Len(Out_CANData1) <> 2 then Out_CANData1 = "0" + Out_CANData1
Out_CANData2 = Out_CANData2 + Out_CANData1
Out_CANData1 = !I2Hex(Out_Data3)
if !Len(Out_CANData1) <> 2 then Out_CANData1 = "0" + Out_CANData1
Out_CANData2 = Out_CANData2 + Out_CANData1
Out_CANData1 = !I2Hex(Out_Data4)
if !Len(Out_CANData1) <> 2 then Out_CANData1 = "0" + Out_CANData1
Out_CANData2 = Out_CANData2 + Out_CANData1
Out_CANData1 = !I2Hex(Out_Data5)
if !Len(Out_CANData1) <> 2 then Out_CANData1 = "0" + Out_CANData1
Out_CANData2 = Out_CANData2 + Out_CANData1
Out_CANData1 = !I2Hex(Out_Data6)
if !Len(Out_CANData1) <> 2 then Out_CANData1 = "0" + Out_CANData1
Out_CANData2 = Out_CANData2 + Out_CANData1
Out_CANData1 = !I2Hex(Out_Data7)
if !Len(Out_CANData1) <> 2 then Out_CANData1 = "0" + Out_CANData1
Out_CANData2 = Out_CANData2 + Out_CANData1
這樣,以后要將In_CANData 的數(shù)據(jù)提取到In_*變量中,只需在腳本中按!setstgy(StringToObject)就可以了。而要將Out_*數(shù)據(jù)合并到Out_CANData, 可先調(diào)用!setstgy(ObjectToString),然后再把Out_CANData2的值賦給Out_CANData。
四、協(xié)議及報文格式
因為MCGS 不便于編寫復雜的腳本程序,所以傳輸協(xié)議的設(shè)計以簡單為原則。本系統(tǒng)使用HiLon 協(xié)議A 。HiLon 協(xié)議A 是一個通用的協(xié)議,基于非對稱型主從式網(wǎng)絡(luò)結(jié)構(gòu),支持廣播和點對點傳送命令數(shù)據(jù),命令數(shù)據(jù)包可長達256 字節(jié),非常適合用作本系統(tǒng)的通信協(xié)議HiLon 協(xié)議以CAN2.0A 幀結(jié)構(gòu)為基礎(chǔ)。下圖是幀報文格式,一個CAN2.0A 標準幀由11 位ID 、1 位RTR 、4 位DLC 、數(shù)據(jù)區(qū)(最多8 個字節(jié))組成。
[align=center][IMG=HiLon A 報文格式]/uploadpic/tech/2007/7/2007073017043663226O.jpg[/IMG]
圖 4 HiLon A 報文格式[/align]
DIR :方向位。方向位決定一半的優(yōu)先級而剩余的優(yōu)先級,由節(jié)點地址決定低地址優(yōu)先級高。當方向位為“1” 時,地址域是源節(jié)點地址(從節(jié)點到主節(jié)點),優(yōu)先級由地址決定;當方向位為“0” 時,地址域是目標節(jié)點地址(主節(jié)點到從節(jié)點),優(yōu)先級由地址決定。從節(jié)點也可使用地址濾波技術(shù)從而減少需處理的網(wǎng)絡(luò)信息量,因而能有效節(jié)省CAN 節(jié)點控制器資源,提高控制器效率。
Address :目標地址,表示節(jié)點地址,范圍只能設(shè)定為0~125
TYPE :幀類型。見下表中的幀類型說明。
[align=center]表 2 HiLon 幀類型
[IMG=HiLon 幀類型]/uploadpic/tech/2007/7/200707301712087027014.jpg[/IMG]
[/align]
DLC: 每幀字節(jié)數(shù)(1~8)
Index :索引字節(jié)。對于單幀數(shù)據(jù),該字節(jié)表示傳輸數(shù)據(jù)的第一個字節(jié);對于多幀數(shù)據(jù),此字節(jié)表示索引字節(jié),即此幀數(shù)據(jù)在數(shù)據(jù)包中的位置。
Data :數(shù)據(jù)
在本系統(tǒng)中,數(shù)據(jù)中心要對各個房間的溫/濕度進行監(jiān)控并修各個房間的溫/濕度SV 值,因此給各個控制室分配唯一的標志符;在下位機向上位機發(fā)送的數(shù)據(jù)報文中攜帶的數(shù)據(jù)是房間的溫/濕度值;上位機向下位機發(fā)送的命令報文攜帶命令號及控制室的溫/濕度SV 值。本系統(tǒng)的傳輸數(shù)據(jù)量較小,且MCGS 的采樣周期本系統(tǒng)取5ms 相對下位機來說較長,因此,本系統(tǒng)選擇使用單幀(點對點)類型幀。利用HiLon報文的特點,將7 位Address 分配給房間ID,每一個房間ID 對應(yīng)一個Address ,地址0 保留。當數(shù)據(jù)方向是從節(jié)點到主節(jié)點時,8 字節(jié)數(shù)據(jù)的前4 字節(jié)用于傳遞房間溫度,后4 字節(jié)用于傳遞房間濕度,當數(shù)據(jù)方向是主節(jié)點到從節(jié)點時,8字節(jié)數(shù)據(jù)的前4 字節(jié)作為命令I(lǐng)D,后4 字節(jié)用于傳遞命令參數(shù)(房間溫/濕度SV值)。報文幀的格式如圖1 所示。
[align=center][IMG=報文幀格式]/uploadpic/tech/2007/7/2007073017221423544B.jpg[/IMG]
圖 5 報文幀格式[/align]
對主節(jié)點到從節(jié)點的命令I(lǐng)D 的定義如下:
[align=center]表 3 控制命令類型及其參數(shù)
[IMG=控制命令類型及其參數(shù)]/uploadpic/tech/2007/7/2007073017273712141B.jpg[/IMG]
[/align]
本系統(tǒng)要監(jiān)控的數(shù)據(jù)是各房間的溫度和濕度及它們的SV 值。要將這些數(shù)據(jù)在總線上傳輸,必須將它們裝入報文幀。為了使傳輸?shù)臄?shù)據(jù)只占用較小的空間而達到較高的精確度,在報文中每一種數(shù)值都分配了4 字節(jié)的空間,數(shù)據(jù)按IEEE-754 標準的float 數(shù)據(jù)類型的格式存儲。這樣,在下位機進行編程就比較方便。但是,上位機的處理程序是用類似VB 腳本的語言寫的,數(shù)據(jù)對象的類型只有數(shù)值型、開關(guān)型和字符型三種,不能直接使用接收到的數(shù)據(jù)。因此,要對接收到的數(shù)據(jù)進行轉(zhuǎn)換。
按IEEE-754 標準,一個浮點數(shù)用兩個部分表示:尾數(shù)和2 的冪。例如:
尾數(shù)代表浮點上的數(shù)據(jù)二進制數(shù)。
二的冪代表指數(shù)。指數(shù)的保存形式是一個0 到255 的8 位值。指數(shù)的實際值是保存值0 到255 減去127,一個范圍在127 到-128 之間的值。
尾數(shù)是一個24 位值(代表大約7 個十進制數(shù)),最高位(MSB) 通常是1, 因此,不保存。一個符號位表示浮點數(shù)是正或負。在尾數(shù)的左邊有一個省略的二進制點和1。 這個數(shù)在浮點數(shù)的保存中經(jīng)常省略。
浮點數(shù)保存的字節(jié)格式如下:
[align=center][IMG=IEEE-754 標準 float 存儲格式]/uploadpic/tech/2007/7/20070731104600663014.jpg[/IMG]
圖 6 IEEE-754 標準 float 存儲格式[/align]
這里:
S 代表符號位,1 是負,0 是正。
E 冪,偏移127。
M 24 位的尾數(shù)(保存在23 位中)。
零是一個特定值,表示冪是0, 尾數(shù)是0。
在運行策略中新建一個名為SplitFloat 的用戶策略,新增一策略行并添加以下腳本程序,用于將數(shù)值型對象float 轉(zhuǎn)換到4 字節(jié)存儲單元Byte0 Byte3:
‘ 計算浮點數(shù)的冪(二進制數(shù)小數(shù)點的位置)
exponent = 0
float1 = !abs(float)
while float1<>0
float1 = !BitRShift(float1, 1)
exponent = exponent + 1
endwhile
exponent = exponent - 1
‘ 計算浮點數(shù)的底數(shù)
mantissa = !abs(float) * (!BitLShift(2, 23 - (exponent + 1))) - 8388608
exponent = exponent + 127
Byte0 = !BitRShift(exponent, 1)
if room1tempsv < 0 then
Byte0 = !BitOr(Byte0, 128)
endif
Byte1 = !BitAnd(!BitOr(!BitRShift(mantissa, 16), !BitLShift(exponent, 7)), 255)
Byte2 = !BitAnd(!BitRShift(mantissa, 8), 255)
Byte3 = !BitAnd(mantissa, 255)
在運行策略中新建一個名為UniteFloat 的用戶策略,新增一策略行并添加以下腳本程序,用于將4 字節(jié)存儲單元Byte0 Byte3 轉(zhuǎn)換到數(shù)值型對象float:
mantissa = (!BitAnd(Byte0, 128) + !BitAnd(Byte1, 127)) * 65536 + _
(Byte2 * 256) + Byte3 + 8388608
exponent = !BitOr(!BitLShift(Byte0, 1), !BitRShift(Byte1, 7)) - 127
float = mantissa / (!BitLShift(2, 23 - (exponent + 1)))
五、實現(xiàn)
系統(tǒng)的控制中心采用定時查詢的方法,每2 秒鐘對各個房間的溫度值和濕度值進行一次查詢。查詢時,組態(tài)軟件先向?qū)崟r數(shù)據(jù)庫中的數(shù)據(jù)對象Out_CANData 寫入查詢房間溫/濕度命令的報文。命令報文的房間ID 對應(yīng)要查詢的房間號,命令I(lǐng)D 為0x00000000,無命令參數(shù)。然后經(jīng)過ZOPC_Server 將報文發(fā)到CAN總線上。在發(fā)送查詢命令后控制中心將等待一段時間(這一段時間要大于MCGS 的最小采集周期),然后再從實時數(shù)據(jù)庫中的數(shù)據(jù)對象In_CANData 讀取數(shù)據(jù)并進行處理和顯示。
如果控制中心要修改房間的SV 值,首先發(fā)出查詢房間溫/濕度SV 值的命令,在收到房間溫/濕度SV值后,在“修改控制室SV 值”窗口中顯示SV 值(或在“修改風道溫度/濕度表SV 值”窗口中顯示),然后發(fā)出帶有參數(shù)的修改房間溫度SV 值命令報文,參數(shù)的內(nèi)容就是要修改的SV 值。
下位機的驗收碼設(shè)置成ID10 為0,ID9~ID3 為房間ID,后3 位屏蔽。當總線上有發(fā)給該房間的報文時,并根據(jù)命令進行相應(yīng)的操作。如果收到的是查詢命令,下位機立即將房間的溫/濕度數(shù)據(jù)發(fā)送到CAN 總線上。數(shù)據(jù)報文的ID 也是該房間的ID,以表示報文中的數(shù)據(jù)是該控制室的。如果是修改房間溫/濕度SV 值命令,下位機就從命令參數(shù)取出SV 值并替換舊的SV 值。
上位機控制流程編寫的具體步驟:
1. 在運行策略中新建一個名為“GetRoomTHV ”的用戶策略,并添加3 個腳本程序,1 個退出策略行,如圖:
[align=center][IMG=GetRoomTHV 策略]/uploadpic/tech/2007/7/2007073111012831562I.jpg[/IMG]
圖 7 GetRoomTHV 策略[/align]
其中,“查詢房間溫/濕度值”腳本如下:
‘ 發(fā)送控制室溫/濕度查詢命令
Out_Extern = 0
Out_Remote = 0
Out_ID = !BitLShift(RoomID, 3) + 0 ‘ 控制室ID + 單幀(點對點)
Out_DataLen = 8
Out_Data0 = 0
Out_Data1 = 0
Out_Data2 = 0
Out_Data3 = 0
Out_Data4 = 0
Out_Data5 = 0
Out_Data6 = 0
Out_Data7 = 0
!setstgy(ObjectToString)
‘ 發(fā)出命令
Out_CANData = Out_CANData2
‘ 等待命令發(fā)出
!TimerReset(1, 0)
!TimerRun(1)
!TimerWaitFor(1, Delay)
!TimerStop(1)
‘ 接收控制室溫/濕度
!setstgy(StringToObject)
roomtemp = roomhum = 0
if (In_Extern <> 0) or (In_Remote <> 0) _
or ((!BitAnd(In_ID, 1024)<>1024) _
and (!BitAnd(In_ID, 7)<>0)) then
In_ID = 0
exit
endif
“計算控制室的溫度”的執(zhí)行條件是!BitAnd(!BitRShift(In_ID, 3), 127) = RoomID 表達式的值為非0,腳本程序如下:
Byte0 = In_Data0
Byte1 = In_Data1
Byte2 = In_Data2
Byte3 = In_Data3
!setstgy(UniteFloat)
roomtemp = float
“計算控制室的濕度”的執(zhí)行條件是!BitAnd(!BitRShift(In_ID, 3), 127) = RoomID 表達式的值為非0,腳本程序如下:
Byte0 = In_Data4
Byte1 = In_Data5
Byte2 = In_Data6
Byte3 = In_Data7
!setstgy(UniteFloat)
roomhum = float
2. 在運行策略中新建名為“查詢各控制室溫/濕度”的循環(huán)策略,循環(huán)時間為2000ms。 添加如下圖所示的策略行。
[align=center][IMG=查詢各控制室溫/濕度策略]/uploadpic/tech/2007/7/2007073111083487072R.jpg[/IMG]
圖 8 查詢各控制室溫/濕度策略[/align]
“初始化”的腳本程序如下:
RoomID = 1
“查詢1 號控制室溫/濕度”的腳本程序如下:
RoomID1 = RoomID
RoomID = RoomID + 1
if (roomtemp = 0) or (roomhum = 0) then
room1st = 1
ErrorTemp = roomtemp
ErrorHum = roomhum
!SaveData(ErrorSave) ‘ 記錄通信錯誤
exit
endif
room1temp = roomtemp
room1hum = roomhum
if room1temp > room1tempsv then
room1st = 1
ErrorTemp = room1temp
ErrorHum = room1hum
!SaveData(exception) ‘ 記錄溫度異常
exit
else
room1st = 0
endif
其它策略行腳本程序與上類似。
所有的“策略調(diào)用”均調(diào)用GetRoomTHV 策略。
3. 在運行策略中新建一個名為“GetRoomSV” 的用戶策略,其他步驟同1。
[align=center][IMG=GetRoomSV 策略]/uploadpic/tech/2007/7/20070731111436892566.jpg[/IMG]
圖 9 GetRoomSV 策略[/align]
“查詢房間溫/濕度SV 值”腳本如下:
‘ 發(fā)送控制室溫/濕度SV 查詢命令
Out_Extern = 0
Out_Remote = 0
Out_ID = !BitLShift(RoomID, 3) + 0 ‘ 控制室ID + 單幀(點對點)
Out_DataLen = 8
Out_Data0 = 0
Out_Data1 = 0
Out_Data2 = 0
Out_Data3 = 1
Out_Data4 = 0
Out_Data5 = 0
Out_Data6 = 0
Out_Data7 = 0
!setstgy(ObjectToString)
‘ 發(fā)出命令
Out_CANData = Out_CANData2
‘ 等待命令發(fā)出
!TimerReset(1, 0)
!TimerRun(1)
!TimerWaitFor(1, Delay)
!TimerStop(1)
‘ 接收控制室溫/濕度
!setstgy(StringToObject)
if (In_Extern <> 0) or (In_Remote <> 0) _
or ((!BitAnd(In_ID, 1024)<>1024) _
and (!BitAnd(In_ID, 7)<>0)) then
In_ID = 0
exit
endif
roomtemp = roomhum = 0
“計算控制室的溫度SV” 的執(zhí)行條件是!BitAnd(!BitRShift(In_ID, 3), 127) = RoomID 表達式的值為非0, 腳本程序如下:
Byte0 = In_Data0
Byte1 = In_Data1
Byte2 = In_Data2
Byte3 = In_Data3
!setstgy(UniteFloat)
roomtempsv = float
“計算控制室的濕度SV” 的執(zhí)行條件是!BitAnd(!BitRShift(In_ID, 3), 127) = RoomID 表達式的值為非0, 腳本程序如下:
Byte0 = In_Data4
Byte1 = In_Data5
Byte2 = In_Data6
Byte3 = In_Data7
!setstgy(UniteFloat)
roomhumsv = float
4. 在運行策略中新建名為“查詢房間1SV 值”的用戶策略,添加如下圖所示的3 個策略行。
[align=center][IMG=查詢房間1SV 值策略]/uploadpic/tech/2007/7/2007073111194331320L.jpg[/IMG]
圖 10 查詢房間1SV 值策略[/align]
“before” 策略行腳本程序如下:
!EnableStgy(查詢各控制室溫/濕度策略, 0)
RoomID = 1
“策略調(diào)用”調(diào)用GetRoomSV 策略。
“after” 策略行腳本程序如下:
room1tempsv = roomtempsv
!EnableStgy(查詢各控制室溫/濕度策略, 1)
5. 重復步驟4。 添加“查詢房間2~6 SV 值”和“查詢風道溫/濕度表1~2 sv 值”策略,并由菜單“修改1~6 號房間SV 值”調(diào)用對應(yīng)的策略。
6. 雙擊主控窗口中名為“修改一號房間SV 值”的菜單項,在菜單屬性設(shè)置對話框的“菜單操作”頁中添加執(zhí)行運行策略塊“查詢房間1 SV 值”。
7. 重復步驟6, 添加其它房間的運行策略。
8. 在運行策略中建立一個名為“SetRoomTSV” 的用戶策略,添加以下腳本程序:
float = roomtempsv
!setstgy(SplitFloat)
‘ 發(fā)送控制室溫/濕度SV 設(shè)置命令
Out_Extern = 0
Out_Remote = 0
Out_ID = !BitLShift(RoomID, 3) + 0 ‘ 控制室ID + 單幀(點對點)
Out_DataLen = 8
Out_Data0 = 0
Out_Data1 = 0
Out_Data2 = 0
Out_Data3 = 2
Out_Data4 = Byte0
Out_Data5 = Byte1
Out_Data6 = Byte2
Out_Data7 = Byte3
!setstgy(ObjectToString)
‘ 發(fā)出命令
Out_CANData = Out_CANData2
‘ 等待命令發(fā)出
!TimerReset(1, 0)
!TimerRun(1)
!TimerWaitFor(1, Delay)
!TimerStop(1)
9. 在運行策略中建立一個名為“調(diào)整房間1SV 值”的用戶策略,并添加以下程序:
!EnableStgy(查詢各控制室溫/濕度策略, 0)
RoomID = 1
roomtempsv = room1tempsv
float = roomtempsv
!setstgy(SetRoomTSV)
!EnableStgy(查詢各控制室溫/濕度策略, 1)
10. 重復步驟9, 添加其它5 個控制室及風道的腳本程序。
11. 給“修改控制室1SV 值”窗口的“確認”按鈕添加如下腳本:
if room1tempsv1<-10 or room1tempsv1>100 then
!setwindow(修改SV 值消息窗口,1)
else
room1tempsv=room1tempsv1
!setwindow(修改控制室1SV 值,3)
room1tempsv1=0
!setstgy(調(diào)整房間1SV 值)
endif
12. 重復步驟11, 添加其它窗口的腳本。
六 模擬控制室
本系統(tǒng)可用DP-668 實驗儀模擬產(chǎn)生控制室數(shù)據(jù)。DP-668 實驗儀具有模擬控制室溫/濕度變化、自修改溫/濕度SV 值以及報警等功能。其模擬溫/濕度變化算法如下:
extern unsigned char code RoomID = 1; /* 房間 ID */
extern float RoomTemp = 0; /* 房間溫度 */
extern float RoomHumi = 0; /* 房間濕度 */
...
float code RoomTempTab[] = {
19.0, 19.2, 19.4, 19.6, 19.8,
20.0, 20.2, 20.4, 20.6, 20.8,
21.0, 21.2, 21.4, 21.6, 21.8,
21.8, 21.6, 21.4, 21.2, 21.0,
20.8, 20.6, 20.4, 20.2, 20.0,
19.8, 19.6, 19.4, 19.2, 19.0
};
float code RoomHumiTab[] = {
55.0, 55.5, 56.0, 56.5,
57.0, 57.5, 58.0, 58.5,
59.0, 59.5, 60.0, 60.5,
61.0, 61.5, 62.0, 62.5,
63.0, 63.5, 64.0, 64.5
};
void main(void)
{
unsigned int idata i, j;
...
while (1)
{
/* 模擬溫/濕度變化 */
RoomTemp = RoomTempTab[j % (sizeof (RoomTempTab)/sizeof(RoomTempTab[0]))];
RoomHumi = RoomHumiTab[j++ % (sizeof (RoomHumiTab)/sizeof(RoomHumiTab[0]))];
...
}
}
本系統(tǒng)也可用任一款ZLGCAN 接口卡和PC 組成的系統(tǒng)來模擬產(chǎn)生控制室數(shù)據(jù),基于ZLGCAN 通用函數(shù)接口編程,同樣具有模擬控制室溫/濕度變化、自修改溫/濕度SV 值以及報警等功能。其模擬溫/濕度變化算法(VC 示范)如下:
float m_dwTemp[8];// 房間1 6 及風道1 2 的溫度
float m_dwHumi[8];// 房間1 6 及風道1 2 的濕度
...
static double i;
i += 0.1;
m_dwTemp[0] = (float)sin(i + 0.0) + 20;
m_dwTemp[1] = (float)sin(i + 0.1) + 20;
m_dwTemp[2] = (float)sin(i + 0.2) + 20;
m_dwTemp[3] = (float)sin(i + 0.3) + 20;
m_dwTemp[4] = (float)sin(i + 0.4) + 20;
m_dwTemp[5] = (float)sin(i + 0.5) + 20;
m_dwTemp[6] = (float)sin(i + 0.6) + 20;
m_dwTemp[7] = (float)sin(i + 0.7) + 20;
m_dwHumi[0] = (float)cos(i + 0.0) + 60;
m_dwHumi[1] = (float)cos(i + 0.1) + 60;
m_dwHumi[2] = (float)cos(i + 0.2) + 60;
m_dwHumi[3] = (float)cos(i + 0.3) + 60;
m_dwHumi[4] = (float)cos(i + 0.4) + 60;
m_dwHumi[5] = (float)cos(i + 0.5) + 60;
m_dwHumi[6] = (float)cos(i + 0.6) + 60;
m_dwHumi[7] = (float)cos(i + 0.7) + 60;
...