董云龍
(遼寧省廣播電視錦州中波站,遼寧 錦州 121000)
配電柜上的數(shù)顯式智能電表通過對配電柜內(nèi)部三相電壓、三相電流進行采樣分析,可以在面板上顯示每相的電壓、電流、有功功率、無功功率、視在功率、功率因數(shù)、交流頻率、消耗的正負有功電能以及消耗的正負無功電能等信息。市面上的電表雖然型號不同,但是大都遵循行業(yè)標準,均采用RS485接口和Modbus協(xié)議,輸出的監(jiān)測數(shù)據(jù)大同小異。
在數(shù)據(jù)通信、計算機網(wǎng)絡以及分布式工業(yè)控制系統(tǒng)中,經(jīng)常采用串行通信來達到信息交換的目的,常見的串行接口標準有RS232、RS422以及RS485等[1]。RS422接口使用A+、A-、B+、B-兩兩差分的4根線,收發(fā)具備獨立的信道,支持全雙工通信,適用于星型網(wǎng)、環(huán)形網(wǎng)。RS485接口只有A、B收發(fā)共用的兩根差分信號線,只能支持半雙工通信,便于在多設備連接的場合使用,可以省掉許多信號線。
Modbus協(xié)議是Modicon公司推出的一種開放式現(xiàn)場總線通信協(xié)議,目前已經(jīng)成為工業(yè)自動化網(wǎng)絡協(xié)議規(guī)范[2]。通過Modbus協(xié)議,不同廠商生產(chǎn)的監(jiān)測設備和控制設備可以與工業(yè)網(wǎng)絡互聯(lián),實現(xiàn)集中監(jiān)控。Modbus協(xié)議描述的是控制器如何請求訪問其他設備,其他設備如何回應來自控制器的請求、檢測錯誤等。Modbus協(xié)議定義了消息結(jié)構(gòu),而未定義物理層,不限定經(jīng)過何種網(wǎng)絡進行通信。Modbus可以在雙絞線、光纖、無線等多種介質(zhì)上傳輸,支持RS232、RS485等多種電氣接口,目前最常見的是RS485接口[3]。
系統(tǒng)選用了全功能三合一隔離型以太網(wǎng)串口轉(zhuǎn)換設備NETCOM-100IE,通過后臺設置可選擇工作在TCP-Server、TCP-Client或者組播模式,通過撥碼選擇可以將RS232、RS422、RS485標準的DB-9串行接口轉(zhuǎn)為RJ45網(wǎng)絡接口,并接入交換機或路由器,利用以太網(wǎng)的特性擴大了數(shù)據(jù)的傳輸和接收范圍。通過查詢智能電表的說明書或用戶手冊,獲取智能電表的設置方法。系統(tǒng)采用三相四線連接方式,RS485接口的硬件地址為0001,波特率為9 600 Baud/s,傳輸幀結(jié)構(gòu)為8個數(shù)據(jù)位、1個停止位、0個校驗位。首先在串行數(shù)據(jù)接口-以太網(wǎng)接口轉(zhuǎn)換器(以下簡稱串以轉(zhuǎn)換器)的網(wǎng)頁設置界面,設定IP地址、子網(wǎng)掩碼、端口號。其次在計算機的網(wǎng)卡屬性界面,設定控制計算機的IP地址與串以轉(zhuǎn)換器在同一個子網(wǎng)段。最后用網(wǎng)線將串以轉(zhuǎn)換器的RJ45接口與控制計算機相連,即可通過“IP:port”方式與智能電表建立通信連接[4]。
Python是當下流行的開源腳本編程語言,支持Windows、Unix、Linux、Android等多種操作系統(tǒng)平臺,網(wǎng)絡編程友好,操作套接字語法簡潔、易讀易用。Python內(nèi)置Socket套接字模塊,可以實現(xiàn)與串以轉(zhuǎn)換器的數(shù)據(jù)交換。其Print函數(shù)可以實現(xiàn)數(shù)據(jù)處理、進制轉(zhuǎn)換以及格式化輸出,Tkinter模塊可以制作圖形界面。
Modbus協(xié)議有兩種通信模式,即美國信息交換標準編碼(American Standard Code for Information Interchange,ASCII)模式和遠程終端設備(Remote Terminal Unit,RTU)模式。ASCII模式是將一個字節(jié)分為兩個ASCII字符發(fā)送,而RTU模式以十六進制傳送數(shù)據(jù),其數(shù)據(jù)傳送效率高于ASCII模式[5]。本系統(tǒng)選用RTU模式,其幀結(jié)構(gòu)為8 bit地址碼+8 bit功能碼+N×8 bit數(shù)據(jù)段+16 bit校驗碼。地址碼是用戶設定的設備地址,每個設備地址唯一,計算機通過地址碼與智能電表建立通信連接。當智能電表收到的地址碼與自身的設定相同時才能返回響應數(shù)據(jù),返回的地址碼為智能電表硬件地址。本系統(tǒng)智能電表硬件地址設定為0001,地址碼為0x01。功能碼表示計算機要求智能電表執(zhí)行何種操作,如0x01為讀開關(guān)量輸出狀態(tài)、0x02為讀開關(guān)量輸入狀態(tài)、0x03為讀寄存器、0x05為寫開關(guān)量輸出(遙控)、0x06為寫單路寄存器以及0x10為寫多路寄存器等。不同廠家的產(chǎn)品對功能碼的定義有差別,使用之前需要查詢說明書或用戶手冊確認。目前最常用的功能碼為0x03,即當計算機查詢儀表和設備狀態(tài)時就向Modbus-RTU總線上發(fā)出0x03功能碼。
數(shù)據(jù)段是請求或響應的數(shù)據(jù),計算機向智能電表發(fā)送指令的數(shù)據(jù)段包括讀取寄存器的硬件起始地址和讀取寄存器的數(shù)量,智能電表收到指令并向計算機返回響應的數(shù)據(jù)段包括數(shù)據(jù)長度和實際采集的數(shù)據(jù)。寄存器是電表采集和存放數(shù)據(jù)的地方,通常內(nèi)部寄存器存儲的信息依次為儀表參數(shù)、三相相電壓采樣、三相線電壓采樣、三相電流采樣、三相有功功率、總有功功率、三相無功功率、總無功功率、三相視在功率、總視在功率、三相功率因數(shù)、總功率因數(shù)、總有功電能、正有功電能、負有功電能、總無功電能、正無功(感性)電能、負無功(容性)電能以及開關(guān)量狀態(tài)等[6]。
通過加載Python語言的Socket模塊,建立計算機與串以轉(zhuǎn)換器(192.168.1.140:4001)的連接,通過串以轉(zhuǎn)換器的RJ45接口與智能電表的RS485接口上的Modbus協(xié)議進行通信。具體程序為:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #構(gòu)造TCP套接字s
s.connect(("192.168.1.140", 4001)) #套接字s連接串以轉(zhuǎn)換器IP和端口
r = s.recv(1024) #接收串以轉(zhuǎn)換器發(fā)送的連接成功建立的握手信息
print(r) #以16進制方式顯示2進制數(shù)據(jù)流,1個字節(jié)用兩個16進制符號輸出顯示
系統(tǒng)連接正確時,運行以上程序,可以在計算機接收到串以轉(zhuǎn)換器輸出的握手信息。為了加快數(shù)據(jù)讀取、處理以及顯示,本系統(tǒng)一次性讀取智能電表的所有寄存器,并提取其中有用的部分數(shù)據(jù)段。設定儀表的硬件通信地址為0001,則程序中儀表的地址碼為0x01,讀取儀表的操作指令碼為0x03,儀表內(nèi)部寄存器的起始地址為0x00,則讀取電表地址0x01起始寄存器0x00數(shù)據(jù)長度0x00 0x63(99)的指令為0x01 0x03 0x01 0x00 0x00 0x63。
計 算(010300000063)16的 CRC-16/Modbus為(E305)16(高位在前),根據(jù)Modbus通信協(xié)議,循環(huán)冗余校驗碼(Cyclic Redundancy Check,CRC)為低8位寫在前,即0x05 0xE3,則使用Python讀取電表的指令為:
s.send(b'x01x03x00x00x00x63x05xe3') #讀寄存器指令
r = s.recv(1024) #接收電表響應數(shù)據(jù)
經(jīng)過查閱,某品牌智能電表返回數(shù)據(jù)中第19~22字節(jié)為B相電壓值,第31~34字節(jié)為C相電流值,第39~42字節(jié)為A相的有功功率值,第59~62字節(jié)為B相的無功功率值,第79~82字節(jié)為C相的視在功率值,第99~102字節(jié)為總功率因數(shù)值,第103~106字節(jié)為交流電頻率。利用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) #帶符號數(shù)
qb = int.from_bytes(r[59:63], byteorder='big',signed=True) #帶符號數(shù)
sc = int.from_bytes(r[79:83], byteorder='big') #無符號數(shù)
cos D =int.from_bytes(r[99:103],byteorder='big')/1000 #無符號,修正為小數(shù)
f = int.from_bytes(r[103:107], byteorder='big')/1000#無符號,修正為小數(shù)
其中:r[59:63]是提取接收數(shù)據(jù)r的第59、60、61、62字節(jié)的16進制數(shù)據(jù);byteorder='big'是指定以高位在前的數(shù)據(jù)讀取方式將16進制數(shù)據(jù)默認轉(zhuǎn)換為不帶符號的10進制數(shù)據(jù);signed=True是指定轉(zhuǎn)換為10進制帶符號的數(shù)據(jù),避免數(shù)據(jù)中以補碼方式表示的負數(shù)出現(xiàn)轉(zhuǎn)換錯誤。利用Python語法print('%.2f' %ia)四舍五入并保留兩位小數(shù)格式化輸出數(shù)據(jù),作為全局變量供給程序其他部分使用。
在Python語法中使用While True結(jié)構(gòu)讓程序持續(xù)運行,通過try except結(jié)構(gòu)抓取并處理程序運行中的錯誤信息,使用time模塊和time.sleep(n)函數(shù)控制控制程序讀取電表數(shù)據(jù)的時間間隔為n秒。
通過Python語言中的tkinter模塊制作同時兼容Windows、Linux、Unix和Android等操作系統(tǒng)的可視化界面,顯示從電表獲取的各項數(shù)據(jù)。與此同時,采用if邏輯結(jié)構(gòu)監(jiān)測并判斷數(shù)據(jù)的變化范圍,從而實現(xiàn)對配電柜的實時監(jiān)測。當數(shù)據(jù)變化超過設定的允許范圍時,程序輸出用于報警的開關(guān)量信號,控制報警系統(tǒng)本地計算機進行聲像報警。通過結(jié)合全球移動通信系統(tǒng)(Global System for Mobile Communication,GSM)模塊或者微信云服務,還可以實現(xiàn)遠程監(jiān)測和報警功能。
由于Modbus協(xié)議被眾多儀表廠家支持,并且RS485接口支持單總線上連接多個設備,因此結(jié)合Python這種跨平臺的腳本語言開發(fā)支持多平臺、多設備的遠程電力監(jiān)測和報警系統(tǒng),不但可以豐富技術(shù)人員的知識結(jié)構(gòu),而且有利于節(jié)約企事業(yè)單位的運營成本。