議的在線監(jiān)控網(wǎng)關方案:從輪詢機制到數(shù)據(jù)采集實踐)
先別急著談技術選型說說我當時為什么一定要做這個基于Modbus的在線監(jiān)控網(wǎng)關方案。工廠改造那陣子現(xiàn)場設備品牌雜得很PLC有西門子的、臺達的儀表有七八種不同協(xié)議的變頻器更是國產(chǎn)進口混著來。你要是每個設備單獨拉一套監(jiān)控軟件光驅動就夠你喝一壺的。但也別慌這些設備里絕大多數(shù)都留了一個統(tǒng)一的“后門”——Modbus通訊接口。不管是RS485走Modbus RTU還是網(wǎng)口走Modbus TCP只要把這個口子利用好就能用一個網(wǎng)關把所有設備的數(shù)據(jù)統(tǒng)一采集上來再轉發(fā)到上層監(jiān)控平臺。我做的這個方案本質上就是一臺邊緣計算網(wǎng)關加一套數(shù)據(jù)采集轉發(fā)服務用Modbus協(xié)議把分散在各車間的設備數(shù)據(jù)匯聚起來再通過MQTT或者HTTP接口推到在線監(jiān)控平臺。這套方案解決的最大痛點就是不用挨個設備找廠商要私有協(xié)議不用給每臺設備單獨配上位機軟件一套網(wǎng)關通吃現(xiàn)場所有帶Modbus接口的設備。文章的后半部分我會把協(xié)議適配、輪詢策略、數(shù)據(jù)建模、斷線重連這些核心細節(jié)全部拆開講包括參數(shù)怎么定、坑在哪里、現(xiàn)場怎么調(diào)非常適合正在做設備數(shù)據(jù)采集、產(chǎn)線數(shù)字化改造的朋友參考也適合剛接觸Modbus協(xié)議、想快速搭一套可落地監(jiān)控系統(tǒng)的開發(fā)者。1. 內(nèi)容整體設計與思路拆解1.1 為什么是Modbus而不是OPC UA或者MQTT聊在線監(jiān)控其實繞不開一個底層問題數(shù)據(jù)從哪來用什么方式拿。我之前見過不少團隊一上來就要上OPC UA覺得先進、功能強、安全。但到現(xiàn)場一看老設備根本不支持要么加網(wǎng)關轉換要么換儀表成本直接翻好幾倍。對于大多數(shù)工廠來說Modbus依然是覆蓋度最高的協(xié)議從幾塊錢的溫度傳感器到幾十萬的進口設備十有八九都帶Modbus接口。這個方案選擇Modbus還有一個非?,F(xiàn)實的理由調(diào)試點位極其方便。Modbus的報文是明文寄存器讀寫用Modbus Poll、Modbus Slave這類工具就能直接對著設備調(diào)試地址對不上分分鐘就能查出來。不像某些私有協(xié)議還得逆向抓包分析一個點位半天都調(diào)不通。但我也得說句公道話Modbus本身沒有主動上報能力全靠主站一遍遍輪詢。所以網(wǎng)關方案里輪詢策略設計得合不合理直接決定了系統(tǒng)能不能在設備數(shù)量多的時候扛得住。1.2 方案整體架構是怎么搭的這套在線監(jiān)控網(wǎng)關方案我把它分成三層采集層網(wǎng)關通過RS485總線或者以太網(wǎng)口按照Modbus RTU/TCP協(xié)議定時輪詢現(xiàn)場設備讀取寄存器數(shù)據(jù)。轉發(fā)層網(wǎng)關內(nèi)部跑數(shù)據(jù)采集服務把拿到的原始寄存器值按照設備點表做解析、換算、單位轉換然后整理成統(tǒng)一格式的JSON數(shù)據(jù)。應用層通過MQTT或HTTP接口把數(shù)據(jù)推送到在線監(jiān)控平臺實現(xiàn)實時曲線、歷史查詢、異常告警、大屏展示。網(wǎng)關硬件我用的是一臺工業(yè)級邊緣網(wǎng)關雙串口加雙網(wǎng)口支持DC 9-36V寬壓供電。選這個型號不是因為它貴而是因為它抗干擾能力強能在車間那種電機啟停頻繁、電磁環(huán)境惡劣的場合穩(wěn)定跑。軟件部分采集服務我選的Node-RED當然你也可以用Python寫個守護腳本后面我詳細說但Node-RED做原型驗證和后期維護確實太方便了。1.3 選型時需要考慮的幾個重要問題在定方案之前有幾個關鍵問題必須想清楚否則后面返工很麻煩。現(xiàn)場設備分布和通訊距離。RS485總線理論傳輸距離是1200米實際用下來超過800米就得考慮加中繼器。如果你的設備分布在不同車間、不同樓層最好是每層放一臺采集網(wǎng)關再通過網(wǎng)絡統(tǒng)一上送而不是硬拉一條超長RS485總線。采集點位的數(shù)量和實時性要求。Modbus是輪詢機制網(wǎng)關向每臺設備發(fā)起請求設備應答一來一回是有時間開銷的。假設一臺設備有20個點位單次輪詢耗時100ms那光這一臺設備就得2秒鐘才能采完一輪。點位太多了實時性必然下降。我一般建議單臺網(wǎng)關監(jiān)控不超過32臺設備采樣周期在1-5秒之間比較合理。斷線重連和數(shù)據(jù)補傳策略。車間環(huán)境不可能保證網(wǎng)絡100%穩(wěn)定網(wǎng)關和設備之間、網(wǎng)關和平臺之間任何一段斷了數(shù)據(jù)都會丟。所以選型時一定要確認網(wǎng)關支持本地緩存和斷線補傳不然網(wǎng)絡一抖動就丟數(shù)據(jù)后期做數(shù)據(jù)分析的時候你會非常痛苦。2. 核心細節(jié)解析與實操要點2.1 Modbus協(xié)議的現(xiàn)場理解和寄存器分類要做Modbus采集協(xié)議本身還是得稍微過一遍不用背報文但要知道數(shù)據(jù)存在哪里。Modbus協(xié)議里數(shù)據(jù)主要存在四個區(qū)域線圈Coil、離散輸入Discrete Input、保持寄存器Holding Register、輸入寄存器Input Register。前兩個是按位操作的單位是bit一般用來讀設備啟停狀態(tài)、報警狀態(tài)后兩個是16位為一個寄存器用來存模擬量數(shù)據(jù)比如溫度、壓力、頻率、電流這些。其中線圈支持讀和寫離散輸入只支持讀保持寄存器支持讀和寫輸入寄存器只支持讀。這個劃分特別重要因為你在做監(jiān)控的時候有的數(shù)據(jù)是要讀出來展示有的數(shù)據(jù)可能還需要遠程下發(fā)控制比如遠程啟停設備、遠程修改設定值。這就得認清楚你要控制的那個參數(shù)到底在哪個區(qū)域功能碼用錯了設備直接給你回異常碼。常見的功能碼我需要現(xiàn)場用得最多的幾個功能碼含義使用場景0x01讀線圈讀取設備啟停狀態(tài)、運行狀態(tài)0x02讀離散輸入讀取設備故障輸入、開關狀態(tài)0x03讀保持寄存器讀取設定值、運行參數(shù)、累計量0x04讀輸入寄存器讀取實時測量值如溫度、壓力0x05寫單個線圈遠程啟停設備0x06寫單個寄存器遠程修改設定值0x10寫多個寄存器批量下發(fā)參數(shù)2.2 串口參數(shù)和報文解析的實操細節(jié)Modbus RTU走的是RS485串口現(xiàn)場調(diào)通的第一步就是串口參數(shù)要配對。波特率、數(shù)據(jù)位、校驗位、停止位這四個參數(shù)必須和從站設備保持一致否則報文發(fā)過去就是雞同鴨講。最常見的配置是9600波特率、8數(shù)據(jù)位、無校驗、1停止位簡寫就是9600 8N1。但不同廠家默認值不一樣有的設備出廠是19200還有的是9600 8E1偶校驗所以你接上一臺新設備第一件事就是查它的說明書確認串口參數(shù)不要想當然。報文層面Modbus RTU的幀結構是從站地址1字節(jié) 功能碼1字節(jié) 數(shù)據(jù)N字節(jié) CRC校驗2字節(jié)。CRC校驗是Modbus RTU特有的低字節(jié)在前。如果你自己寫解析代碼CRC算不對設備數(shù)據(jù)就永遠解析不出來。我自己在方案里直接把Modbus的解析邏輯封裝成了函數(shù)庫從站地址、功能碼、起始地址、寄存器數(shù)量全部做成配置項。這樣現(xiàn)場加設備就只是改配置不用改代碼后面維護省了很多事。2.3 數(shù)據(jù)采集服務的實現(xiàn)思路網(wǎng)關側的數(shù)據(jù)采集服務我強烈建議用Node-RED來做。很多人一聽可視化編程就覺得不靠譜但實際上Node-RED在工業(yè)物聯(lián)網(wǎng)場景里已經(jīng)非常成熟了它對Modbus有現(xiàn)成的節(jié)點支持你只需要配置好串口或TCP連接然后把輪詢邏輯拖出來就能跑。如果不想用Node-RED用Python寫采集服務也完全可行核心就是用pymodbus庫。我提供一下我當時的設計思路啟動時加載設備點表配置包括設備ID、串口參數(shù)、寄存器地址、數(shù)據(jù)類型、縮放系數(shù)。按照設備分組用獨立的異步任務循環(huán)執(zhí)行輪詢。每輪輪詢結束把采集結果發(fā)布到MQTT主題主題按設備編碼命名。采集任務之間用信號量控制并發(fā)避免多個串口請求同時發(fā)送導致數(shù)據(jù)沖突。2.4 告警機制的簡單實現(xiàn)在線監(jiān)控不只是看數(shù)據(jù)更是要能發(fā)現(xiàn)問題。我在方案里做了一個輕量級的告警引擎支持兩種告警規(guī)則閾值告警比如某臺空壓機的排氣溫度超過85度就觸發(fā)告警。狀態(tài)告警比如設備通訊斷開、連續(xù)N次輪詢無響應說明設備離線了也要告警。告警觸發(fā)后通過釘釘機器人或者微信企業(yè)號推送給對應負責人。這里我不建議用短信費用高而且很多時候現(xiàn)場值班人員看微信比看短信還勤。3. 實操過程與核心環(huán)節(jié)實現(xiàn)3.1 設備點表的整理和規(guī)劃做在線監(jiān)控網(wǎng)關第一步不是接線路而是整理點表。點表就是一張表列清楚每臺設備有哪些數(shù)據(jù)要采集、數(shù)據(jù)存在哪個地址、什么類型、單位是什么、怎么換算。點表整理清楚了后面寫配置也好調(diào)試也好都能省很多力。我拿一個實際項目舉例現(xiàn)場有12臺注塑機每臺設備需要采集的數(shù)據(jù)包括運行狀態(tài)線圈地址0故障報警離散輸入地址0當前模溫輸入寄存器地址0單位0.1度需要除以10當前壓力輸入寄存器地址1單位0.1MPa需要除以10累計產(chǎn)量保持寄存器地址10-1132位無符號整數(shù)高16位在前這個點表整理好之后你在網(wǎng)關里的配置就一目了然。每個數(shù)據(jù)項對應一個數(shù)據(jù)點ID比如INJ-001-RUN代表1號注塑機運行狀態(tài)INJ-001-TEMP代表1號注塑機模溫。平臺端展示的時候直接用這些數(shù)據(jù)點ID做映射就行。注意寄存器地址的單位是“寄存器號”不是字節(jié)。32位數(shù)據(jù)占兩個寄存器64位占四個。而且不同廠家對于32位數(shù)據(jù)的字節(jié)序定義不一樣有的高16位在前有的低16位在前一定要通過實際讀取驗證后再定配置。3.2 Modbus RTU現(xiàn)場接線與通訊測試接線這塊雖然沒有多復雜但細節(jié)決定成敗。RS485通訊用兩根線A和B也叫D和D-接線的時候特別注意A接A、B接B不要交叉。很多現(xiàn)場調(diào)試不通最后發(fā)現(xiàn)就是A/B接反了報文發(fā)出去設備根本沒收到??偩€兩端需要接120歐姆終端電阻。如果通訊距離短、設備少不接可能也能跑但設備多了、距離長了不接終端電阻會出現(xiàn)信號反射導致通訊時好時壞。我建議總線兩端各接一個終端電阻別省這個事。接好線之后先用Modbus Poll工具熱搜詞里也有人問這個的密鑰其實官方有試用版?zhèn)€人調(diào)試用足夠了正式用建議買授權也不貴測試一下通訊。把串口參數(shù)填進去從站地址填1功能碼選03起始地址填0寄存器數(shù)量填10點擊連接如果能看到數(shù)據(jù)在跳動說明通訊鏈路通了。Modbus Poll是主站模擬工具還有一個配套的Modbus Slave是從站模擬工具。調(diào)試的時候你可以用Modbus Slave模擬一臺設備用Modbus Poll或者你自己的采集服務去讀它先把雙方邏輯調(diào)通再接真實設備這樣能大大縮短調(diào)試時間。3.3 MQTT數(shù)據(jù)上云和平臺展示數(shù)據(jù)到了網(wǎng)關解析成標準JSON格式之后下一步就是推送到在線監(jiān)控平臺。MQTT是物聯(lián)網(wǎng)場景里最常見的消息協(xié)議網(wǎng)關作為MQTT客戶端把采集數(shù)據(jù)發(fā)布到特定主題平臺端訂閱這些主題實時入庫。我推薦用EMQX作為MQTT Broker開源版部署簡單性能也夠用。平臺端如果用現(xiàn)成的物聯(lián)網(wǎng)平臺比如ThingsBoard那它自帶MQTT接入能力配置一下就能把數(shù)據(jù)展示成大屏看板。如果不想用現(xiàn)成平臺自己寫個后端定時從MQTT拉數(shù)據(jù)入庫前端用ECharts畫曲線也完全可行。關鍵一點是數(shù)據(jù)入庫的時候要帶好設備編碼、數(shù)據(jù)點ID、時間戳三個字段缺一不可。設備編碼用來定位是哪臺設備數(shù)據(jù)點ID用來定位是哪個參數(shù)時間戳用來定位是哪一刻的數(shù)據(jù)。沒有時間戳的歷史數(shù)據(jù)就是一堆垃圾。3.4 輪詢參數(shù)的計算和優(yōu)化輪詢周期是多長很多新手上來直接設100毫秒覺得越快越好。實際上這要看設備能夠承受的通訊頻率。有些老PLC的Modbus通訊處理能力很弱你高頻輪詢它它反而會通訊超時甚至影響PLC本身的掃描周期。我一般按這個思路來算單臺設備數(shù)據(jù)讀取耗時 請求發(fā)送時間 設備處理時間 響應返回時間RS485在9600波特率下1個字節(jié)大約1ms讀10個寄存器請求幀8字節(jié)響應幀25字節(jié)左右加上設備處理時間單次大約40-60ms。如果總線上掛了10臺設備每臺讀一次一輪下來大概0.5秒。那輪詢周期就設置在1-2秒既能保證實時性又不會給總線造成壓力。如果監(jiān)控平臺需要每秒鐘刷新一次數(shù)據(jù)單臺網(wǎng)關下面的設備就不能太多或者要分多條RS485總線每條總線掛一部分設備并行輪詢。4. 常見問題與排查技巧實錄4.1 Modbus Poll報02 Illegal Data Address怎么處理熱詞里有人專門搜“modbus poll 02 illegal”這個問題現(xiàn)場出現(xiàn)率極高。02是Modbus的異常碼含義是“非法的數(shù)據(jù)地址”說白了就是你請求的寄存器地址在這個設備上不存在。排查思路就三步第一確認你的起始地址填對了。很多設備的寄存器地址在文檔里是“40001”這種PLC風格的地址對應協(xié)議里的地址其實是0差了一個偏移。你在工具里填的時候要么直接填協(xié)議地址要么注意工具軟件里有沒有加1的選項。第二確認寄存器數(shù)量別越界。你從地址0開始讀數(shù)量填100但設備實際只有50個寄存器超過的部分就會報02。第三確認你用的功能碼對應正確的數(shù)據(jù)區(qū)域。比如設備的溫度數(shù)據(jù)在輸入寄存器你讀保持寄存器肯定讀不到反過來你要寫設定值寫的是保持寄存器卻用讀線圈的功能碼去操作也會報錯。4.2 能Ping通但Modbus TCP不通是什么原因熱詞里也有“modbus tcp 能pin通,但modscan不通什么原因”這個問題我也遇到過。Ping通說明網(wǎng)絡層是通的Modbus TCP不通問題基本出在端口或者設備本身。Modbus TCP的默認端口是502很多設備支持自定義端口你得確認設備上的端口到底是多少。另外有些設備的Modbus TCP服務默認是關閉的需要在設備參數(shù)里打開或者需要配置訪問白名單。還有一種情況是防火墻攔了502端口。Windows自帶的防火墻有時候會攔掉來自局域網(wǎng)的502訪問排查時可以先臨時關掉防火墻試試確認是防火墻問題再添加放行規(guī)則。最后還有一種可能就是設備支持多個連接但連接數(shù)被占滿了。Modbus TCP允許同時建立的連接數(shù)有限如果之前有調(diào)試工具或者監(jiān)控軟件一直連著沒斷開新連接就會失敗。這個用TCP工具看連接狀態(tài)就能發(fā)現(xiàn)。4.3 數(shù)據(jù)亂跳、偶爾讀到0或者負數(shù)怎么辦Modbus讀到亂數(shù)據(jù)多半是數(shù)據(jù)類型配錯了。比如設備存的是16位有符號整數(shù)你按無符號整數(shù)解析負值就會變成一個很大的正數(shù)設備存的是32位浮點數(shù)你按兩個16位整數(shù)解析得到的數(shù)就是亂的。解決辦法是讀幾個寄存器的原始值用計算器按16進制轉10進制、按浮點數(shù)格式轉一下看看和設備實際顯示值對不對得上。對得上說明解析方式正確對不上就換字節(jié)序、換數(shù)據(jù)類型再試。至于偶爾讀到0可能是輪詢和設備正在更新的數(shù)據(jù)撞上了。有些設備在更新內(nèi)部數(shù)據(jù)時如果你正好去讀讀到的是半新半舊的數(shù)據(jù)。這種情況可以在采集服務里做一次數(shù)據(jù)有效性校驗比如溫度值如果超出-50到200度的物理范圍就丟棄這一幀等下一輪再讀。4.4 網(wǎng)關長期運行后數(shù)據(jù)不更新了系統(tǒng)跑了一兩個月突然發(fā)現(xiàn)平臺上某個設備的數(shù)據(jù)不刷了但設備本身明明是好的。這個我在線下項目里排查過原因基本就兩類。第一類是網(wǎng)關側Modbus通訊線程卡死了。設備長時間無響應如果超時處理寫得不完善通訊狀態(tài)機可能一直卡在等待響應的狀態(tài)后續(xù)請求全部發(fā)不出去。解決辦法是給每次請求都加超時時間超時后強制重置連接。我一般設超時為500ms連續(xù)超時3次就斷開重連。第二類是MQTT連接斷開了但沒重連。網(wǎng)關和MQTT Broker之間的長連接中間經(jīng)過交換機或者路由器偶爾會有連接假死的情況——TCP連接看似還在實際數(shù)據(jù)已經(jīng)不走了。解決方法是啟用MQTT的KeepAlive機制客戶端定時發(fā)心跳包服務端在超時未收到心跳時主動斷開連接客戶端隨即發(fā)起重連。我在網(wǎng)關服務里加了一個看門狗邏輯每隔5分鐘檢查一次MQTT連接狀態(tài)和最近數(shù)據(jù)更新時間如果發(fā)現(xiàn)超過2分鐘沒有新數(shù)據(jù)上報就自動重啟采集任務實測下來系統(tǒng)穩(wěn)定性提升非常明顯。4.5 調(diào)試小工具推薦最后分享一下我平時調(diào)試Modbus網(wǎng)關方案的工具箱工具用途Modbus Poll主站模擬讀取從站設備數(shù)據(jù)時首選Modbus Slave從站模擬調(diào)試采集服務時當假設備VSPD虛擬串口電腦上虛擬出一對互聯(lián)串口方便調(diào)試串口程序MQTTXMQTT客戶端調(diào)試工具查看消息發(fā)布訂閱非常方便Wireshark抓包分析Modbus TCP報文一眼就能看清這里有個小技巧調(diào)試RS485總線上的設備時我經(jīng)常用USB轉RS485模塊把設備掛到電腦上用Modbus Poll直接讀。如果設備數(shù)量多那就在每個設備旁邊臨時接一個RS485轉RJ45的轉換器把總線拓撲理清楚再統(tǒng)一接到網(wǎng)關會輕松很多。5. 關于協(xié)議深度測試的幾點補充做在線監(jiān)控網(wǎng)關不僅要讓正常情況跑得通還要考慮異常情況怎么處理?,F(xiàn)場調(diào)試完一塊邏輯后一定要模擬設備掉線、寄存器越界、數(shù)據(jù)異常等場景驗證網(wǎng)關和平臺的容錯能力。很多項目的需求書上都會寫“系統(tǒng)應具備高可靠性”但可靠性真不是靠寫代碼寫出來的是靠一輪一輪故障測試測出來的。我習慣的做法是每個通訊周期增加一個狀態(tài)計數(shù)連續(xù)幾個周期通訊失敗就標記設備離線同時觸發(fā)告警恢復后自動清除離線狀態(tài)。這樣網(wǎng)絡抖動的時候不會誤報但設備真的掛了也能及時通知到人。再提一個LabVIEW讀Modbus的場景熱詞里也有“l(fā)abview 讀modbus rtu從站信息”。LabVIEW有現(xiàn)成的Modbus庫用事件結構加定時器做輪詢就能實現(xiàn)底層原理和我上面講的完全一樣只不過采集程序跑在PC上而不是網(wǎng)關上。如果你只是做實驗室驗證或者小規(guī)模監(jiān)控用LabVIEW完全可以但現(xiàn)場環(huán)境惡劣、要求長期穩(wěn)定運行的場景還是建議用工業(yè)網(wǎng)關。這套基于Modbus的在線監(jiān)控網(wǎng)關方案我實際部署到產(chǎn)線之后最大的感受就是方案本身不復雜難的是把每一個細微的環(huán)節(jié)做成可配置、可維護、可故障恢復的機制。Modbus協(xié)議像一根針把散落的設備串了起來網(wǎng)關像大腦把枯燥的寄存器數(shù)據(jù)變成了業(yè)務價值。如果你正在做類似的數(shù)據(jù)采集改造別貪大求全先把單臺設備的通訊和解析跑通再擴展到整條產(chǎn)線穩(wěn)扎穩(wěn)打比什么都重要。最后再分享一個小技巧所有設備的通訊參數(shù)和點表配置一定要用同一個配置文件統(tǒng)一管理現(xiàn)場加設備、改參數(shù)改完配置重啟服務就生效這比每次去改代碼重新部署要省一百倍的時間。