用友报表数据采集 [VB在仪表数据采集和报表上的应用]
0 前言 工业PLC控制系统通过采集仪表输出的4~20mA信号进行积分,得到介质的累积量。由于4~20mA信号时模拟信号,和仪表显示的瞬时流量存误差,PLC实现的方式是通过对瞬时流量的积分,时间长了,PLC的累积量和仪表的累计量的误差就会越来越大。因此生产上的PLC控制系统的报表和抄表人员的报表数据相差比较大。
通过使用vb编程,采用串口通讯,使用仪表支持的Modbus-RTU协议,将盟控仪表的累积量用通讯的方式采集到计算机中,通过通讯采集上来的仪表数据做报表能准时的将报表数据统计上来,这种方式,不仅消除了PLC系统和抄表上的误差,也取代了人工抄表。
1 MSComm控件设置
1.1 添加MSComm控件
打开VB工程,在菜单栏的工程下找到部件,或者也可以通过在工具箱上右击,选择部件,在控件页面中勾选Microsoft Comm Control6.0,点击确定,完成控件的添加。
1.2 MSComm属性设置
添加控件完成之后,在工具箱中就可以看到这个控件。将控件拖入到窗体中,设置其属性,设置名称为MSC_SJ。设置端口号的时候,需要通过控制面板的管理工具下的设备管理中查看工控机的端口号,其值不能超过16。
With MSC_SJ
.CommPort = 1
.Settings = "9600,n,8,1"""设置端口参数,需要和仪表的设置保持一致
.PortOpen = True ""打开通讯端口
.InputMode = 1""接收二进制数据
1.3 MSComm发送数据
按照Modbus-RTU串口通讯协议,需要读取仪表瞬时量和累积量,这两个量都是4字节的浮点数。所以需要发送的数据为:站地址(仪表设置的地址)+功能码03(读寄存器地址)+数据起始地址(所需要的数据所在仪表的地址)+访问数据的个数(数据按字计算长度)+CRC校验。采用CRC-16,对data(i)数组进行校验,函数如下:
Dim CRC16Lo, CRC16Hi As Byte
Dim CL, CH,SaveHi, SaveLo As Byte
CRC16Lo = &HFF
CRC16Hi = &HFF
CL = &H1
CH = &HA0
For i = 0 To UBound(data) - 1
CRC16Lo = CRC16Lo Xor data(i)
For Flag = 0 To 7
SaveHi = CRC16Hi
SaveLo = CRC16Lo
CRC16Hi = CRC16Hi\2
CRC16Lo = CRC16Lo\2
If ((SaveHi And &H1)= &H1) Then
CRC16Lo = CRC16Lo Or &H80
End If
If ((SaveLo And &H1)= &H1) Then
CRC16Hi = CRC16Hi Xor CH
CRC16Lo = CRC16Lo Xor CL
End If
Next Flag
Next i
Dim ReturnData(1) As Byte
ReturnData(0) = CRC16Hi
ReturnData(1) = CRC16Lo
CalcCRC16 = ReturnData
2 和仪表通讯
2.1 仪表通讯设置
盟控仪表MF1503通讯参数的设置,在功能设置下的通讯设置中,设置通讯协议为Modbus,站地址(从6开始),波特率为9600,数据位为8,停止位为1,无校验,浮点数格式为3210。浮点数的格式和后面的浮点数的处理是相关的,如果仪表没有这个功能就需要在程序中调整4字节的顺序。
2.2 接收仪表数据
使用MSComm控件接收数据有两种方式,一个是定时刷新的方式,还有一种是采用OnComm事件触发数据接收。此处采用OnComm事件触发数据接收,需要设置RThreshold这个属性。
MBRcvLenth = 5 + SndByte(5) * 2
MSC_SJ.RThreshold = MBRcvLenth
Dim RcvData As Byte
Dim MBRcv As Variant
Select Case MSC_SJ.CommEvent
Case comEventOverrun
Exit Sub
Case comEventRxOver
Exit Sub
Case comEvReceive
MSC_SJ.InputLen = MBRcvLenth
MBRcv = MSC_SJTest.Input
MSC_SJ.InBufferCount = 0
For i = 0 To MBRcvLenth - 1
MBRcvByte(i) = MBRcv(i)
Next i
End Select
数据接收完成,同样也需要做CRC校验核对,以保证数据没有受到干扰。
2.3 数据转换
数据采集上来之后,是二进制的字符串,需要将数据按字节取出。需要转换为浮点数类型。
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
