備通信標(biāo)準(zhǔn)化與集成實(shí)戰(zhàn))
AF框架第十二章主要解決的是設(shè)備層通信這件事。我把這一章從頭到尾過(guò)了一遍也順手在幾個(gè)實(shí)際項(xiàng)目里做了驗(yàn)證。先說(shuō)結(jié)論這一章的內(nèi)容比前面很多章節(jié)都實(shí)用如果你正在做S7-1500和第三方設(shè)備變頻器、機(jī)器人、儀表、上位機(jī)的通信對(duì)接這一章基本能把設(shè)計(jì)思路和關(guān)鍵代碼邏輯講清楚。整章看下來(lái)核心不是教你怎么寫某一條通信指令而是告訴你如何在AF框架的架構(gòu)下把通信這件事標(biāo)準(zhǔn)化、模塊化、可復(fù)用。這一章適合三類人一是已經(jīng)在用AF框架做項(xiàng)目的工程師想看看官方推薦的通信層怎么搭二是被各種設(shè)備通信協(xié)議搞得頭疼的PLC程序員想知道怎么用一套統(tǒng)一思路去應(yīng)對(duì)Modbus、TCP/IP、OPC UA這些常見(jiàn)方式三是剛接觸AF框架、讀到這一章有點(diǎn)懵的新手我會(huì)把里面的概念用大白話重新捋一遍順便補(bǔ)充一些原文檔里不會(huì)寫的實(shí)操細(xì)節(jié)。1. 這一章在AF框架中的定位1.1 從框架全局看第十二章的承上啟下AF框架Application Framework的全稱是西門子面向SIMATIC S7-1200/1500平臺(tái)的一套應(yīng)用開(kāi)發(fā)框架。它不是一套現(xiàn)成的程序而是一套約定包含數(shù)據(jù)結(jié)構(gòu)約定、功能塊劃分約定、狀態(tài)機(jī)模板和命名規(guī)范。框架前面章節(jié)解決的問(wèn)題分別是第一章到第五章講基礎(chǔ)數(shù)據(jù)類型和通用功能塊中間章節(jié)講報(bào)警管理、配方管理、數(shù)據(jù)記錄這些都是PLC內(nèi)部的功能組織。到了第十二章視角從內(nèi)部轉(zhuǎn)向外部。這一章講的是如何讓一個(gè)基于AF框架的PLC程序和PLC之外的設(shè)備、系統(tǒng)對(duì)話。放到整個(gè)框架里看這一章更像是一個(gè)收口章節(jié)——把前面建立的標(biāo)準(zhǔn)化數(shù)據(jù)結(jié)構(gòu)通過(guò)標(biāo)準(zhǔn)化的通信通道送到外部世界去。同時(shí)它又向下兼容了老項(xiàng)目的遷移需求很多用戶是從S7-300/400的老程序遷移過(guò)來(lái)的老程序里各功能塊直接調(diào)用通信指令到了新框架下必須改寫這一章就給出了改寫的標(biāo)準(zhǔn)路徑。翻譯這一章的時(shí)候我的一個(gè)明顯感受是作者對(duì)通信的定位非??酥啤H聫念^到尾沒(méi)有試圖把所有通信協(xié)議都講一遍而是盯著幾個(gè)核心場(chǎng)景周期性數(shù)據(jù)交換、非周期性命令傳遞、故障狀態(tài)上報(bào)。圍繞這三個(gè)場(chǎng)景去設(shè)計(jì)功能塊才是這章真正有價(jià)值的思路。1.2 第十二章為什么聚焦通信集成AF框架前面章節(jié)處理的數(shù)據(jù)比如報(bào)警消息、配方參數(shù)、生產(chǎn)統(tǒng)計(jì)如果只存在PLC內(nèi)部?jī)r(jià)值就少了一大半。這些數(shù)據(jù)最終要交給HMI顯示、交給MES系統(tǒng)記錄、交給變頻器去執(zhí)行、交給機(jī)器人去聯(lián)動(dòng)。所以第十二章必須回答一個(gè)問(wèn)題在AF框架的體系下PLC如何高效、可靠地完成這一層數(shù)據(jù)交換。這一章的翻譯難點(diǎn)也在這里西門子官方文檔中大量使用了英文縮寫和面向?qū)ο缶幊痰母拍畋热鏸nstance、interface、callback這類詞直接翻譯成實(shí)例接口回調(diào)很容易讓習(xí)慣了傳統(tǒng)LD梯形圖編程的工程師犯迷糊。我在翻譯時(shí)做了不少本土化處理把interface拆成功能塊的對(duì)外參數(shù)把callback解釋成通信完成后的通知機(jī)制這樣讀起來(lái)順很多。另外這一章有一個(gè)隱藏前提它假設(shè)你已經(jīng)在用AF框架的數(shù)據(jù)結(jié)構(gòu)了。比如框架里定義了統(tǒng)一的設(shè)備狀態(tài)數(shù)據(jù)類型這一章的通信功能塊就直接跟這種類型對(duì)接。如果你沒(méi)有用AF框架直接看這一章會(huì)覺(jué)得很多地方多此一舉——比如為什么通信功能塊非要帶一個(gè)請(qǐng)求隊(duì)列而不是直接來(lái)什么處理什么。理解了框架的全局設(shè)計(jì)才能理解這些看似多余的結(jié)構(gòu)。2. 通信架構(gòu)設(shè)計(jì)思路拆解2.1 為什么AF框架堅(jiān)持集中式通信管理傳統(tǒng)的PLC通信程序最常見(jiàn)的寫法是每個(gè)功能塊里面各自調(diào)用通信指令。比如控制變頻器的功能塊里直接寫Modbus通信指令讀取儀表的功能塊里直接寫串口通信指令。這種方式調(diào)試前期很快但項(xiàng)目一復(fù)雜就出問(wèn)題通信指令在同一個(gè)CPU里爭(zhēng)搶通信資源一個(gè)功能塊卡住其他功能塊的通信全部超時(shí)第三方設(shè)備做了更換你得把所有相關(guān)功能塊翻出來(lái)改。AF框架第十二章的設(shè)計(jì)思路是反過(guò)來(lái)的它把通信這件事從業(yè)務(wù)功能塊里抽離出來(lái)形成一層獨(dú)立的通信管理層。業(yè)務(wù)功能塊需要發(fā)送數(shù)據(jù)不是直接調(diào)用通信指令而是把數(shù)據(jù)放到一個(gè)統(tǒng)一的發(fā)送緩沖區(qū)然后由通信管理功能塊統(tǒng)一調(diào)度發(fā)送。反過(guò)來(lái)接收到的數(shù)據(jù)也由通信管理功能塊統(tǒng)一接收解析后放入接收緩沖區(qū)業(yè)務(wù)功能塊自己去取。我用做飯來(lái)打個(gè)比方傳統(tǒng)寫法是每個(gè)菜館自己雇人去進(jìn)貨各買各的堵在路上誰(shuí)也進(jìn)不來(lái)集中式通信管理是整個(gè)園區(qū)建了一個(gè)中央采購(gòu)中心各菜館把需求報(bào)上去采購(gòu)中心統(tǒng)一派車。單個(gè)菜館業(yè)務(wù)功能塊不再關(guān)心菜是哪兒買來(lái)的、怎么運(yùn)來(lái)的只管接貨讀接收緩沖區(qū)。這種設(shè)計(jì)的第一個(gè)好處是通信通道可以被多個(gè)業(yè)務(wù)功能塊復(fù)用。AF框架里一條通信連接比如一個(gè)TCP連接可以被多個(gè)功能塊輪流使用通過(guò)請(qǐng)求隊(duì)列仲裁誰(shuí)優(yōu)先級(jí)高誰(shuí)先發(fā)。第二個(gè)好處是通信故障的隔離。通信層單獨(dú)檢測(cè)連接狀態(tài)、重試次數(shù)、超時(shí)時(shí)間業(yè)務(wù)功能塊只需要讀取通信層的狀態(tài)字就知道當(dāng)前通信是否正常而不用自己處理底層錯(cuò)誤。2.2 三種典型通信方式的選型邏輯第十二章圍繞三種通信方式展開(kāi)Modbus TCP、TCP/IP自定義協(xié)議、OPC UA。章節(jié)里沒(méi)有直接說(shuō)什么情況下用哪種我從它的功能塊結(jié)構(gòu)上讀出了選型邏輯這里整理一下。Modbus TCP適合標(biāo)準(zhǔn)第三方設(shè)備的場(chǎng)景。只要設(shè)備支持Modbus TCP不管是ABB變頻器、森蘭變頻器還是各種儀表都可以用同一個(gè)功能塊接入。選它的理由是極低的對(duì)接成本——Modbus協(xié)議是公開(kāi)的、結(jié)構(gòu)簡(jiǎn)單的、幾乎所有工業(yè)設(shè)備都支持。但Modbus的缺點(diǎn)是數(shù)據(jù)結(jié)構(gòu)弱只能讀寄存器、線圈沒(méi)有復(fù)雜的類型系統(tǒng)也沒(méi)有設(shè)備自動(dòng)識(shí)別機(jī)制。TCP/IP自定義協(xié)議適合非標(biāo)設(shè)備或系統(tǒng)的場(chǎng)景比如和庫(kù)卡機(jī)器人的交互、和上位機(jī)的私有協(xié)議通信。這種情況Modbus覆蓋不了需要按對(duì)方協(xié)議文檔逐字節(jié)組幀、解析。AF框架在這一塊提供的價(jià)值是把幀的組裝和拆解標(biāo)準(zhǔn)化把協(xié)議部分留給工程師自己按需填寫。OPC UA適合信息化系統(tǒng)對(duì)接比如MES、SCADA、以及過(guò)程仿真軟件的通訊熱搜詞里提到的Process Simulate通過(guò)OPC UA與西門子PLC通訊就是典型場(chǎng)景。OPC UA的強(qiáng)項(xiàng)是信息建模數(shù)據(jù)帶語(yǔ)義不用像Modbus那樣每個(gè)地址都要查表對(duì)應(yīng)。代價(jià)是通信棧和配置都更重對(duì)PLC資源占用也更高。從章節(jié)的行文看作者對(duì)三種方式的態(tài)度不是哪個(gè)先進(jìn)用哪個(gè)而是哪把鑰匙開(kāi)哪把鎖。這正好也是我在實(shí)際項(xiàng)目中的選型原則。2.3 心跳、超時(shí)與數(shù)據(jù)一致性的處理翻譯第十二章的時(shí)候心跳這個(gè)詞反復(fù)出現(xiàn)。AF框架的通信功能塊里內(nèi)置了心跳機(jī)制PLC周期性向外發(fā)送一個(gè)遞增的計(jì)數(shù)值對(duì)方設(shè)備收到后若能正?;貜?fù)說(shuō)明鏈路活著如果連續(xù)幾次收不到對(duì)方的正?;貜?fù)通信層自動(dòng)標(biāo)記連接異常而不是繼續(xù)悶頭等數(shù)據(jù)。這個(gè)設(shè)計(jì)對(duì)工程現(xiàn)場(chǎng)的意義很大。很多現(xiàn)場(chǎng)通信問(wèn)題不是一次性完全斷掉而是間歇性丟包、超時(shí)、停頓。如果沒(méi)有心跳機(jī)制業(yè)務(wù)層接收到一半數(shù)據(jù)很可能拿著不完整的數(shù)據(jù)去執(zhí)行動(dòng)作這是非常危險(xiǎn)的。有了心跳檢測(cè)就算通信抖動(dòng)PLC至少知道當(dāng)前數(shù)據(jù)不可信可以切換到安全狀態(tài)。超時(shí)處理是另一個(gè)關(guān)鍵點(diǎn)。AF框架把所有通信請(qǐng)求都拆成請(qǐng)求—響應(yīng)配對(duì)每個(gè)請(qǐng)求發(fā)出后啟動(dòng)一個(gè)超時(shí)定時(shí)器。定時(shí)器到點(diǎn)未收到響應(yīng)該請(qǐng)求被標(biāo)記為失敗并進(jìn)入重試隊(duì)列重試超過(guò)設(shè)定次數(shù)通信功能塊向業(yè)務(wù)功能塊上報(bào)通信失敗狀態(tài)。這個(gè)模式保證了通信問(wèn)題永遠(yuǎn)不會(huì)無(wú)限期地阻塞業(yè)務(wù)邏輯——任何一次數(shù)據(jù)請(qǐng)求都必須在有限時(shí)間內(nèi)給出結(jié)論哪怕結(jié)論是失敗了。數(shù)據(jù)一致性這一塊章節(jié)里強(qiáng)調(diào)了一個(gè)容易被人忽略的點(diǎn)PLC和外部設(shè)備之間的數(shù)據(jù)交換不要直接把原始數(shù)據(jù)暴露給業(yè)務(wù)邏輯。AF框架的做法是設(shè)置一套鏡像區(qū)通信層把收到的數(shù)據(jù)先寫入鏡像區(qū)校驗(yàn)完整后再整體更新到業(yè)務(wù)可見(jiàn)的數(shù)據(jù)區(qū)。這樣做的好處是業(yè)務(wù)邏輯任何時(shí)候讀取到的數(shù)據(jù)都是完整的一幀數(shù)據(jù)不會(huì)出現(xiàn)前一半是新的后一半是舊的這類錯(cuò)位問(wèn)題。3. 核心功能塊詳解與實(shí)操要點(diǎn)3.1 通信功能塊的標(biāo)準(zhǔn)結(jié)構(gòu)第十二章給出的通信功能塊對(duì)外接口并不復(fù)雜大致分四類參數(shù)控制參數(shù)、狀態(tài)參數(shù)、數(shù)據(jù)區(qū)指針、協(xié)議相關(guān)參數(shù)??刂茀?shù)管什么時(shí)候通信和和誰(shuí)通信狀態(tài)參數(shù)管當(dāng)前通信狀態(tài)和最近一次錯(cuò)誤碼數(shù)據(jù)區(qū)指針指向?qū)嶋H要發(fā)送或接收的數(shù)據(jù)緩沖協(xié)議相關(guān)參數(shù)是地址、端口、從站號(hào)這類信息。我在翻譯這一章時(shí)對(duì)照過(guò)其他框架的通信功能塊設(shè)計(jì)AF的處理有一個(gè)明顯特征它不允許功能塊直接持有數(shù)據(jù)存儲(chǔ)區(qū)而是用指針引用外部數(shù)據(jù)區(qū)。很多新手第一次讀到這個(gè)設(shè)計(jì)會(huì)不理解覺(jué)得直接把數(shù)據(jù)放在功能塊內(nèi)部多省事。但從工程角度想指針引用的方式讓一個(gè)功能塊可以服務(wù)于多組數(shù)據(jù)。比如你和十個(gè)變頻器通信不需要建十個(gè)通信功能塊實(shí)例只要建一個(gè)通信功能塊實(shí)例然后在不同的時(shí)間點(diǎn)讓它分別指向不同變頻器的數(shù)據(jù)區(qū)。這個(gè)設(shè)計(jì)的另外一個(gè)好處是狀態(tài)機(jī)可以獨(dú)立運(yùn)行。AF框架的通信功能塊內(nèi)部是一個(gè)典型的狀態(tài)機(jī)空閑→建立連接→發(fā)送請(qǐng)求→等待響應(yīng)→解析數(shù)據(jù)→回到空閑。每一個(gè)狀態(tài)之間的切換條件都寫在表中現(xiàn)場(chǎng)出問(wèn)題的時(shí)候通過(guò)狀態(tài)字就能定位到卡在哪里排查效率高很多。注意使用指針引用數(shù)據(jù)區(qū)時(shí)務(wù)必保證數(shù)據(jù)區(qū)在PLC的保持性存儲(chǔ)區(qū)中并避免在功能塊退出后仍然操作已失效的數(shù)據(jù)區(qū)引用。AF框架對(duì)此有專門的數(shù)據(jù)區(qū)有效性檢查功能塊翻譯時(shí)我發(fā)現(xiàn)很多項(xiàng)目沒(méi)用上其實(shí)是個(gè)大隱患。3.2 參數(shù)傳遞與數(shù)據(jù)類型映射這一章有大量篇幅在講數(shù)據(jù)類型映射我一開(kāi)始覺(jué)得有點(diǎn)枯燥后來(lái)仔細(xì)看才發(fā)現(xiàn)這是實(shí)操中最容易出錯(cuò)的部分。AF框架的統(tǒng)一通信數(shù)據(jù)載體是字節(jié)數(shù)組。也就是說(shuō)不管外部設(shè)備是Modbus寄存器還是自定義協(xié)議最終進(jìn)入PLC后都被拆成字節(jié)放進(jìn)一個(gè)數(shù)組里??蚣茉偬峁┮惶子成湟?guī)則把這些字節(jié)按照項(xiàng)目定義的數(shù)據(jù)結(jié)構(gòu)解釋回來(lái)。比如一個(gè)雙字實(shí)數(shù)REAL在Modbus TCP上占了兩個(gè)寄存器映射進(jìn)字節(jié)數(shù)組后高字節(jié)在前還是低字節(jié)在前是靠字節(jié)順序參數(shù)控制的。我看到很多工程師在這里踩坑明明通信通了數(shù)據(jù)也能收到但數(shù)值不對(duì)或者小數(shù)點(diǎn)位置不對(duì)原因往往就是字節(jié)順序和數(shù)據(jù)類型的長(zhǎng)度沒(méi)配對(duì)。AF框架在功能塊里明確暴露了這兩個(gè)參數(shù)不允許開(kāi)發(fā)者猜。翻譯時(shí)我把這部分單獨(dú)拎出來(lái)做了注釋一定要先確認(rèn)對(duì)方設(shè)備的字節(jié)序西門子和大部分歐洲設(shè)備默認(rèn)高字節(jié)在前但有些儀表和第三方控制器默認(rèn)低字節(jié)在前這個(gè)不對(duì)齊后面全是糊涂賬。數(shù)據(jù)類型的長(zhǎng)度映射也值得注意。同樣是整數(shù)有BYTE8位、WORD16位、DWORD32位三種長(zhǎng)度。外部設(shè)備和PLC之間交換數(shù)據(jù)最穩(wěn)妥的做法是統(tǒng)一約定為WORD或DWORD長(zhǎng)度避免因?qū)Ψ桨l(fā)了16位PLC按32位解釋導(dǎo)致的高位填充垃圾數(shù)據(jù)。數(shù)據(jù)類型在字節(jié)數(shù)組中的占用常見(jiàn)來(lái)源易錯(cuò)點(diǎn)BOOL1 bit按位打包設(shè)備狀態(tài)位位偏移計(jì)算和文檔不一致BYTE1 字節(jié)小數(shù)值、命令碼無(wú)符號(hào)與有符號(hào)混亂WORD2 字節(jié)整數(shù)寄存器字節(jié)序顛倒REAL4 字節(jié)模擬量、溫度等數(shù)據(jù)來(lái)自兩個(gè)寄存器時(shí)高低字順序STRING變長(zhǎng)設(shè)備名稱、報(bào)警文本長(zhǎng)度前綴和終止符的差異3.3 與第三方設(shè)備對(duì)接的典型案例第十二章給了幾個(gè)對(duì)接案例我挑兩個(gè)和當(dāng)前項(xiàng)目最貼近的展開(kāi)講。第一個(gè)是西門子S7-1500與變頻器的Modbus TCP通信。AF框架的通信功能塊面向Modbus時(shí)把功能碼FC03讀保持寄存器、FC06寫單個(gè)寄存器、FC16寫多個(gè)寄存器作為顯式參數(shù)開(kāi)放。實(shí)際調(diào)試中遇到ABB變頻器時(shí)最典型的坑是AB變頻器的Modbus寄存器地址文檔里寫的是40xxx這是PLC習(xí)慣的地址表示法報(bào)文里實(shí)際地址要減一40001對(duì)應(yīng)地址0。S7-1500配合AF框架在組態(tài)時(shí)直接把地址做減一處理就能避免運(yùn)行時(shí)一次又一次的地址錯(cuò)誤提示。而森蘭變頻器SB200系列的Modbus地址是純16進(jìn)制寄存器地址不用減一兩者混用時(shí)特別容易搞混。AF框架的功能塊里把地址偏移量單獨(dú)做成了一個(gè)參數(shù)這一個(gè)參數(shù)解決了我在現(xiàn)場(chǎng)最頭疼的兼容問(wèn)題。第二個(gè)是西門子S7-1500與庫(kù)卡機(jī)器人的交互。這種場(chǎng)景一般走TCP/IP或ProfinetAF框架的處理方式是定義一套標(biāo)準(zhǔn)的命令—應(yīng)答數(shù)據(jù)包結(jié)構(gòu)。PLC發(fā)送命令數(shù)據(jù)包例如請(qǐng)求機(jī)器人移動(dòng)到位置A機(jī)器人執(zhí)行后回傳應(yīng)答數(shù)據(jù)包例如已到達(dá)位置A。章節(jié)里強(qiáng)調(diào)了指令去重的問(wèn)題——網(wǎng)絡(luò)通信會(huì)重發(fā)機(jī)器人可能收到兩條相同的移動(dòng)指令如果沒(méi)做去重機(jī)器人會(huì)重復(fù)執(zhí)行。AF框架里在數(shù)據(jù)包里加入命令序號(hào)字段PLC發(fā)出的第N條命令序號(hào)為N機(jī)器人只需記下最后一次執(zhí)行的序號(hào)序號(hào)重復(fù)則忽略。4. 移植到實(shí)際項(xiàng)目的完整過(guò)程4.1 從章節(jié)示例到項(xiàng)目代碼的翻譯路徑我拿自己最近做的一個(gè)實(shí)例說(shuō)明這一章怎么落地。項(xiàng)目要求一臺(tái)S7-1500作為主站和兩臺(tái)ABB變頻器Modbus TCP通信、一臺(tái)庫(kù)卡機(jī)器人TCP/IP通信、一套上位機(jī)系統(tǒng)OPC UA通信同時(shí)對(duì)接。第一步先按AF框架的結(jié)構(gòu)梳理誰(shuí)和誰(shuí)說(shuō)話。列一張通信矩陣圖每一條通信連接、對(duì)應(yīng)的設(shè)備類型、通信協(xié)議、數(shù)據(jù)交換周期、數(shù)據(jù)量大小、優(yōu)先級(jí)。這一步做完我心里就有底了——這相當(dāng)于第十二章里說(shuō)的通信需求分析是整個(gè)設(shè)計(jì)的地基。第二步確定通信功能塊的實(shí)例化數(shù)量。AF框架的官方建議是一條物理連接對(duì)應(yīng)一個(gè)通信功能塊實(shí)例。我的項(xiàng)目里兩臺(tái)ABB變頻器可以共用一條Modbus TCP連接所以用一個(gè)通信實(shí)例庫(kù)卡機(jī)器人單獨(dú)一條TCP連接單開(kāi)一個(gè)實(shí)例OPC UA走的是PLC內(nèi)置的OPC UA服務(wù)器功能AF框架主要配合做服務(wù)器側(cè)的地址空間映射不需要傳統(tǒng)意義上的通信實(shí)例。第三步配置數(shù)據(jù)區(qū)。把每一臺(tái)設(shè)備的發(fā)送數(shù)據(jù)區(qū)和接收數(shù)據(jù)區(qū)在PLC的數(shù)據(jù)塊里聲明好。數(shù)據(jù)區(qū)的大小要留足余量比如變頻器的運(yùn)行參數(shù)我預(yù)計(jì)只用到10個(gè)寄存器但我會(huì)配置20個(gè)寄存器的數(shù)據(jù)區(qū)多出來(lái)的部分是給以后擴(kuò)展用的。翻譯章節(jié)時(shí)看到一個(gè)觀點(diǎn)很認(rèn)可數(shù)據(jù)區(qū)一旦定好盡量在一個(gè)項(xiàng)目周期內(nèi)保持不變換地址的代價(jià)遠(yuǎn)大于多占幾個(gè)字節(jié)的存儲(chǔ)。第四步逐條填寫協(xié)議參數(shù)。Modbus TCP這邊填從站地址、寄存器起始地址、寄存器數(shù)量、字節(jié)順序TCP/IP這邊填機(jī)器人的IP和端口號(hào)、幀格式定義OPC UA這邊主要是建立服務(wù)器配置把需要開(kāi)放給上位機(jī)的變量掛到地址空間。第五步寫業(yè)務(wù)側(cè)的調(diào)用邏輯。業(yè)務(wù)功能塊在需要通信的時(shí)刻把數(shù)據(jù)寫入發(fā)送數(shù)據(jù)區(qū)然后把發(fā)送請(qǐng)求標(biāo)志置位。通信功能塊檢測(cè)到請(qǐng)求標(biāo)志從發(fā)送數(shù)據(jù)區(qū)取數(shù)發(fā)出報(bào)文收到應(yīng)答后把數(shù)據(jù)寫入接收數(shù)據(jù)區(qū)并清除請(qǐng)求標(biāo)志。整個(gè)過(guò)程業(yè)務(wù)代碼完全不用關(guān)心底層協(xié)議這和第二章說(shuō)的接口與實(shí)現(xiàn)分離一脈相承。4.2 與熱搜場(chǎng)景的交叉驗(yàn)證看那些經(jīng)典問(wèn)題怎么解熱搜詞里有一類高頻問(wèn)題我今天翻譯完第十二章突然感覺(jué)它們其實(shí)都是同一個(gè)答案的不同變體。這類問(wèn)題是西門子PLC與三菱變頻器RS485通訊S7-200 SMART與森蘭變頻器通信Modscan能讀串口數(shù)據(jù)但西門子組態(tài)軟件不能讀。先說(shuō)S7-200 SMART與三菱變頻器RS485通信。三菱變頻器的RS485協(xié)議和標(biāo)準(zhǔn)的Modbus RTU不完全一致特別是命令幀的CRC校驗(yàn)和站號(hào)定義都有廠商的特殊處理。AF框架雖然以S7-1500為主但它對(duì)通信功能塊的抽象思路是通用的把協(xié)議差異封裝進(jìn)功能塊內(nèi)部對(duì)外暴露的永遠(yuǎn)是請(qǐng)求數(shù)據(jù)、響應(yīng)數(shù)據(jù)、錯(cuò)誤碼這三樣。你要是用這個(gè)思路去看S7-200 SMART的通信就會(huì)很自然地想到把三菱特有的協(xié)議寫成一個(gè)獨(dú)立的協(xié)議轉(zhuǎn)換子程序和主通信邏輯分開(kāi)。這個(gè)思路比試圖在梯形圖里一行行調(diào)CRC要省心太多。另外一類問(wèn)題是第三方上位機(jī)讀不到PLC數(shù)據(jù)。比如KepServer連接S7-1500時(shí)讀不到數(shù)據(jù)或者Process Simulate通過(guò)OPC UA與西門子PLC無(wú)法交互。這類問(wèn)題十有八九不是通信層斷了而是數(shù)據(jù)模型沒(méi)有對(duì)上。AF框架在第十二章前面幾節(jié)強(qiáng)推的統(tǒng)一數(shù)據(jù)塊結(jié)構(gòu)恰好能幫你把給上位機(jī)看的數(shù)據(jù)單獨(dú)整理出來(lái)結(jié)構(gòu)清晰、變量名規(guī)范KepServer或OPC UA客戶端在瀏覽時(shí)一目了然。很多人不用框架的套路直接裸奔用DB塊地址亂七八糟上位機(jī)工程師連變量都找不到自然讀不到數(shù)據(jù)。我遇到過(guò)一次類似情況最后發(fā)現(xiàn)是DB塊沒(méi)有做非優(yōu)化訪問(wèn)外部OPC UA無(wú)法識(shí)別優(yōu)化訪問(wèn)的DB塊。這個(gè)細(xì)節(jié)AF框架相關(guān)的章節(jié)里反復(fù)提到過(guò)屬于典型的框架避免的坑。關(guān)于Modscan能讀串口數(shù)據(jù)但西門子組態(tài)軟件不能讀這一類問(wèn)題則是另一個(gè)維度。Modscan是通用的Modbus調(diào)試工具它讀數(shù)據(jù)不分地址區(qū)只要鏈路通就一定能讀到。但西門子組態(tài)軟件有明確的地址區(qū)劃分I區(qū)、Q區(qū)、M區(qū)、DB區(qū)如果你把儀表數(shù)據(jù)放到了一個(gè)和組態(tài)配置不一致的地址區(qū)Modscan照常能讀組態(tài)軟件卻找不到。解決思路還是那一套先建標(biāo)準(zhǔn)的數(shù)據(jù)映射表再配置組態(tài)軟件而不是配錯(cuò)了之后到處發(fā)帖問(wèn)。4.3 從S7-1200/1500延伸到S7-200 SMART的遷移技巧AF框架雖然主要針對(duì)S7-1200/1500但我發(fā)現(xiàn)很多人想把其中思路用到S7-200 SMART上因?yàn)?00 SMART做小型設(shè)備項(xiàng)目量很大。第十二章里的通信架構(gòu)思想可以用但具體實(shí)現(xiàn)要降級(jí)。S7-200 SMART的分區(qū)存儲(chǔ)和指令集都比1500簡(jiǎn)單沒(méi)法完全照搬AF的通信管理層鏡像數(shù)據(jù)區(qū)指針引用。我在幾個(gè)小項(xiàng)目里是這么做的把AF框架的集中式思路簡(jiǎn)化成兩個(gè)全局?jǐn)?shù)據(jù)塊一個(gè)通信子程序。全局?jǐn)?shù)據(jù)塊A存所有發(fā)送數(shù)據(jù)全局?jǐn)?shù)據(jù)塊B存所有接收數(shù)據(jù)通信子程序統(tǒng)一處理RS485或TCP外部設(shè)備的數(shù)據(jù)分發(fā)靠子程序里的索引表完成。這個(gè)簡(jiǎn)化版雖然少了AF的完整狀態(tài)機(jī)和自動(dòng)重試但在資源有限的CPU上跑得很穩(wěn)定而且保留了最核心的收益——業(yè)務(wù)代碼和通信代碼分離。翻譯章節(jié)時(shí)發(fā)現(xiàn)AF框架作者在開(kāi)篇其實(shí)說(shuō)過(guò)一句話大意是框架是為了讓代碼更清晰、更可維護(hù)而不是為了框架而框架。這句話放在S7-200 SMART的簡(jiǎn)化方案上非常合適我們借鑒的是思想不必糾結(jié)形似。5. 常見(jiàn)問(wèn)題與排查實(shí)錄5.1 通信失敗的三類典型原因這一章最后一部分結(jié)合我自己的調(diào)試經(jīng)歷把通信失敗的常見(jiàn)原因歸成三類。第一類是參數(shù)配置錯(cuò)誤。IP地址、端口、從站號(hào)、寄存器地址這一類看似簡(jiǎn)單的錯(cuò)誤反而最難查因?yàn)閳?bào)錯(cuò)不明顯。我的習(xí)慣是任何通信功能塊接入新設(shè)備第一件事不是看功能塊是否通信成功而是用一個(gè)通用調(diào)試工具比如Modscan直接對(duì)設(shè)備發(fā)報(bào)文先確認(rèn)設(shè)備本身沒(méi)問(wèn)題再回過(guò)來(lái)查PLC側(cè)的配置。這樣可以快速把問(wèn)題范圍縮小一半。第二類是通信資源沖突。PLC的通信資源是有限的S7-1500同時(shí)建立的TCP連接、Modbus連接、OPC UA會(huì)話數(shù)都有上限。項(xiàng)目里多個(gè)設(shè)備同時(shí)對(duì)接時(shí)如果連接數(shù)超過(guò)了CPU的許可范圍新連接會(huì)建立失敗但舊連接的異常未必會(huì)立刻暴露。這里要用第十二章通信狀態(tài)里的連接計(jì)數(shù)實(shí)時(shí)監(jiān)控已用連接數(shù)。第三類是PLC程序掃描周期與通信周期不匹配。如果CPU掃描周期遠(yuǎn)大于通信超時(shí)時(shí)間功能塊還沒(méi)來(lái)得及處理收到的數(shù)據(jù)超時(shí)標(biāo)志就先置位了。這種情況下通信本身是通的但邏輯處理不過(guò)來(lái)。AF框架提供的解決辦法是調(diào)整通信功能塊的調(diào)用位置——把它放到一個(gè)高優(yōu)先級(jí)的中斷OB里保證通信數(shù)據(jù)的處理不被普通的IO刷新延誤。癥狀可能原因快速驗(yàn)證方法解決動(dòng)作通信完全不通物理鏈路斷開(kāi)或參數(shù)配置錯(cuò)誤檢查網(wǎng)線指示燈、用調(diào)試工具直連設(shè)備排除物理問(wèn)題后逐項(xiàng)核對(duì)IP/端口/站號(hào)時(shí)通時(shí)斷通信資源沖突或電磁干擾查看通信狀態(tài)里的連接計(jì)數(shù)和錯(cuò)誤碼減少并發(fā)連接或加裝網(wǎng)絡(luò)隔離器數(shù)據(jù)能通但數(shù)值不對(duì)字節(jié)序或數(shù)據(jù)類型映射錯(cuò)誤用固定值回環(huán)測(cè)試發(fā)已知數(shù)看收到什么修正字節(jié)順序或調(diào)整數(shù)據(jù)類型長(zhǎng)度偶發(fā)超時(shí)掃描周期與通信周期不匹配比較CPU掃描周期和通信超時(shí)時(shí)間將通信功能塊移到中斷OB中執(zhí)行上位機(jī)讀不到數(shù)據(jù)數(shù)據(jù)塊優(yōu)化訪問(wèn)或地址區(qū)不匹配在上位機(jī)地址空間直接瀏覽PLC數(shù)據(jù)關(guān)閉優(yōu)化訪問(wèn)按模塊標(biāo)準(zhǔn)地址區(qū)重新映射5.2 通信數(shù)據(jù)錯(cuò)亂的深坑不是你錯(cuò)了是它自帶偏移這是我翻譯第十二章時(shí)最有共鳴的部分也是很多現(xiàn)場(chǎng)排查到深夜才發(fā)現(xiàn)的問(wèn)題。Modbus協(xié)議本身的寄存器地址是零基的但不同廠商的文檔習(xí)慣于用一基甚至四萬(wàn)系列的表示法。比如變頻器參數(shù)P100文檔里標(biāo)注Modbus地址為40100實(shí)際報(bào)文中的地址卻是99。這種偏移量問(wèn)題一個(gè)項(xiàng)目里有三四種變頻器每一種的偏移規(guī)則都略有不同光靠人工配對(duì)必然出錯(cuò)。AF框架的方案是在通信功能塊里內(nèi)置一個(gè)地址解碼規(guī)則從設(shè)備型號(hào)到實(shí)際地址的映射全部自動(dòng)化。換句話說(shuō)你以后在這個(gè)框架下接新設(shè)備只需要添加一條地址映射記錄剩下的計(jì)算全部由代碼完成。話雖如此我要提醒一句這類映射規(guī)則一定要在項(xiàng)目文檔里留痕否則過(guò)幾個(gè)月回來(lái)看代碼你會(huì)想不通為什么當(dāng)初40001被減了一。團(tuán)隊(duì)項(xiàng)目里這類魔法數(shù)字最容易引起交接時(shí)的互相傷害。5.3 功能塊實(shí)例化的內(nèi)存分配問(wèn)題第十二章末段討論了多個(gè)通信實(shí)例時(shí)的內(nèi)存規(guī)劃。這里有一個(gè)反直覺(jué)的點(diǎn)通信功能塊實(shí)例的數(shù)量不是越多越好因?yàn)槊恳粋€(gè)實(shí)例都會(huì)占用獨(dú)立的背景數(shù)據(jù)塊背景DB這塊內(nèi)存在CPU里是固定占用的哪怕該實(shí)例沒(méi)有建立通信。我在一個(gè)早期項(xiàng)目里就吃過(guò)虧S7-1500的CPU看著內(nèi)存很大覺(jué)得多開(kāi)幾個(gè)通信實(shí)例沒(méi)問(wèn)題結(jié)果程序做到后段發(fā)現(xiàn)MEM存儲(chǔ)區(qū)不夠用了還得回頭刪減實(shí)例數(shù)量重構(gòu)通信邏輯。后來(lái)學(xué)聰明了按AF框架文檔的建議一個(gè)通信實(shí)例覆蓋多條邏輯鏈路靠路由表區(qū)分不同設(shè)備而不是簡(jiǎn)單粗暴地一臺(tái)設(shè)備一個(gè)實(shí)例。這個(gè)操作在第十一章的后半段也提過(guò)第十二章算是把應(yīng)用細(xì)節(jié)補(bǔ)齊了。注意通信功能塊的實(shí)例化除了內(nèi)存開(kāi)銷還有掃描時(shí)間開(kāi)銷。每一個(gè)實(shí)例在每次掃描中都要執(zhí)行狀態(tài)機(jī)處理實(shí)例過(guò)多會(huì)拉長(zhǎng)程序掃描周期。評(píng)估實(shí)例數(shù)量時(shí)既要看內(nèi)存也要看CPU的循環(huán)時(shí)間預(yù)算。6. 翻譯筆記之外的實(shí)戰(zhàn)心得6.1 這一章最值得反復(fù)讀的三處如果把這一章壓縮成必須記住的三句話我的選擇是第一通信層必須和業(yè)務(wù)層解耦。哪怕你不是用AF框架也建議把通信的收發(fā)邏輯封裝成獨(dú)立的功能塊不要散落到各個(gè)業(yè)務(wù)塊里。我在后續(xù)項(xiàng)目中改變最大的地方就是這一條——程序結(jié)構(gòu)清晰了排查問(wèn)題的難度會(huì)降一個(gè)量級(jí)。第二通信狀態(tài)必須暴露給HMI。AF框架的通信功能塊帶有完整的狀態(tài)字未初始化、建立中、運(yùn)行正常、重試中、通信失敗這些狀態(tài)不要只在程序里用把它傳到HMI畫面上操作工能第一時(shí)間看到通信閃斷而不是等到數(shù)據(jù)異常了才發(fā)現(xiàn)。我自己被操作工問(wèn)過(guò)無(wú)數(shù)次為什么數(shù)據(jù)不動(dòng)了后來(lái)加上通信狀態(tài)顯示這類問(wèn)題幾乎絕跡。第三統(tǒng)一的數(shù)據(jù)區(qū)勝過(guò)散亂的通信指令。哪怕你只是做一個(gè)很小的設(shè)備只有一臺(tái)變頻器一條通信也建議單獨(dú)建一個(gè)數(shù)據(jù)塊存放通信數(shù)據(jù)而不是隨手放在某幾個(gè)M位和M字里。數(shù)據(jù)區(qū)統(tǒng)一調(diào)試時(shí)能少花一半時(shí)間交接時(shí)也能少挨一半罵。6.2 用AF框架第十二章避免改了上位機(jī)又忘了PLC的尷尬做通信項(xiàng)目的過(guò)程中最容易出現(xiàn)的問(wèn)題是上位機(jī)側(cè)改了地址但PLC側(cè)忘了同步。熱搜詞里反復(fù)出現(xiàn)KepServer、OPC UA、組態(tài)軟件連不上PLC等問(wèn)題大多和這種兩側(cè)不同步有關(guān)。AF框架在第十二章給出的解法是把PLC對(duì)外通信的數(shù)據(jù)全部集中到一個(gè)通信映射區(qū)上位機(jī)和PLC約定只通過(guò)這個(gè)映射區(qū)交換數(shù)據(jù)PLC側(cè)其他任何變量都不直接對(duì)上位機(jī)開(kāi)放。這樣改地址時(shí)只需要改映射區(qū)里的一條記錄PLC程序和上位機(jī)配置同步修改即可大大減少只改了一頭的概率。我在實(shí)際項(xiàng)目中用這個(gè)方法做得比較徹底映射區(qū)里連注釋都寫上此地址與上位機(jī)綁定修改必須通知上位機(jī)工程師。這樣做看起來(lái)有點(diǎn)機(jī)械但在多人協(xié)作的項(xiàng)目里這是最不依賴個(gè)人記憶的可靠方案。6.3 翻譯視角的補(bǔ)充英德原始文檔里那些翻譯不出來(lái)的坑這一章的英文原版和中文習(xí)慣很大的一個(gè)差異是英文里的configuration和parameter在原文里經(jīng)常混用。翻譯到中文時(shí)如果都翻成參數(shù)會(huì)掩蓋兩者的區(qū)別。我在處理時(shí)做了區(qū)分configuration翻成組態(tài)指設(shè)備級(jí)的參數(shù)集合如通信初始化配置parameter翻成參數(shù)指運(yùn)行過(guò)程中可以動(dòng)態(tài)調(diào)整的量。這個(gè)區(qū)分很重要因?yàn)锳F框架里通信功能塊的組態(tài)是在下載程序前定好的而參數(shù)可以在HMI上運(yùn)行時(shí)修改。如果概念混在一起新手很容易在運(yùn)行時(shí)盲目修改組態(tài)項(xiàng)導(dǎo)致功能塊重新初始化通信閃斷。另外德軍原版里很多動(dòng)詞的語(yǔ)義比英文復(fù)雜一層翻譯成英文本身就已經(jīng)丟信息。比如überwachen這個(gè)詞英文翻成monitor中文再翻成監(jiān)視三重翻譯下來(lái)原文里帶有主動(dòng)干預(yù)含義的監(jiān)視這個(gè)信息就丟了。AF框架里的很多監(jiān)視功能塊其實(shí)不只是監(jiān)視還包含超限自動(dòng)修正的含義。我在翻譯時(shí)會(huì)在這類詞后面加括號(hào)備注原文提醒自己也是提醒讀者不要小看這些詞義差異它直接決定你理解功能塊的行為邊界。6.4 關(guān)于深入學(xué)習(xí)這一章的建議如果你決定啃下AF框架第十二章并實(shí)際用起來(lái)我給三條學(xué)習(xí)路徑的建議。第一先搭硬件環(huán)境再讀文檔。沒(méi)有實(shí)際PLC和第三方設(shè)備或者仿真軟件讀這一章很容易覺(jué)得抽象。哪怕你只有一臺(tái)S7-1500本機(jī)也可以先建兩個(gè)通信功能塊做回環(huán)測(cè)試PLC自己發(fā)自己收把整個(gè)通信流程跑通再去看書本里的擴(kuò)展內(nèi)容?;丨h(huán)通了后面的事情都順理成章。第二帶著什么時(shí)候用得上去讀。這一章每一節(jié)解決一類問(wèn)題。你在做上位機(jī)對(duì)接就重點(diǎn)看OPC UA那幾節(jié)你在做變頻器通信就重點(diǎn)看Modbus那幾節(jié)在做機(jī)器人聯(lián)動(dòng)重點(diǎn)看TCP/IP那幾節(jié)。工作驅(qū)動(dòng)型的閱讀比從頭到尾通讀效率高很多。第三把這一章和AF框架里的報(bào)警管理、配方管理章節(jié)聯(lián)動(dòng)起來(lái)看。你會(huì)慢慢發(fā)現(xiàn)通信只是手段標(biāo)準(zhǔn)化的數(shù)據(jù)在系統(tǒng)里流動(dòng)才是目的。第十二章在整本書里不孤立它和前后章節(jié)一起構(gòu)成了西門子這套框架的完整閉環(huán)。這就是從會(huì)用一個(gè)功能塊到會(huì)搭一個(gè)可維護(hù)系統(tǒng)的關(guān)鍵一步。