董云龙
(辽宁省广播电视锦州中波站,辽宁 锦州 121000)
配电柜上的数显式智能电表通过对配电柜内部三相电压、三相电流进行采样分析,可以在面板上显示每相的电压、电流、有功功率、无功功率、视在功率、功率因数、交流频率、消耗的正负有功电能以及消耗的正负无功电能等信息。市面上的电表虽然型号不同,但是大都遵循行业标准,均采用RS485接口和Modbus协议,输出的监测数据大同小异。
在数据通信、计算机网络以及分布式工业控制系统中,经常采用串行通信来达到信息交换的目的,常见的串行接口标准有RS232、RS422以及RS485等[1]。RS422接口使用A+、A-、B+、B-两两差分的4根线,收发具备独立的信道,支持全双工通信,适用于星型网、环形网。RS485接口只有A、B收发共用的两根差分信号线,只能支持半双工通信,便于在多设备连接的场合使用,可以省掉许多信号线。
Modbus协议是Modicon公司推出的一种开放式现场总线通信协议,目前已经成为工业自动化网络协议规范[2]。通过Modbus协议,不同厂商生产的监测设备和控制设备可以与工业网络互联,实现集中监控。Modbus协议描述的是控制器如何请求访问其他设备,其他设备如何回应来自控制器的请求、检测错误等。Modbus协议定义了消息结构,而未定义物理层,不限定经过何种网络进行通信。Modbus可以在双绞线、光纤、无线等多种介质上传输,支持RS232、RS485等多种电气接口,目前最常见的是RS485接口[3]。
系统选用了全功能三合一隔离型以太网串口转换设备NETCOM-100IE,通过后台设置可选择工作在TCP-Server、TCP-Client或者组播模式,通过拨码选择可以将RS232、RS422、RS485标准的DB-9串行接口转为RJ45网络接口,并接入交换机或路由器,利用以太网的特性扩大了数据的传输和接收范围。通过查询智能电表的说明书或用户手册,获取智能电表的设置方法。系统采用三相四线连接方式,RS485接口的硬件地址为0001,波特率为9 600 Baud/s,传输帧结构为8个数据位、1个停止位、0个校验位。首先在串行数据接口-以太网接口转换器(以下简称串以转换器)的网页设置界面,设定IP地址、子网掩码、端口号。其次在计算机的网卡属性界面,设定控制计算机的IP地址与串以转换器在同一个子网段。最后用网线将串以转换器的RJ45接口与控制计算机相连,即可通过“IP:port”方式与智能电表建立通信连接[4]。
Python是当下流行的开源脚本编程语言,支持Windows、Unix、Linux、Android等多种操作系统平台,网络编程友好,操作套接字语法简洁、易读易用。Python内置Socket套接字模块,可以实现与串以转换器的数据交换。其Print函数可以实现数据处理、进制转换以及格式化输出,Tkinter模块可以制作图形界面。
Modbus协议有两种通信模式,即美国信息交换标准编码(American Standard Code for Information Interchange,ASCII)模式和远程终端设备(Remote Terminal Unit,RTU)模式。ASCII模式是将一个字节分为两个ASCII字符发送,而RTU模式以十六进制传送数据,其数据传送效率高于ASCII模式[5]。本系统选用RTU模式,其帧结构为8 bit地址码+8 bit功能码+N×8 bit数据段+16 bit校验码。地址码是用户设定的设备地址,每个设备地址唯一,计算机通过地址码与智能电表建立通信连接。当智能电表收到的地址码与自身的设定相同时才能返回响应数据,返回的地址码为智能电表硬件地址。本系统智能电表硬件地址设定为0001,地址码为0x01。功能码表示计算机要求智能电表执行何种操作,如0x01为读开关量输出状态、0x02为读开关量输入状态、0x03为读寄存器、0x05为写开关量输出(遥控)、0x06为写单路寄存器以及0x10为写多路寄存器等。不同厂家的产品对功能码的定义有差别,使用之前需要查询说明书或用户手册确认。目前最常用的功能码为0x03,即当计算机查询仪表和设备状态时就向Modbus-RTU总线上发出0x03功能码。
数据段是请求或响应的数据,计算机向智能电表发送指令的数据段包括读取寄存器的硬件起始地址和读取寄存器的数量,智能电表收到指令并向计算机返回响应的数据段包括数据长度和实际采集的数据。寄存器是电表采集和存放数据的地方,通常内部寄存器存储的信息依次为仪表参数、三相相电压采样、三相线电压采样、三相电流采样、三相有功功率、总有功功率、三相无功功率、总无功功率、三相视在功率、总视在功率、三相功率因数、总功率因数、总有功电能、正有功电能、负有功电能、总无功电能、正无功(感性)电能、负无功(容性)电能以及开关量状态等[6]。
通过加载Python语言的Socket模块,建立计算机与串以转换器(192.168.1.140:4001)的连接,通过串以转换器的RJ45接口与智能电表的RS485接口上的Modbus协议进行通信。具体程序为:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #构造TCP套接字s
s.connect(("192.168.1.140", 4001)) #套接字s连接串以转换器IP和端口
r = s.recv(1024) #接收串以转换器发送的连接成功建立的握手信息
print(r) #以16进制方式显示2进制数据流,1个字节用两个16进制符号输出显示
系统连接正确时,运行以上程序,可以在计算机接收到串以转换器输出的握手信息。为了加快数据读取、处理以及显示,本系统一次性读取智能电表的所有寄存器,并提取其中有用的部分数据段。设定仪表的硬件通信地址为0001,则程序中仪表的地址码为0x01,读取仪表的操作指令码为0x03,仪表内部寄存器的起始地址为0x00,则读取电表地址0x01起始寄存器0x00数据长度0x00 0x63(99)的指令为0x01 0x03 0x01 0x00 0x00 0x63。
计 算(010300000063)16的 CRC-16/Modbus为(E305)16(高位在前),根据Modbus通信协议,循环冗余校验码(Cyclic Redundancy Check,CRC)为低8位写在前,即0x05 0xE3,则使用Python读取电表的指令为:
s.send(b'x01x03x00x00x00x63x05xe3') #读寄存器指令
r = s.recv(1024) #接收电表响应数据
经过查阅,某品牌智能电表返回数据中第19~22字节为B相电压值,第31~34字节为C相电流值,第39~42字节为A相的有功功率值,第59~62字节为B相的无功功率值,第79~82字节为C相的视在功率值,第99~102字节为总功率因数值,第103~106字节为交流电频率。利用Python提取、处理、显示的程序为:
ub = int.from_bytes(r[19:23], byteorder='big')/1000 #无电压互感器直接采样
ic =int.from_bytes(r[31:35],byteorder='big')*80/1000 #400/5A电流互感
pa = int.from_bytes(r[39:43], byteorder='big',signed=True) #带符号数
qb = int.from_bytes(r[59:63], byteorder='big',signed=True) #带符号数
sc = int.from_bytes(r[79:83], byteorder='big') #无符号数
cos D =int.from_bytes(r[99:103],byteorder='big')/1000 #无符号,修正为小数
f = int.from_bytes(r[103:107], byteorder='big')/1000#无符号,修正为小数
其中:r[59:63]是提取接收数据r的第59、60、61、62字节的16进制数据;byteorder='big'是指定以高位在前的数据读取方式将16进制数据默认转换为不带符号的10进制数据;signed=True是指定转换为10进制带符号的数据,避免数据中以补码方式表示的负数出现转换错误。利用Python语法print('%.2f' %ia)四舍五入并保留两位小数格式化输出数据,作为全局变量供给程序其他部分使用。
在Python语法中使用While True结构让程序持续运行,通过try except结构抓取并处理程序运行中的错误信息,使用time模块和time.sleep(n)函数控制控制程序读取电表数据的时间间隔为n秒。
通过Python语言中的tkinter模块制作同时兼容Windows、Linux、Unix和Android等操作系统的可视化界面,显示从电表获取的各项数据。与此同时,采用if逻辑结构监测并判断数据的变化范围,从而实现对配电柜的实时监测。当数据变化超过设定的允许范围时,程序输出用于报警的开关量信号,控制报警系统本地计算机进行声像报警。通过结合全球移动通信系统(Global System for Mobile Communication,GSM)模块或者微信云服务,还可以实现远程监测和报警功能。
由于Modbus协议被众多仪表厂家支持,并且RS485接口支持单总线上连接多个设备,因此结合Python这种跨平台的脚本语言开发支持多平台、多设备的远程电力监测和报警系统,不但可以丰富技术人员的知识结构,而且有利于节约企事业单位的运营成本。