
【摘要】VB是一種具有很好的圖形用戶(hù)接口(Graphic user interface,簡(jiǎn)寫(xiě)為GUI)的程序設(shè)計(jì)語(yǔ)言, 同時(shí)又是一種完全支持結(jié)構(gòu)化程序設(shè)計(jì)的面向?qū)ο蟮某绦蛟O(shè)計(jì)語(yǔ)言。其特點(diǎn)不僅語(yǔ)法口語(yǔ)化,淺顯易懂,易于掌握,而且編程界面友好,操作簡(jiǎn)便,模塊化結(jié)構(gòu)化程度高。尤其其功能強(qiáng)大,編程面廣。本文根據(jù)作者長(zhǎng)期使用VB進(jìn)行工業(yè)控制的編程經(jīng)驗(yàn),并結(jié)合熱力發(fā)電廠化學(xué)水車(chē)間的運(yùn)作過(guò)程,介紹如何用VB來(lái)編程實(shí)現(xiàn)計(jì)算機(jī)與下位機(jī)之間的通訊。
【關(guān)鍵詞】下位機(jī)、ADAM模塊、模擬量、開(kāi)關(guān)量。
中圖分類(lèi)號(hào):G201
一、工作原理
熱力發(fā)電廠為確保發(fā)電機(jī)組運(yùn)轉(zhuǎn)正常,化學(xué)水車(chē)間必須24小時(shí)對(duì)機(jī)組的化學(xué)水性質(zhì)進(jìn)行監(jiān)視測(cè)量。需要測(cè)量的數(shù)據(jù)項(xiàng)很多,根據(jù)熱電廠的規(guī)模和設(shè)備情況的不同而不同。比如有:凝結(jié)水電導(dǎo)值,凝結(jié)水溶氧值、疏水電導(dǎo)值,除氧水溶氧值、給水電導(dǎo)值、給水PH值,爐水PH值,飽和汽電導(dǎo)值,過(guò)熱汽電導(dǎo)值等,這些值測(cè)出來(lái)的都是一些離散性的數(shù)值,統(tǒng)稱(chēng)模擬量。而象“凝結(jié)水超溫閥”、“過(guò)熱汽超溫閥”、“冷卻水壓力低”等這種狀態(tài)量數(shù)據(jù)測(cè)出來(lái)只有兩種值:“正常”用“-1”表示, “不正常”用“0 ”表示,這些數(shù)據(jù)統(tǒng)稱(chēng)開(kāi)關(guān)量。這些模擬量和開(kāi)關(guān)量首先經(jīng)過(guò)一種智能儀表轉(zhuǎn)換成電信號(hào).一般,模擬量為電流信號(hào),開(kāi)關(guān)量為電壓信號(hào)。這些信號(hào)再由模數(shù)轉(zhuǎn)換器轉(zhuǎn)換成數(shù)字信號(hào)送到計(jì)算機(jī)端口(如com1口)。用戶(hù)編制的監(jiān)控程序其功能便是要能準(zhǔn)確及時(shí)地從計(jì)算機(jī)端口捕獲這些數(shù)據(jù),再按用戶(hù)的量程要求轉(zhuǎn)換成數(shù)值進(jìn)行顯示并生成數(shù)據(jù)文件進(jìn)行報(bào)表管理。
二、模數(shù)轉(zhuǎn)換器
在整個(gè)控制流程中,我們通常把計(jì)算機(jī)稱(chēng)為上位機(jī),模數(shù)轉(zhuǎn)換器稱(chēng)為下位機(jī)。ADAM系列模塊在計(jì)算機(jī)工業(yè)控制應(yīng)用中是一種常用的A/D轉(zhuǎn)換器。它具有性能穩(wěn)定、精確度高、量程寬等特性。其中ADAM 4520 用于地址管理和通訊。ADAM 4017用于連接模擬量,ADAM 4053用于連接開(kāi)關(guān)量,其連接圖如下,Vc一般為+12伏電壓。
一般來(lái)說(shuō)明,4520只須一個(gè),而4017和4053的個(gè)數(shù)要須根據(jù)具體模擬量和開(kāi)關(guān)量的個(gè)數(shù)來(lái)確定。一個(gè)4053可連接16路開(kāi)關(guān)量,一個(gè)4017可連接8路模擬量。 使用前還必須用ADAM專(zhuān)用測(cè)試程序設(shè)置模塊的量程檔,并對(duì)多個(gè)模塊進(jìn)行地址分配。如若要用到2個(gè)4017,則將其中一個(gè)地址設(shè)定為01H,另一個(gè)地址設(shè)置為02H。用VB編程時(shí),程序中的接口地址必須與這個(gè)設(shè)定一致,否則將導(dǎo)致捕獲的數(shù)據(jù)張冠李戴,不合實(shí)際而失去意義。模塊的地址和量程設(shè)定好后,由ADAM測(cè)試程寫(xiě)入模塊中的EPROM中.
三、程序?qū)嵗?/p>
窗體中要建立定時(shí)器對(duì)象(名為timer1)和通訊對(duì)象(名為comm1)。假設(shè)目前有10個(gè)模擬量,10個(gè)開(kāi)關(guān)量,有一個(gè)機(jī)組。下位機(jī)有:一個(gè)4520,兩個(gè)4017,地址分別為01H和02H,每個(gè)4017只用到5路端口; 一個(gè)開(kāi)關(guān)量,地址為03H。并假設(shè)ADAM4017用0--20毫安檔,模量實(shí)際電流信號(hào)的變化范圍是4--20毫安,先定義如下變量:
CONST mnlnum=10 '模擬量個(gè)數(shù)
const kglnum=10 '開(kāi)關(guān)量個(gè)數(shù)
CONST jznum=1 '機(jī)組個(gè)數(shù)
Dim bi(1 To 8) As Integer '開(kāi)關(guān)量轉(zhuǎn)換后的值
Dim aM4000(1 To mnlnum) as String '用于存放從端口捕獲到的字串
Dim currkgl(1 To kglnum, 1 To jznum) As Integer '最后得到的開(kāi)關(guān)量的值
Dim currmnl(1 To mnlnum, 1 To jznum) As Integer '最后得到的模擬量的值
Dim lcmax(1 to mnlnum,1 to jznum) '用戶(hù)最大量程
Dim lcmin(1 to mnlnum,1 to jznum) '用戶(hù)最小量程
編制時(shí)鐘事件,以便程序定時(shí)去端口采集數(shù)據(jù)。定時(shí)器對(duì)象Timer1的interval值可設(shè)置為60000,目的是讓程序每分鐘采集一次數(shù)據(jù)。
Sub Timer1_Timer ()
Dummy = DoEvents() '響應(yīng)Windows的其它任務(wù)
getmnl '捕獲模擬量的值
mnlzh '模擬量根據(jù)量程轉(zhuǎn)換
Dummy = DoEvents()
kgin '開(kāi)關(guān)量轉(zhuǎn)換
Dummy = DoEvents()
End Sub
Sub getmnl () 'ADAM 通訊
On Error Resume Next
Comm1.PortOpen = True
For i = 1 To 5 '01H只用5路通道
Select Case i
Case 1
aab$ = \"#010\" '通道的具體地址
Case 2
aab$ = \"#011\"
Case 3
aab$ = \"#012\"
Case 4
aab$ = \"#013\"
Case 5
aab$ = \"#014\"
End Select
ccb$ = adam_mnli(aab$)
If ccb$ <> \"fail\" Then aM4000(i) = ccb$
Dummy = DoEvents()
Next i
For j = 1 To 5 '02H只用5路通道
Select Case j
Case 1
aab$ = \"#020\"
Case 2
aab$ = \"#021\"
Case 3
aab$ = \"#022\"
Case 4
aab$ = \"#023\"
Case 5
aab$ = \"#024\"
End Select
ccb$ = adam_mnli(aab$)
If ccb$ <> \"fail\" Then
aM4000(j + 5) = ccb$
End If
Dummy = DoEvents()
Next j
Comm1.PortOpen = False
End Sub
Function adam_mnli(mnlo As String) As String
'模擬量輸入4017 address 01,02H
On Error Resume Next
Comm1.Output = mnlo Chr$(13)
rx$ = \"\"
flag = 0
Do
Dummy = DoEvents()
flag = flag + 1
Loop Until Comm1.InBufferCount > 1 Or flag > 600
If flag > 600 Then
adam_mnli = \"fail\"
Exit Function
Else
rx$ = Comm1.Input '捕獲到的字串放rx$變量中
End If
If Mid$(rx$, Len(rx$), Len(rx$)) = Chr$(13) Then
adam_mnli=Mid$(rx$, 3, 6) '截取有效部分賦給函數(shù)
End If
End Function
Sub mnlzh () '下位機(jī)組模擬量轉(zhuǎn)換
ReDim pmnl(1 To mnlnum, 1 To jznum) As Single
For i = 1 To mnlnum
pmnl(i, 1) = (Val(aM4000(i)) - 4) / (20# - 4) '根據(jù)毫安檔轉(zhuǎn)換
currmnl(i,1)=pmnl(i,1)*(lcmax(i,1)-lcmin(i, 1) )+lcmin(i,1)
'根據(jù)最大和最小量程轉(zhuǎn)換成顯示需要的值
Next i
End Sub
Sub kgin () '4053 地址03H
h_kgl1$ = adam_kglin(\"$03\")
ssY% = Val(\"H\" Mid$(h_kgl1$, 3, 2)) '低8路開(kāi)關(guān)
kglzh(ssY%) '開(kāi)關(guān)量轉(zhuǎn)換
currkgl(1, 1) = bi(1)
currkgl(2, 1) = bi(2)
currkgl(3, 1) = bi(3)
currkgl(4, 1) = bi(4)
currkgl(5, 1) = bi(5)
currkgl(6, 1) = bi(6)
currkgl(7, 1) = bi(7)
currkgl(8, 1) = bi(8)
ssY% = Val(\"H\" Mid$(h_kgl1$, 1, 2))
kglzh(ssY%)
currkgl(9, 1) = bi(1)
currkgl(10, 1) = bi(2)
End Sub
Function adam_kglin (kin As String) As String
'ADAM 開(kāi)關(guān)量輸入變頻器 4053,捕獲開(kāi)關(guān)量數(shù)據(jù)
On Error Resume Next
Comm1.PortOpen = True
Comm1.Output = kin Chr$(13)
flag = 0
Do
Dummy = DoEvents()
flag = flag + 1
Loop Until Comm1.InBufferCount > 1 Or flag > 1300
If flag > 1300 Then
adam_kglin = \"fail\"
Comm1.PortOpen = False: Exit Function
Else
rx$ = Comm1.Input
End If
If Mid$(rx$, Len(rx$), Len(rx$)) = Chr$(13) Then
'取前四位
adam_kglin = Mid$(rx$, 2, 4)
'每個(gè)4053有16路開(kāi)關(guān)通道,因此函數(shù)值是個(gè)四位16進(jìn)制數(shù),16位二
'進(jìn)制數(shù),1表示正常,0表示故障
End If
Comm1.PortOpen = False
End Function
Sub kglzh (t As Integer) '開(kāi)關(guān)量轉(zhuǎn)換
For i = 1 To 8
dd = t Mod 2
If dd <> 0 Then
bi(i) = 1
Else
bi(i) = 0
End If
t = t \ 2
Next i
End Sub
以上程序從端口捕獲到的數(shù)據(jù)經(jīng)程序處理后得到的最終有效值存放在數(shù)組currmnl( )和currkgl( )中,在具體應(yīng)用中,用戶(hù)可以編制其它程序?qū)Ψ旁跀?shù)組currmnl( )和currkgl( )中數(shù)據(jù)進(jìn)行報(bào)表管理。