1、 软件设计课程设计报告课设名称 OPC客户端的编程一、课设目的:通过对课程设计的实际操作进一步了解OPC的各种概念,掌握OPC客户端的编写方法。并对微软的DCOM有一定的了解,要求通过合适的DCOM配置,使客户端能够读取网络上服务器中的数据。二、课设内容:1)利用VB语言编写出一个简单的OPC客户端程序,要求这个客户端能够读取服务器中的数据,并显示出来。2)配置DCOM,使客户端能够能过DCOM读取另一台服务器上的数据。三、课设步骤: (一)运行环境的设置本步骤的主要内容是设置用VB开发的应用程序计算机运行环境。主要是就OPC服务器和OPC客户应用程序分别在不同的计算机上运行的远程连接形式,说
2、明OPC运行环境的设置方法。OPC服务器和OPC客户应用程序在相同的计算机上运行的本地连接形式形态,几乎使用分布式COM的默认设置就可以运行,或者参考下面介绍的远程连接设置方法,将OPC服务器的设置和OPC客户应用程序的设置在同一台计算机上也可以解决问题。操作系统不同,DCOM的配置方法也稍有不同。下面介绍Windows 2000/NT DCOM 及其windows XP系统的环境配置的步骤: 1)Windows 2000/NT DCOM 设置 首先运行DCOMCNFG 进入DCOM 配置程序 设置默认属性为以下设置 设置默认安全机制 设置默认访问权限如下,即加入Everyone 允许访问设置
3、默认启动权限如下,即加入Everyone 允许调用 设置引用程序OpcEnum属性 安全性设置如下 身份标识设置如下然后设置OPC 服务器程序,实际应用过程中服务器的注册信息是不同的,本例的OPC 服务器为kingview.view,其设置与OpcEnum 相同。客户端设置默认安全设置,设置同服务器4、5、6 步骤。客户端登录的用户必须是服务器中合法的用户。例如在服务其中包括 aaaa 用户,客户端可以以aaaa 用户登录而且密码与服务器中aaaa 用户的密码相同就可以访问访问服务器了。如果经过以上 各步还有问题,那么让客户端和服务器以相同用户名和口令登录,一定可以正确连接.1) window
4、s XP系统设置首先需要关闭SP2的防火墙,具体可由开始控制面板安全中心windows防火墙关闭 接着,按以下步骤配置DCOM点击开始运行,再输入DCOMCNFG,如下图点确定,进入XP的DCOM配置界面:再依次选择组件服务计算机我的电脑属性进入我的电脑属性界面,之后选择COM安全页: 首先选择访问权限,编辑限制,从中加入everyone,并将本地连接与远程连接前的复选框都选上同样,再选择启动激活权限编辑限制,并接下图配置:然后点击确定,则XP的DCOM就已经配置完成。(二)VB编程及实现 (1)建立一个Visual Basic工程 1)启动Visual Basic,新建一个Visual Ba
5、sic工程。图1 Visual Basic 工程的建立 2)设置OPC包装DLL 因为在新建的Visual Basic工程OPC包装DLL还没有被注册,必须用下述方法对OPC包装DLL进行注册。设置方法: 1.从Visual Basic菜单里选择Project-References。 2.在Available References表示中,选择对应OPC包装DLL的文件名。这里我们选择OPC Automation 2.0。图2 引用的设置(2)建立一个OPC对象 在Visual Basic里,是以对象的单位对OPC服务器进行访问。OPC自动化接口是由以下四种对象所定义。 OPC服务器 OPC组(
6、OPC组集合) OPC标签(OPC标签集合) OPC浏览器 这里只说明OPC服务器,OPC组以及OPC标签对象的使用方法。具体的来说,先连接一个特定的OPC服务器,然后建立OPC组,最后添加OPC标签。1) 变量声明 参考图3-3所示的示范代码,先对OPC对象变量进行声明。变量的数据类型应该指定为对象型。这些对象变量最好在窗体代码的(General)部分声明。因为在(General)部分声明的变量,可以在窗体的任何方法的代码内引用。变量申明中定义整型数据n用于做出温度和液位变化曲线。表1 OPC对象变量的声明 Option Base 1 Option Explicit Dim WithEven
7、ts objServer As OPCServer Dim objGroups As OPCGroups Dim objTestGrp As OPCGroup Dim objItems As OPCItems Dim n As Integer 定义新的变量n,用于画出反应罐温度和液位变化曲线 Dim lServerHandles() As Long有关定义OPC对象的声明及其说明列于表3-1表2 OPC对象变量的声明变量名说明objServerOPCServer对象,用于连接OPC服务器。objGroupsOPCGroups对象,用于添加OPC组的OPC组集合objTestGrpOPCGrou
8、p对象,演示用的OPC组。objItemsOPCItems对象,用于添加OPC标签的OPC标签集合。lServerHandles()长整型的数组,用于保存OPC标签的服务器句柄。2) 连接OPC服务器和建立OPC组下面说明如何连接OPC服务器和建立OPC组。考虑到代码的可反复使用性,这里采用子程序进行编程。这里用“NEW”关键词生成OPC服务器的对象,然后调用OPC服务器对象的“Connect”方法,和OPC服务器连接。在连接远程服务器的时候,需要指定作为选用参数的远程计算机名(表3)表3 Connect子程序Sub Connect(strProgID As String, Optional
9、strNode As String) If objServer Is Nothing Then 建立一个OPC服务器对象 Set objServer = New OPCServer End If If objServer.ServerState = OPCDisconnected Then 连接OPC服务器 objServer.Connect strProgID, strNode End If If objGroups Is Nothing Then 建立一个OPC组集合 Set objGroups = objServer.OPCGroups End If If objTestGrp Is N
10、othing Then 添加一个OPC组 Set objTestGrp = objGroups.Add(TestGrp) End IfEnd Sub3) 添加OPC标签对OPC服务器进行访问前,必须先在OPC组里添加要访问的OPC标签。这里添加OPC标签的标识符和数目是固定的,但是实际的OPC应用程序往往要按照用户的指定或读取组态文件取得和处理需要添加OPC标签(表4)表4 AddItem子程序Sub AddItem() Dim strItemIDs(2) As String Dim lClientHandles(2) As Long Dim lErrors() As LongDim I As
11、 Integer If objTestGrp Is Nothing Then Exit Sub End If If Not objItems Is Nothing Then If objItems.Count 0 Then Exit Sub End IfEnd If 设置组活动状态 objTestGrp.IsActive = True 取消组非同期通知 objTestGrp.IsSubscribed = False 建立OPC项集合 Set objItems = objTestGrp.OPCItems 生成标签的项标识符 strItemIDs(1) = 反应罐温度.Value strItemI
12、Ds(2) = 反应罐液位.Value lClientHandles(1) = 1 lClientHandles(2) = 2 添加OPC项 Call objItems.AddItems(2, strItemIDs, _ lClientHandles, lServerHandles, lErrors)End Sub4) 断开OPC服务器 连接着OPC服务器的OPC应用程序,在退出前必须断开和OPC服务器的连接(表5)。因为OPC服务器并不知道OPC应用程序已经退出,如果不先断开连接,那么OPC服务器所使用的计算机资源就不被释放。如果这样的问题反复发生,久而久之,连续运转的自动控制系统可能会使计
13、算机资源渐渐枯竭从而发生严重问题。表5 Disconnect子程序Sub Disconnect()Dim lErrors() As Long If Not objItems Is Nothing Then If objItems.Count 0 Then 清除OPC项 objItems.Remove 2, lServerHandles, lErrors End If Set objItems = NothingEnd If If Not objTestGrp Is Nothing Then 清除OPC组 objGroups.Remove TestGrp Set objTestGrp = Not
14、hing End If If Not objGroups Is Nothing Then Set objGroups = Nothing End If If Not objServer Is Nothing Then If objServer.ServerState OPCDisconnected Then 断开OPC服务器. objServer.Disconnect End If Set objServer = Nothing End If End Sub(3)同步数据读写到此为止,我们已经基本说明了OPC对象。现在,让我们制作一个实际的OPC数据访问应用程序。我们采用同步方式的数据访问。1
15、)窗体设计 让我们制做如图3所示窗体的OPC应用程序。图3 窗体设计 这个程序读取2点的数据,并用棒图表示读取的数据。棒图的更新周期为0.1s(100ms),使用定时器以0.1秒的周期对OPC服务器进行同期数据读取。并且假定规定温度上限为150,液位上限为600。窗体中所使用的控件种类如表6所示表6 OPC_zj的控件表控件名称窗体(Form)OPC_zj命令按钮(CommandButton)zjConnect命令按钮(CommandButton)zjAddItem命令按钮(CommandButton)zjQuit命令按钮(CommandButton)zjStop定时器(Timer)zjTmU
16、pdate图像(PictureBox)picBar(作为数组使用,从左开始12)图像(PictureBox)Picture1(作为数组使用,从左开始12)标签(Label)lbBar(作为数组使用。从左开如12)标签(Label)Label1(反应罐温度)标签(Label)Label2(反应罐液位)标签(Label)Label3(显示即时日期)标签(Label)Label4(显示即时时间)标签(Label)Label5(显示反应罐温度变化趋势)标签(Label)Label6(显示反应罐液位变化趋势)标签(Label)Label7(显示反应罐温度情况)标签(Label)Label8(显示反应罐液
17、位情况) 命令按钮的事件当按下在窗体上的命令按钮的事件发生时,通过调用在第一部分说明的各种方法对发生的事件进行处理(表7,表8,表9,表10)表7 zjConnect命令按钮的单击事件处理Private Sub zjConnect_Click() 调用Connect子程序 Call Connect(kingview.view.1,192.168.0.1)End Sub表8 zjAddItem命令按钮的单击事件处理Private Sub zjAddItem_Click() 调用AddItem子程序 Call AddItem If Not objTestGrp Is Nothing Then If
18、 objTestGrp.OPCItems.Count 0 Then 启动定时器 tmUpdate.Enabled = True Else End If End If End Sub表9 zjQuit命令按钮的单击事件处理Private Sub zjQuit_Click() 卸载窗体 Unload OPC_zjEnd Sub表10 zjStop命令按钮的单击事件处理Private Sub zjStop_Click()If zjtmUpdate.Enabled = False Then Call AddItem 调用AddItem子程序 If Not objTestGrp Is Nothing T
19、hen If objTestGrp.OPCItems.Count 0 Then 启动定时器 zjtmUpdate.Enabled = True Else End If End If Else zjtmUpdate.Enabled = FalseEnd IfEnd Sub为了在中止应用程序时断开和OPC服务器的连接,在窗体的Unload事件处理中调用了断开OPC服务器连接子程序(表11)表11 OPC_zj窗体的卸载事件处理Private Sub Form_Unload(Cancel As Integer) 调用Disconnect子程序 Call DisconnectEnd Sub 为了在操作
20、界面上同步显示日期和时间,定义方法zjdate,并且在同步读取数据过程中进行调用以便实时更新,显示时间代码如表12所示。表12 方法zjdate的定义处理 日期时间显示方法Sub zjdate()Label3.Caption = Trim(Str(Year(Date) + 年 + Trim(Str(Month(Date) + 月 _+ Trim(Str(Day(Date) + 日Label4.Caption = 现在时间: + Trim(Str(Hour(Time) + 时 + Trim(Str(Minute(Time) _+ 分 + Trim(Str(Second(Time) + 秒End
21、Sub3)同步数据读取在本示范程序中是利用定时器事件进行数据更新的显示。这时所有的数据是采用同步方式对OPC服务器进行读取的。表13是定时器事件处理以及同步读取处理的代码。表13 zjtmUpdate定时器的定时事件处理Private Sub zjtmUpdate_Timer() Dim vtItemValues() As Variant Dim lErrors() As Long Dim strBuf As String Dim nWidth As Integer Dim nHeight As Integer Dim nDrawHeight As Integer Dim sglScale A
22、s Single Dim I As Integer 同期读取SyncRead OPCCache, vtItemValues, lErrors 棒图的表示 For I = 1 To 2 数据的格式化 strBuf = Format(vtItemValues(I), #.000) 表示数据字符串 lbBar(I).Caption = strBuf 计算棒的宽和高 nWidth = picBar(I).ScaleWidth nHeight = picBar(I).ScaleHeight sglScale = vtItemValues(I) / 800 nDrawHeight = CInt(nHeig
23、ht * sglScale) 清除现棒图 picBar(I).Cls 绘制棒图 picBar(I).Line (0, nHeight - nDrawHeight)-(nWidth, nHeight), _ RGB(0, 255, 0), BF 绘制温度和液位的变化曲线 n = n + 1 Picture1(I).Line (n - 1, nHeight - nDrawHeight)-(n - 1, nHeight), _ RGB(0, 0, 255) 判断反应罐温度和液位正常情况 If vtItemValues(1) 150 Then Label7.Caption = 温度过高! Else L
24、abel7.Caption = 温度正常! End If If vtItemValues(2) 600 Then Label8.Caption = 液位过高! Else Label8.Caption = 液位正常! End If NextEnd Sub 定时器事件处理内调用的“SyncRead”子程序如表14所示。再有在读取前为了避免错误发生,对OPC组和OPC标签进行检查。表14 SyncRead子程序Sub SyncRead(nSource As Integer, ByRef vtItemValues() As Variant, _ ByRef lErrors() As Long) Dim
25、 lServerHandlesTemp(2) As Long Dim j As Integer If objTestGrp Is Nothing Then Exit SubEnd If调用日期和时间显示方法Call zjdate If objTestGrp.OPCItems.Count 0 Then 同期读取 objTestGrp.SyncRead nSource, 2, lServerHandles, _ vtItemValues, lErrors End IfEnd Sub在窗体开始加载时对定时器进行初始化,如表15所示表15 窗体载入时定时器的初始化Private Sub Form_Lo
26、ad() zjtmUpdate.Enabled = FalsezjtmUpdate.Interval = 100初始化n n = 0End Sub至此,窗体上的各项控件所对应的事件及方法全部定义完毕,通过连接OPC并读取服务器数据,可以实现对所取数据的其他操作.四、运行结果经过上述的计算机环境设置、窗体设计和代码编写,整个设计过程便已完成了,经调试无误后便可以观察运行结果,基于自己的设计功能,可以从窗体界面读取当前日期和时间,时刻观察到反应罐温度和液位数据大小及其相应的变化趋势,并且能够观察到温度和液位是否超过了规定的上限,其运行结果如下图所示:图4 温度和液位正常的情况图5 温度和液位过高的
27、情况五、 课设总结及心得本次软件课程设计让我们进一步通过实际操作熟悉对OPC的各种概念,并且掌握OPC客户端的编写方法,由于设计前老师已经提供了课设范例,经过对所提供的范例进行分析和研究,我们对课程设计的步骤和重点都有了更好的了解,在老师所给的源程序的基础上进行改进,这使我们对OPC客户端的编程有了一定的了解,并且更加熟悉和掌握了Visual Basic 这种编程语言,经过计算机环境的设置,对微软的DCOM有一定的了解,虽然实验室中的所有机子都是已经配置好了的,但是仍然了解了其配置的重要性。在实验过程中我们的确遇到过一些困难,但是我们努力去图书馆努力查找资料,并且在老师和同学的帮助都顺利解决了难题,得到了自己想要的结果。本次课程设计极大地锻炼了我的动手能力,让我进一步学会了用理论联系实际的解决问题的方法,为进一步学习网络及服务器相关内容打下了坚实的基础,获益匪浅。