源HMI設(shè)計(jì)工具選型指南:從PLC監(jiān)控到SCADA上位機(jī)實(shí)戰(zhàn))
上個(gè)月我?guī)鸵粋€(gè)朋友選型一套小型產(chǎn)線的上位機(jī)方案他最初的念頭是買(mǎi)一套現(xiàn)成的商業(yè)組態(tài)軟件。結(jié)果去打聽(tīng)了一圈授權(quán)費(fèi)用、培訓(xùn)成本、后期維護(hù)加起來(lái)直接勸退而且很多功能他根本用不上。后來(lái)我們擠出兩個(gè)晚上把幾款主流開(kāi)源HMI設(shè)計(jì)工具拉出來(lái)對(duì)比又花了一天半把一套PLC監(jiān)控頁(yè)面上線預(yù)算幾乎歸零。這篇文章就是從那兩天半的實(shí)戰(zhàn)里整理出來(lái)的重點(diǎn)圍繞工業(yè)自動(dòng)化、SCADA上位機(jī)、PLC監(jiān)控場(chǎng)景聊聊開(kāi)源HMI設(shè)計(jì)工具到底該怎么選、怎么用。先給個(gè)忠告開(kāi)源HMI工具不是商業(yè)軟件的簡(jiǎn)單替代品它是另一條技術(shù)路線。選得好兩三天就能上線選不好后面改架構(gòu)的痛苦會(huì)遠(yuǎn)超你的想象。下面我按選型前思考、方案盤(pán)點(diǎn)、實(shí)操Demo、通信原理、踩坑記錄這個(gè)順序講最后附上我的個(gè)人判斷。1. 為什么越來(lái)越多的工控項(xiàng)目開(kāi)始放棄商業(yè)組態(tài)軟件1.1 商業(yè)HMI軟件的核心痛點(diǎn)做自動(dòng)化項(xiàng)目的工程師多少都碰過(guò)這幾類(lèi)商業(yè)組態(tài)軟件。它們功能確實(shí)全組態(tài)畫(huà)圖、變量管理、報(bào)警、歷史曲線、配方管理什么都有。但問(wèn)題也集中在幾點(diǎn)授權(quán)成本高按點(diǎn)位收費(fèi)是行業(yè)慣例有些軟件連開(kāi)發(fā)環(huán)境都要單獨(dú)買(mǎi)授權(quán)。一個(gè)中型項(xiàng)目大幾百上千點(diǎn)的授權(quán)費(fèi)動(dòng)輒幾萬(wàn)。綁定硬件和操作系統(tǒng)很多授權(quán)鎖定加密狗或網(wǎng)卡換電腦要重新激活運(yùn)行環(huán)境以Windows為主想在Linux工控機(jī)上跑非常費(fèi)勁。擴(kuò)展性差想給頁(yè)面加一個(gè)非標(biāo)準(zhǔn)控件想接一個(gè)私有協(xié)議想去掉某個(gè)用不到的模塊基本都做不到。文檔與社區(qū)封閉遇到問(wèn)題大多數(shù)時(shí)候只能找原廠客服。而原廠客服對(duì)中小項(xiàng)目的響應(yīng)速度經(jīng)歷過(guò)的人都懂。所以這幾年我越來(lái)越傾向于把開(kāi)源方案放進(jìn)候選清單里不是在摳成本而是它確實(shí)解決了很多工程現(xiàn)場(chǎng)的實(shí)際麻煩。1.2 開(kāi)源方案為什么能站住腳過(guò)去大家覺(jué)得開(kāi)源HMI不靠譜主要是早期項(xiàng)目功能太弱、文檔太少、界面簡(jiǎn)陋。但最近五年發(fā)生了幾個(gè)變化Web技術(shù)成熟瀏覽器端SVG組態(tài)、WebSocket實(shí)時(shí)推送、WebGL圖表渲染讓開(kāi)源HMI在畫(huà)面表現(xiàn)力上已經(jīng)不輸傳統(tǒng)組態(tài)軟件。工業(yè)通信協(xié)議走向標(biāo)準(zhǔn)化Modbus TCP/RTU、OPC UA這些跨廠商協(xié)議被越來(lái)越廣泛地支持開(kāi)源項(xiàng)目只要支持這些協(xié)議就等于打通了市面上絕大多數(shù)PLC和儀表。部署方式變輕Docker等容器技術(shù)普及之后開(kāi)源SCADA平臺(tái)從“搭建一堆依賴(lài)”變成了“一條命令啟動(dòng)”實(shí)施成本大幅下降。生態(tài)互補(bǔ)有采集工具、有數(shù)據(jù)庫(kù)、有可視化前端每個(gè)環(huán)節(jié)都有優(yōu)秀的開(kāi)源項(xiàng)目可選大家可以像搭積木一樣組合出適合自己方案的鏈路。當(dāng)然開(kāi)源不是免費(fèi)午餐。你已經(jīng)支付的成本是“學(xué)習(xí)時(shí)間”和“自己維護(hù)的精力”這兩個(gè)我在后面的選型清單里會(huì)詳細(xì)展開(kāi)。2. 選型前的硬核思考你的HMI到底需要哪幾層能力2.1 不要把“畫(huà)面上有幾個(gè)儀表盤(pán)”當(dāng)成HMI經(jīng)常有人拿著Grafana做的漂亮大屏來(lái)問(wèn)“這是不是就是開(kāi)源HMI”嚴(yán)格來(lái)說(shuō)不是。HMI或者SCADA系統(tǒng)至少包含五層能力采集層從PLC、儀表、傳感器讀取數(shù)據(jù)按指定周期輪詢(xún)支持?jǐn)嗑€重連。數(shù)據(jù)映射層把協(xié)議側(cè)的寄存器地址、數(shù)據(jù)塊偏移映射成工程意義上的“變量”比如“1號(hào)罐溫度”“水泵轉(zhuǎn)速”還要解決字節(jié)序、數(shù)據(jù)類(lèi)型轉(zhuǎn)換問(wèn)題。畫(huà)面組態(tài)層把圖元、按鈕、文本框和變量綁定起來(lái)支持顏色變化、動(dòng)畫(huà)、數(shù)值顯示、滑動(dòng)條、趨勢(shì)圖。報(bào)警與事件層設(shè)置上下限、報(bào)警確認(rèn)、恢復(fù)判斷、報(bào)警記錄。歷史存儲(chǔ)層把數(shù)據(jù)存進(jìn)數(shù)據(jù)庫(kù)支持按時(shí)間段查詢(xún)和曲線回放。一個(gè)項(xiàng)目如果只需要第1、3層那很多輕量工具就夠了如果五層都要就不能只看“能畫(huà)圖”否則做到中途會(huì)發(fā)現(xiàn)報(bào)警或者歷史記錄缺失非常難受。2.2 選型前必須明確的技術(shù)約束清單我建議你在選型前先把下面這張表填完再開(kāi)始比工具。這能幫你過(guò)濾掉80%不合適的選項(xiàng)。問(wèn)題為什么重要點(diǎn)位數(shù)量有多少50、200、還是2000以上點(diǎn)位直接影響采集輪詢(xún)策略、數(shù)據(jù)庫(kù)選型、頁(yè)面加載性能數(shù)據(jù)刷新速度要求多快1秒、500毫秒、還是毫秒級(jí)刷新周期太短會(huì)壓垮設(shè)備網(wǎng)口太長(zhǎng)則失去實(shí)時(shí)監(jiān)控意義現(xiàn)場(chǎng)用到哪些PLC或儀表不同協(xié)議支持程度差異巨大私有協(xié)議往往需要額外網(wǎng)關(guān)或庫(kù)需要Web遠(yuǎn)程訪問(wèn)嗎需要瀏覽器訪問(wèn)就優(yōu)先Web組態(tài)型不需要可以選桌面型歷史數(shù)據(jù)要存多久存多少點(diǎn)決定用SQLite、MySQL還是時(shí)序數(shù)據(jù)庫(kù)報(bào)警需要怎么處理只要閃爍還是要確認(rèn)、要記錄簡(jiǎn)版報(bào)警和工業(yè)級(jí)報(bào)警實(shí)現(xiàn)成本差別很大開(kāi)發(fā)團(tuán)隊(duì)熟悉什么語(yǔ)言Python、Node.js、Java、C#團(tuán)隊(duì)適合的工具完全不同有沒(méi)有人專(zhuān)職維護(hù)這個(gè)系統(tǒng)沒(méi)人維護(hù)就選社區(qū)活躍、常規(guī)部署簡(jiǎn)單的項(xiàng)目比如20個(gè)點(diǎn)位的水泵房監(jiān)控和2000個(gè)點(diǎn)位的車(chē)間SCADA前者用輕量Web組態(tài)加SQLite就夠后者必須考慮分布式采集、歷史歸檔、性能優(yōu)化甚至考慮是否要引入時(shí)序數(shù)據(jù)庫(kù)。把這些問(wèn)題想清楚再去選型才能少走彎路。3. 主流開(kāi)源HMI/SCADA方案盤(pán)點(diǎn)它們到底是什么定位3.1 輕量Web組態(tài)型出自帶編輯器的場(chǎng)景這一類(lèi)的代表是FUXA一個(gè)基于Web的HMI/SCADA項(xiàng)目自帶網(wǎng)頁(yè)版組態(tài)編輯器支持拖拽圖元、綁定變量、設(shè)置報(bào)警、畫(huà)趨勢(shì)曲線。它對(duì)中小型項(xiàng)目非常友好部署后用戶(hù)在瀏覽器里打開(kāi)IP地址就能開(kāi)發(fā)畫(huà)面不需要裝任何客戶(hù)端。它的數(shù)據(jù)接入能力也比較全支持Modbus TCP/RTU、MQTT、OPC UA還有西門(mén)子S7等其他協(xié)議。我實(shí)測(cè)下來(lái)一個(gè)200點(diǎn)以?xún)?nèi)的項(xiàng)目單臺(tái)服務(wù)器跑得很穩(wěn)。如果你做的是泵站、污水處理、小型產(chǎn)線監(jiān)控這類(lèi)需求可以把它列為第一候選。3.2 流程編排加儀表盤(pán)型靈活但需要拼裝這一類(lèi)以Node-RED為代表。Node-RED本身就是一款基于流的編程工具生態(tài)里有大量的Modbus、S7、OPC UA、MQTT節(jié)點(diǎn)可以把采集邏輯用節(jié)點(diǎn)連線的方式搭出來(lái)。它的Dashboard模塊又能生成基礎(chǔ)儀表盤(pán)包括圖表、開(kāi)關(guān)、表格等。Node-RED最大的優(yōu)勢(shì)是靈活幾乎所有協(xié)議都能通過(guò)安裝節(jié)點(diǎn)來(lái)支持很適合做“采集端”和“中轉(zhuǎn)層”。但它本身不是專(zhuān)業(yè)的組態(tài)軟件畫(huà)面布局能力偏弱復(fù)雜聯(lián)動(dòng)邏輯要靠寫(xiě)Function節(jié)點(diǎn)完成做大型SCADA畫(huà)面會(huì)比較痛苦。業(yè)界最常見(jiàn)的用法是讓Node-RED專(zhuān)門(mén)負(fù)責(zé)采集數(shù)據(jù)然后往MQTT或數(shù)據(jù)庫(kù)里扔再讓其他可視化工具取數(shù)據(jù)展示。3.3 數(shù)據(jù)可視化大屏型只做展示是它的強(qiáng)項(xiàng)提到Grafana工控圈都不陌生。它擅長(zhǎng)對(duì)接時(shí)序數(shù)據(jù)庫(kù)比如InfluxDB、Prometheus、SQLite、MySQL做出非常美觀的實(shí)時(shí)曲線、儀表盤(pán)、告警面板。但注意Grafana不能直接采集Modbus或者S7數(shù)據(jù)也沒(méi)有工業(yè)組態(tài)里“變量綁定圖元”的概念。它不是HMI而是數(shù)據(jù)可視化平臺(tái)。如果項(xiàng)目只需要把已經(jīng)存在數(shù)據(jù)庫(kù)里的數(shù)據(jù)做得好看Grafana足夠好如果還要實(shí)時(shí)控制PLC輸出、做復(fù)雜報(bào)警聯(lián)動(dòng)就必須在前面加一道采集層比如Node-RED采集后寫(xiě)庫(kù)再由Grafana展示。它的告警能力相對(duì)簡(jiǎn)單復(fù)雜的分級(jí)策略或確認(rèn)流程做起來(lái)不如專(zhuān)業(yè)SCADA順手。3.4 全功能開(kāi)源SCADA平臺(tái)型適合中大型項(xiàng)目如果系統(tǒng)規(guī)模較大需要完整的SCADA功能就要看Rapid SCADA和SCADA-LTS這一類(lèi)項(xiàng)目。Rapid SCADA采用C#生態(tài)包含服務(wù)器、通信模塊、Web界面、數(shù)據(jù)庫(kù)存儲(chǔ)以及大量工業(yè)設(shè)備驅(qū)動(dòng)模塊。適合有一定.NET開(kāi)發(fā)能力的團(tuán)隊(duì)部署偏傳統(tǒng)學(xué)習(xí)曲線比輕量工具陡。SCADA-LTS基于Java生態(tài)提供數(shù)據(jù)采集、報(bào)警、歷史存儲(chǔ)、趨勢(shì)分析等功能內(nèi)置Web界面支持多用戶(hù)權(quán)限和工業(yè)協(xié)議。適合熟悉Java技術(shù)棧、需要全功能SCADA但不想從零搭建的團(tuán)隊(duì)。這類(lèi)平臺(tái)的特點(diǎn)是“該有的功能都有”但代價(jià)是你得投入時(shí)間學(xué)習(xí)它們的架構(gòu)、配置文件和數(shù)據(jù)模型。它們更像是傳統(tǒng)商業(yè)SCADA的開(kāi)源對(duì)應(yīng)物。3.5 物聯(lián)網(wǎng)平臺(tái)型自帶SCADA模塊的融合方案最后說(shuō)一下ThingsBoard。它本來(lái)是個(gè)物聯(lián)網(wǎng)設(shè)備管理平臺(tái)后來(lái)加入了儀表盤(pán)和SCADA能力。它的強(qiáng)項(xiàng)在設(shè)備管理、數(shù)據(jù)入庫(kù)、報(bào)警規(guī)則以及REST API和MQTT接入。如果你的“HMI”要對(duì)接大量物聯(lián)網(wǎng)設(shè)備又需要遠(yuǎn)程管理、多租戶(hù)、設(shè)備影子之類(lèi)的功能ThingsBoard會(huì)很合適。不過(guò)它偏向IoT體系純做PLC監(jiān)控時(shí)反而顯得重配置流程也復(fù)雜中小型純工控項(xiàng)目要慎重評(píng)估。3.6 橫向?qū)Ρ纫痪湓捰涀∷鼈兊哪芰吔绶桨钢饕Z(yǔ)言/生態(tài)數(shù)據(jù)采集畫(huà)面組態(tài)報(bào)警聯(lián)動(dòng)歷史存儲(chǔ)適合場(chǎng)景FUXANode.js/WebModbus、MQTT、OPC UA、S7自帶組態(tài)編輯器拖拽式支持閾值報(bào)警內(nèi)嵌存儲(chǔ)中小型監(jiān)控頁(yè)面的快速搭建Node-REDNode.js生態(tài)節(jié)點(diǎn)豐富協(xié)議極多Dashboard較弱需自行寫(xiě)邏輯配合數(shù)據(jù)庫(kù)采集中轉(zhuǎn)、系統(tǒng)集成GrafanaGo/Web不能直接采集儀表盤(pán)/大屏非常強(qiáng)簡(jiǎn)單告警配合時(shí)序數(shù)據(jù)庫(kù)數(shù)據(jù)可視化、大屏Rapid SCADAC#/.NET內(nèi)置大量工業(yè)驅(qū)動(dòng)Web/桌面組態(tài)完整報(bào)警體系數(shù)據(jù)庫(kù)支持良好中大型全功能SCADASCADA-LTSJava支持Modbus、OPC UA等自帶Web界面完整報(bào)警體系MySQL/MariaDB中大型SCADA的Java選型ThingsBoardJava/WebIoT協(xié)議、MQTT、HTTP儀表盤(pán)/SCADA模塊規(guī)則引擎報(bào)警內(nèi)置數(shù)據(jù)庫(kù)IoT設(shè)備管理融合場(chǎng)景4. 實(shí)操篇用開(kāi)源方案把一套PLC數(shù)據(jù)搬進(jìn)瀏覽器頁(yè)面4.1 為什么我拿FUXA做演示我平時(shí)做中小型監(jiān)控項(xiàng)目最常選的組合就是FUXA加Modbus模擬器做驗(yàn)證。原因很簡(jiǎn)單FUXA部署最簡(jiǎn)單組態(tài)界面就在瀏覽器里新手上手路徑最短。下面的操作能在一天內(nèi)從零跑通而且步驟可以平移到真實(shí)PLC環(huán)境。先說(shuō)明一下我下面提到的“FUXA”你可以理解為一類(lèi)Web組態(tài)型開(kāi)源HMI設(shè)計(jì)工具的代表。如果你在選型時(shí)看到功能類(lèi)似的其他項(xiàng)目思路和操作流程基本通用。4.2 第一步部署運(yùn)行環(huán)境FUXA支持Docker部署這是最快的方式。在服務(wù)器或工控機(jī)上裝好Docker之后一條命令就能啟動(dòng)docker run -d --name fuxa \ -p 1881:1881 \ -v fuxa_data:/usr/src/app/data \ FUXA官方鏡像名稱(chēng)啟動(dòng)后瀏覽器訪問(wèn)http://服務(wù)器IP:1881就能打開(kāi)組態(tài)開(kāi)發(fā)界面。如果你不用Docker也可以直接用Node.js跑源碼但那樣需要手動(dòng)裝依賴(lài)、配置數(shù)據(jù)庫(kù)速度慢一些。我這里強(qiáng)調(diào)一個(gè)易錯(cuò)細(xì)節(jié)數(shù)據(jù)卷要掛載好。因?yàn)镕UXA的畫(huà)面、變量配置、報(bào)警規(guī)則都存在數(shù)據(jù)目錄里容器一刪就要靠這個(gè)數(shù)據(jù)卷保留配置。我做項(xiàng)目時(shí)習(xí)慣把數(shù)據(jù)目錄單獨(dú)放在一塊獨(dú)立磁盤(pán)或NAS上避免工控機(jī)系統(tǒng)盤(pán)故障時(shí)整個(gè)項(xiàng)目配置丟失。4.3 第二步準(zhǔn)備一個(gè)Modbus從站做數(shù)據(jù)源沒(méi)有真實(shí)PLC時(shí)可以用Modbus模擬器充當(dāng)從站。常見(jiàn)做法是裝一個(gè)Modbus Slave軟件在里面創(chuàng)建一張寄存器表手動(dòng)改變數(shù)值模擬現(xiàn)場(chǎng)工況。也可以寫(xiě)一個(gè)Python腳本用pymodbus庫(kù)啟動(dòng)一個(gè)虛擬Modbus TCP從站from pymodbus.server import StartTcpServer from pymodbus.datastore import ModbusSequentialDataBlock, ModbusSlaveContext, ModbusServerContext # 建立一段模擬保持寄存器起始地址從0開(kāi)始共100個(gè)寄存器 slave ModbusSlaveContext( diModbusSequentialDataBlock(0, [False] * 100), coModbusSequentialDataBlock(0, [False] * 100), hrModbusSequentialDataBlock(0, [0] * 100), irModbusSequentialDataBlock(0, [0] * 100), ) context ModbusServerContext(slaves{1: slave}, singleFalse) # 啟動(dòng)Modbus TCP Server默認(rèn)端口502 StartTcpServer(contextcontext, address(0.0.0.0, 502))運(yùn)行起來(lái)后這臺(tái)機(jī)器就是一臺(tái)虛擬PLC寄存器地址可以直接映射到FUXA里。這里也要提醒一句Linux下運(yùn)行綁502端口需要root或?qū)?yīng)權(quán)限Windows下沒(méi)這個(gè)問(wèn)題實(shí)際項(xiàng)目里PLC的Modbus TCP端口通常也是502。4.4 第三步在FUXA里創(chuàng)建設(shè)備與變量打開(kāi)FUXA頁(yè)面后先創(chuàng)建設(shè)備。設(shè)備類(lèi)型選Modbus TCP填從站IP地址、端口502、輪詢(xún)周期。輪詢(xún)周期建議先按1秒設(shè)后面根據(jù)設(shè)備響應(yīng)速度再調(diào)。接著創(chuàng)建變量。這是把寄存器地址變成“工程變量”的關(guān)鍵一步變量名寫(xiě)上“1號(hào)罐溫度”這種便于辨識(shí)的名稱(chēng)。數(shù)據(jù)地址填寄存器偏移量比如保持寄存器40001對(duì)應(yīng)偏移040002對(duì)應(yīng)偏移1。數(shù)據(jù)類(lèi)型按PLC寄存器里的實(shí)際存儲(chǔ)類(lèi)型選擇常見(jiàn)的有Int16、UInt16、Int32、Float32。這一步非常關(guān)鍵選錯(cuò)數(shù)據(jù)類(lèi)型讀出來(lái)的數(shù)就是亂碼。訪問(wèn)類(lèi)型按需選只讀或讀寫(xiě)。要支持控制按鈕、遠(yuǎn)程啟停就選讀寫(xiě)。我在實(shí)際配置時(shí)會(huì)把變量在紙質(zhì)的點(diǎn)位表上先整理好把設(shè)備IP、寄存器偏移、數(shù)據(jù)類(lèi)型、讀寫(xiě)屬性全部列清楚再到FUXA里錄入。這樣看起來(lái)慢但能大幅度減少配置錯(cuò)誤。動(dòng)輒幾十上百個(gè)變量的時(shí)候腦子直接記絕對(duì)會(huì)亂。4.5 第四步拖拽圖元綁定變量FUXA的組態(tài)界面和傳統(tǒng)HMI軟件類(lèi)似左側(cè)是圖元庫(kù)中間是畫(huà)布右側(cè)是屬性面板。把數(shù)值顯示、開(kāi)關(guān)按鈕、圖形儀表拖到畫(huà)布上然后在屬性里綁定剛才創(chuàng)建的變量。舉個(gè)實(shí)際例子我需要做一個(gè)水泵運(yùn)行狀態(tài)頁(yè)面。拖入一個(gè)圓形的“指示燈”圖元綁定一個(gè)布爾變量用顏色表達(dá)式讓變量為1時(shí)顯示綠色為0時(shí)顯示灰色。拖入一個(gè)“數(shù)值顯示”控件綁定溫度變量顯示單位保持“℃”。拖入一個(gè)“啟動(dòng)”按鈕綁定一個(gè)讀寫(xiě)變量按下時(shí)寫(xiě)入1實(shí)現(xiàn)遠(yuǎn)程啟動(dòng)動(dòng)作。綁定完成后切換到運(yùn)行模式模擬器里修改寄存器值頁(yè)面上應(yīng)該能看到實(shí)時(shí)變化。這種“數(shù)值變化驅(qū)動(dòng)圖元變化”的機(jī)制就是HMI組態(tài)的核心圖元只是載體變量才是靈魂。4.6 第五步設(shè)置報(bào)警與聯(lián)動(dòng)報(bào)警是SCADA不可或缺的部分。FUXA里可以為變量配置報(bào)警規(guī)則比如1號(hào)罐溫度上限60度觸發(fā)報(bào)警后頁(yè)面上的圖元會(huì)閃爍并在報(bào)警列表里出現(xiàn)記錄。這里有幾個(gè)經(jīng)驗(yàn)報(bào)警值建議設(shè)置成“閾值滯回區(qū)間”比如高報(bào)58度觸發(fā)、55度恢復(fù)避免臨界值附近反復(fù)報(bào)警。報(bào)警要配置確認(rèn)機(jī)制操作人員點(diǎn)擊“確認(rèn)”后閃爍變常亮但報(bào)警記錄仍保留。聯(lián)動(dòng)邏輯比如溫度超限自動(dòng)解鎖某個(gè)按鈕依賴(lài)變量之間的讀寫(xiě)控制必要時(shí)可以在瀏覽器端用少量腳本實(shí)現(xiàn)不影響組態(tài)流程。4.7 第六步多人訪問(wèn)與權(quán)限控制Web組態(tài)帶來(lái)的一個(gè)直接好處是現(xiàn)場(chǎng)中控室大屏、辦公室辦公電腦、車(chē)間平板可以同時(shí)打開(kāi)同一個(gè)頁(yè)面不需要安裝任何客戶(hù)端。FUXA支持用戶(hù)管理可以設(shè)置不同權(quán)限。我的習(xí)慣是查看權(quán)限給車(chē)間主任、值班人員只讀頁(yè)面。操作權(quán)限給當(dāng)班操作員可以點(diǎn)按鈕、改設(shè)置參數(shù)。管理員權(quán)限僅給少數(shù)維護(hù)人員能修改畫(huà)面、修改報(bào)警規(guī)則。權(quán)限這個(gè)事別偷懶。工業(yè)現(xiàn)場(chǎng)一旦有人誤操作影響的不只是電腦畫(huà)面可能是真實(shí)設(shè)備。系統(tǒng)上線前把權(quán)限表理清楚再開(kāi)通賬號(hào)。5. Modbus、OPC UA還是私有協(xié)議HMI與PLC通信的底層邏輯5.1 寄存器與點(diǎn)位理解HMI通信的第一把鑰匙PLC里的數(shù)據(jù)對(duì)HMI來(lái)說(shuō)就是一堆“寄存器”。HMI按協(xié)議發(fā)出讀取請(qǐng)求PLC返回寄存器里的數(shù)值HMI再把數(shù)值映射到畫(huà)布圖元上。以Modbus為例最常用的是保持寄存器和輸入寄存器。保持寄存器可以讀寫(xiě)通常用來(lái)存放控制參數(shù)和輸出值輸入寄存器一般只讀用來(lái)讀取外部模擬量或設(shè)備狀態(tài)。地址編號(hào)在不同場(chǎng)合有不同表示法容易把人繞暈區(qū)域常見(jiàn)地址表示協(xié)議偏移線圈00001開(kāi)始0x區(qū)離散輸入10001開(kāi)始1x區(qū)輸入寄存器30001開(kāi)始3x區(qū)保持寄存器40001開(kāi)始4x區(qū)在配置開(kāi)源HMI時(shí)多數(shù)工具讓你填“偏移量”而不是“40001”這種完整地址。比如保持寄存器40001填偏移040002填偏移1千萬(wàn)不要把40001這個(gè)數(shù)字直接填進(jìn)偏移里這是新手最容易犯的錯(cuò)配置完讀數(shù)全亂。5.2 32位數(shù)據(jù)與字節(jié)序?yàn)槭裁磿?huì)讀到天文數(shù)字Modbus寄存器一個(gè)只有16位也就是一個(gè)寄存器最多放一個(gè)16位整數(shù)。工業(yè)現(xiàn)場(chǎng)的浮點(diǎn)溫度、累加計(jì)量這種32位數(shù)據(jù)是占用兩個(gè)連續(xù)寄存器的。這時(shí)候就涉及字節(jié)序大端模式Motorola順序高字節(jié)在前。小端模式Intel順序低字節(jié)在前。還有字序的區(qū)別兩個(gè)寄存器誰(shuí)在高位、誰(shuí)在低位。我遇到過(guò)一個(gè)典型問(wèn)題讀回來(lái)的溫度在值域范圍內(nèi)但小數(shù)點(diǎn)后面幾位完全不對(duì)或者一會(huì)兒正一會(huì)兒負(fù)。排查到最后就是設(shè)備手冊(cè)里寫(xiě)的是“低字在前高字在后”而組態(tài)這邊按“高字在前”解析了。解決辦法就是配置變量時(shí)留個(gè)心眼先把一個(gè)已知值寫(xiě)進(jìn)PLC讀過(guò)來(lái)看解析是否正確。比對(duì)出正確字節(jié)序后把所有同類(lèi)變量統(tǒng)一設(shè)置。千萬(wàn)別憑記憶猜每臺(tái)設(shè)備的Modbus從站實(shí)現(xiàn)都可能不一樣。5.3 OPC UA跨廠商互通的時(shí)代選擇OPC UA的價(jià)值在于它不關(guān)心你底層用的什么PLC、什么協(xié)議。PLC廠商或者第三方網(wǎng)關(guān)會(huì)把所有數(shù)據(jù)整理成統(tǒng)一的“節(jié)點(diǎn)樹(shù)”上位機(jī)只需要瀏覽節(jié)點(diǎn)、訂閱節(jié)點(diǎn)值就行。用OPC UA接HMI最大的好處是配置簡(jiǎn)單不需要關(guān)心寄存器偏移、字節(jié)序、數(shù)據(jù)類(lèi)型映射節(jié)點(diǎn)名稱(chēng)和工程變量名幾乎一一對(duì)應(yīng)而且OPC UA自帶加密鑒權(quán)比裸奔的Modbus TCP安全很多。開(kāi)源HMI工具里對(duì)OPC UA支持做得好的方案在設(shè)備配置時(shí)只要填OPC UA服務(wù)端地址和節(jié)點(diǎn)ID即可。如果你的現(xiàn)場(chǎng)設(shè)備比較多、品牌雜我非常建議先把數(shù)據(jù)匯到一臺(tái)OPC UA服務(wù)器上再讓HMI統(tǒng)一對(duì)接。這樣HMI只需要處理一種協(xié)議維護(hù)成本低不少。5.4 西門(mén)子私有協(xié)議S7通信怎么接西門(mén)子PLC除了支持Modbus TCP之外它自己的S7通信協(xié)議是私有的。好在開(kāi)源生態(tài)里已經(jīng)有很成熟的通信庫(kù)比如snap7C/C、Python、Node.js都有綁定。用開(kāi)源HMI直接連西門(mén)子PLC通常需要提供DB塊號(hào)、起始偏移、數(shù)據(jù)類(lèi)型。這和Modbus邏輯相同只是尋址方式換成了“DB號(hào)加偏移”的體系。我用這類(lèi)方案連過(guò)S7-1200和S7-1500讀取DB塊里的溫度、壓力、速度等變量都很穩(wěn)定寫(xiě)操作也支持但要注意PLC側(cè)的訪問(wèn)權(quán)限設(shè)置CPU屬性里必須允許從遠(yuǎn)程通信訪問(wèn)。這里有個(gè)排查技巧如果連接失敗先查看通信庫(kù)自身的報(bào)錯(cuò)信息常見(jiàn)的多是“機(jī)架號(hào)/槽號(hào)配置錯(cuò)誤”“PLC側(cè)訪問(wèn)保護(hù)拒絕”“端口被防火墻攔截”這三類(lèi)逐個(gè)排除比盲目改HMI參數(shù)高效得多。6. 我在實(shí)際項(xiàng)目里踩過(guò)的坑以及對(duì)應(yīng)的處理辦法6.1 刷新周期打太高設(shè)備網(wǎng)口直接擁堵有一次做項(xiàng)目客戶(hù)說(shuō)數(shù)據(jù)要“越快越好”我把Modbus輪詢(xún)周期調(diào)到了100毫秒結(jié)果沒(méi)跑幾分鐘PLC的網(wǎng)口CPU占用就飆高了連正常程序下載都變慢。復(fù)盤(pán)原因HMI每100毫秒對(duì)整個(gè)寄存器區(qū)做一次全量輪詢(xún)報(bào)文數(shù)量巨大打爆了PLC響應(yīng)能力。后來(lái)改成“分組輪詢(xún)”策略把實(shí)時(shí)性要求高的數(shù)據(jù)放一個(gè)組500毫秒一輪普通數(shù)據(jù)顯示放另一個(gè)組2秒一輪變化率小的累計(jì)量放5秒一輪。實(shí)測(cè)下來(lái)數(shù)據(jù)一樣跟手PLC負(fù)載下降了80%以上。6.2 斷線重連機(jī)制PLC重啟后頁(yè)面“卡死”模擬器測(cè)試一切正?,F(xiàn)場(chǎng)跑了幾天后有一臺(tái)PLC斷電重啟HMI頁(yè)面從此再也不刷新。檢查發(fā)現(xiàn)通信庫(kù)在PLC斷線后默認(rèn)不會(huì)自動(dòng)重連必須手動(dòng)重啟設(shè)備服務(wù)。解決辦法在設(shè)備配置里找到通信超時(shí)和重試設(shè)置把“自動(dòng)重連”打開(kāi)同時(shí)把重試間隔設(shè)得溫和一些比如5秒重試一次。最好再寫(xiě)一個(gè)看門(mén)狗定期檢查通信狀態(tài)長(zhǎng)時(shí)間斷線時(shí)在頁(yè)面上顯示醒目的“通訊故障”橫幅。開(kāi)源工具往往默認(rèn)不會(huì)做這件事運(yùn)維和值班人員又不會(huì)去翻服務(wù)狀態(tài)頁(yè)面上的故障提示非常重要。6.3 報(bào)警“抖”臨界點(diǎn)反復(fù)觸發(fā)溫度在59.9度和60.1度之間來(lái)回跳動(dòng)時(shí)一個(gè)簡(jiǎn)單的“溫度大于60度報(bào)警”就會(huì)瘋了似的頻繁觸發(fā)和恢復(fù)報(bào)警記錄被刷屏操作員也分不清哪些是真實(shí)故障。這就是沒(méi)有設(shè)置“滯回區(qū)間”造成的。正確做法是高報(bào)觸發(fā)值設(shè)為60度恢復(fù)值設(shè)為55度低報(bào)觸發(fā)值設(shè)為0度恢復(fù)值設(shè)為5度。這樣現(xiàn)場(chǎng)設(shè)備的正常波動(dòng)不會(huì)頻繁跨越報(bào)警邊界報(bào)警記錄一眼看過(guò)去只有真正的異常。6.4 歷史數(shù)據(jù)越存越多頁(yè)面打開(kāi)越來(lái)越慢中小型項(xiàng)目最常見(jiàn)的做法是數(shù)據(jù)直接存在本機(jī)數(shù)據(jù)庫(kù)比如SQLite。但運(yùn)行三個(gè)月之后歷史表積了大量記錄趨勢(shì)頁(yè)面的查詢(xún)開(kāi)始變慢。這時(shí)不能一直加索引硬扛應(yīng)該考慮數(shù)據(jù)分級(jí)策略實(shí)時(shí)數(shù)據(jù)寫(xiě)入內(nèi)存緩存頁(yè)面查最近幾分鐘直接從緩存取。當(dāng)天數(shù)據(jù)寫(xiě)入按小時(shí)分區(qū)的數(shù)據(jù)表。超過(guò)三個(gè)月的老數(shù)據(jù)定期歸檔減小主表的查詢(xún)壓力。如果項(xiàng)目數(shù)據(jù)量大也可以把歷史庫(kù)換成時(shí)序數(shù)據(jù)庫(kù)把查詢(xún)壓力交給專(zhuān)門(mén)為時(shí)間序列優(yōu)化的引擎。開(kāi)源組件之間可以通過(guò)MQTT或HTTP接口解耦把“采集、存儲(chǔ)、展示”做成三段獨(dú)立的服務(wù)哪一段出問(wèn)題都不影響另外兩段。6.5 瀏覽器緩存改完配置頁(yè)面還是老樣子Web組態(tài)的另一個(gè)怪毛病是瀏覽器緩存。組態(tài)畫(huà)面的JS和圖片資源更新后現(xiàn)場(chǎng)大屏的瀏覽器還是舊版本。我經(jīng)常在客戶(hù)現(xiàn)場(chǎng)被問(wèn)“為什么改了畫(huà)面沒(méi)生效”其實(shí)按下F12打開(kāi)開(kāi)發(fā)工具勾選“Disable cache”再刷新頁(yè)面就正常了。為了減少這種問(wèn)題我一般會(huì)在發(fā)布時(shí)改一下靜態(tài)資源的版本號(hào)或者文件名讓瀏覽器識(shí)別為“新資源”。實(shí)操層面開(kāi)發(fā)機(jī)永遠(yuǎn)用無(wú)痕窗口訪問(wèn)HMI頁(yè)面現(xiàn)場(chǎng)機(jī)器則掛一個(gè)大字提示畫(huà)面不更新時(shí)按CtrlF5強(qiáng)制刷新。6.6 常見(jiàn)問(wèn)題速查表現(xiàn)象可能原因處置方向全部變量斷線IP、端口、網(wǎng)絡(luò)不通服務(wù)未啟動(dòng)先ping再telnet 502端口再查日志單個(gè)變量數(shù)據(jù)異常寄存器偏移填錯(cuò)、數(shù)據(jù)類(lèi)型不對(duì)對(duì)照點(diǎn)位表檢查偏移和字節(jié)序數(shù)據(jù)抖動(dòng)但PLC側(cè)正常輪詢(xún)周期太短、電磁干擾加大輪詢(xún)間隔檢查屏蔽雙絞線接地頁(yè)面加載慢變量過(guò)多、圖元復(fù)雜、數(shù)據(jù)庫(kù)查詢(xún)慢優(yōu)化輪詢(xún)分組圖元SVG簡(jiǎn)化歷史分表報(bào)警刷屏未設(shè)置滯回區(qū)間加滯回閾值或改為變化率報(bào)警7. 寫(xiě)在最后我的選型經(jīng)驗(yàn)和一個(gè)小彩蛋做了好幾個(gè)開(kāi)源HMI項(xiàng)目之后我最大的體會(huì)是選型不是找“最好的工具”而是找“最匹配當(dāng)前團(tuán)隊(duì)和項(xiàng)目約束的工具”。20個(gè)點(diǎn)的小泵站上一個(gè)全功能SCADA平臺(tái)純屬給自己添麻煩2000個(gè)點(diǎn)的車(chē)間級(jí)項(xiàng)目指望一個(gè)輕量組態(tài)工具撐全場(chǎng)也不現(xiàn)實(shí)。先畫(huà)點(diǎn)位表、列采集清單、理報(bào)警需求再回到這篇文章的對(duì)比表里去匹配整個(gè)過(guò)程會(huì)順暢非常多。最后分享一個(gè)小彩蛋用這套Web組態(tài)方案調(diào)試時(shí)我會(huì)同時(shí)打開(kāi)瀏覽器的開(kāi)發(fā)者工具切到Network面板過(guò)濾WebSocket連接。頁(yè)面里所有實(shí)時(shí)變量的數(shù)據(jù)推送都走WebSocket刷新頻率多少、有沒(méi)有斷線重連在Network面板里看得一清二楚。排查“頁(yè)面為什么沒(méi)更新”時(shí)這個(gè)技巧比在HMI代碼里打斷點(diǎn)還快。如果你已經(jīng)在用開(kāi)源HMI做項(xiàng)目下次遇到莫名其妙的刷新問(wèn)題先別急著懷疑工具打開(kāi)這個(gè)面板看一眼大概率能直接定位到問(wèn)題。