議到實戰(zhàn)調(diào)試全指南)
1. 方案背景與選型思路為什么用Modbus-RTU拖匯川伺服先說一個我自己的判斷不是所有伺服現(xiàn)場都值得上EtherCAT也不是所有項目都有條件用PROFINET。很多中小型單機設備、舊產(chǎn)線改造、或者“PLC加兩三臺軸”的工況用Modbus-RTU反而是最省事、最穩(wěn)妥的路線。我接手過一臺老式包裝機PLC是西門子S7-1200伺服用的是匯川MS1H4系列現(xiàn)場沒有PN從站模塊也沒有額外預算上總線耦合器最后就是靠驅(qū)動器自帶的RS-485口跑Modbus-RTU把位置和狀態(tài)全部拉進了博途。匯川伺服對Modbus-RTU的支持其實很完整。大部分匯川伺服驅(qū)動器都內(nèi)置了RS-485通訊口支持標準的03讀保持寄存器、06寫單個寄存器、10十六進制0x10寫多個寄存器等功能碼。這意味著你完全不用額外買通訊卡一根雙絞線就能把PLC和伺服串起來。相比EtherCAT動輒幾百上千的從站模塊費用Modbus-RTU的硬件成本幾乎可以忽略而且調(diào)試思路非常直觀——你能在電腦上用一個串口調(diào)試助手把每一個指令都看得清清楚楚。當然Modbus-RTU不是萬能的。它只能實現(xiàn)“間歇式”的主從問答做不到EtherCAT那種同步性。如果你的項目要求多軸插補、高速位置同步、或者周期在1ms以內(nèi)的實時控制那直接上EtherCAT或PROFINET IRT別糾結。但如果只是單軸定位、速度給定、狀態(tài)讀取或者對同步要求不苛刻的場合Modbus-RTU完全能打而且后期維護成本低車間電工也能看懂。寫在前面幾個核心結論避免你走彎路通訊角色上西門子PLC永遠做主站匯川伺服做從站這是定死的不存在對調(diào)的情況。幀結構不搞清楚后面所有配置都是空中樓閣CRC算錯一個字節(jié)伺服就給你回個異常碼。匯川伺服側(cè)的通訊參數(shù)組站地址、波特率、數(shù)據(jù)格式和西門子側(cè)必須嚴格一致“9600,8,N,1”這五個字符一個都不能錯。編碼器線數(shù)262144這個數(shù)值它是編碼器硬件分辨率不是通訊參數(shù)原樣保留就對了不要試圖去改。這篇文章我從Modbus-RTU幀結構講起一路講到博途里面的MB_COMM_LOAD和MB_MASTER組態(tài)最后把我的踩坑記錄和排查套路也整理出來。適合新手照著一步步做也適合給那些“通訊通了一半、狀態(tài)碼亂跳”的兄弟做個排錯參考。2. Modbus-RTU幀結構拆解從字節(jié)序列到CRC校驗Modbus-RTU的本質(zhì)就是主站把一段二進制數(shù)據(jù)發(fā)給從站從站處理完以后再回一段二進制數(shù)據(jù)。這段數(shù)據(jù)不是隨便發(fā)的它有嚴格的格式要求任何一幀不合法從站都不會搭理你。2.1 標準幀格式地址碼、功能碼、數(shù)據(jù)域、CRC一個完整的主站請求幀長這樣字段長度說明從站地址1字節(jié)范圍1~247對應伺服驅(qū)動器設置的站地址功能碼1字節(jié)03讀寄存器06寫單寄存器0x10寫多寄存器數(shù)據(jù)域N字節(jié)寄存器起始地址、寄存器數(shù)量、寫入值等CRC校驗2字節(jié)CRC16低位在前高位在后從站返回的應答幀結構更簡單字段長度說明從站地址1字節(jié)和請求幀的地址一致功能碼1字節(jié)正常情況下原樣返回如果出錯最高位置1比如0x83數(shù)據(jù)域N字節(jié)返回的數(shù)據(jù)或異常碼CRC校驗2字節(jié)同樣低位在前這里有一個特別容易翻車的點就是字節(jié)序。Modbus-RTU在傳輸多字節(jié)數(shù)據(jù)時寄存器地址和寄存器值是“高字節(jié)在前低字節(jié)在后”也就是大端模式。比如你要讀0x0200這個寄存器報文里寫的是02 00而不是00 02。但CRC字節(jié)又是“低字節(jié)在前高字節(jié)在后”這兩個正好相反我第一次調(diào)的時候就把CRC的順序搞反了在調(diào)試助手里看怎么都對不上。還有一個物理層要求幀與幀之間必須要有至少3.5個字符時間的靜默間隔。如果兩個字節(jié)之間的間隔超過1.5個字符時間從站就認為一幀結束了后面再來的字節(jié)會被當成下一幀處理。這個時間換算下來在9600波特率下大約是3.6ms在115200波特率下大約只有0.3ms。實際調(diào)試時我的習慣是在PLC側(cè)配合TIA的發(fā)送間隔建議保持50~100ms的最小輪詢間隔別圖快。2.2 CRC16校驗怎么算給小白一個能直接抄的算法CRC校驗的作用是保證一幀數(shù)據(jù)從主站到從站的過程中沒有被干擾破壞。Modbus-RTU使用的是CRC16多項式是0xA001初始值是0xFFFF。計算邏輯不復雜但手算是真的累現(xiàn)場調(diào)試你不可能拿筆算一般直接用調(diào)試助手的自動CRC功能或者用PLC里現(xiàn)成的庫函數(shù)。如果你要在單片機或者自寫上位機里做可以直接用這個標準實現(xiàn)unsigned int crc16_modbus(unsigned char *data, unsigned int len) { unsigned int crc 0xFFFF; unsigned int i, j; for (i 0; i len; i) { crc ^ data[i]; for (j 0; j 8; j) { if (crc 0x0001) { crc (crc 1) ^ 0xA001; } else { crc 1; } } } return crc; }這個函數(shù)返回的crc值低字節(jié)在前發(fā)出去就對了。很多初學者用網(wǎng)上在線CRC計算工具算出來的是一個規(guī)范值但傳輸?shù)臅r候必須把低字節(jié)寫在前面否則伺服收到以后校驗不通過直接丟棄這一幀表現(xiàn)為“從站完全無響應”。2.3 一個具體報文示例讀伺服參數(shù)寄存器以匯川伺服常見的“參數(shù)寄存器映射法”為例很多系列的驅(qū)動器會把H0D-00這類參數(shù)映射到0x0D00寄存器。假設我手頭這臺MS1H4驅(qū)動器站地址設置為1波特率設為96008位數(shù)據(jù)位無校驗1位停止位。我要讀取它的H0D-00參數(shù)值請求幀就是01 03 0D 00 00 01 [CRC低字節(jié)] [CRC高字節(jié)]拆開解讀01從站地址103讀保持寄存器0D 00起始寄存器地址0x0D0000 01讀1個寄存器如果一切正常從站返回01 03 02 00 03 [CRC低字節(jié)] [CRC高字節(jié)]01從站地址回顯03功能碼回顯02返回數(shù)據(jù)的字節(jié)數(shù)2個字節(jié)00 03寄存器值也就是H0D-00當前值為3只要你能在串口調(diào)試助手里看到這一問一答說明物理鏈路通了驅(qū)動器和PLC的串口參數(shù)沒問題。很多現(xiàn)場調(diào)不通第一步就卡在這——建議你在接PLC之前一定先用USB轉(zhuǎn)485串口模塊加一個網(wǎng)線調(diào)試助手把伺服這一頭調(diào)通再往PLC方向走。這里要特別強調(diào)一下不同型號的匯川伺服寄存器映射表不完全一樣。IS系列是一種規(guī)則MS1H4系列可能又是另一種規(guī)則還有一部分新系列走的是CiA402對象字典映射。所以不要死記我上面給的0x0D00動手之前先打開你手頭那臺驅(qū)動器對應的《通訊協(xié)議手冊》查一下“Modbus寄存器地址映射表”再把具體地址套進幀結構里。幀格式是通用的地址映射才是每個型號獨有的東西。3. 匯川伺服驅(qū)動器側(cè)參數(shù)設置與接線準備3.1 硬件接線RS-485端口與終端電阻RS-485是半雙工差分通訊兩根線分別叫A和B也有叫和-的現(xiàn)場最常用的接法是屏蔽雙絞線。匯川伺服驅(qū)動器上通常提供一個DB9或者RJ45形式的通訊口具體針腳定義必須查手冊不要想當然。我手頭這臺MS1H4通訊口是DB9母頭標準定義通常包括3腳RS-485 BD-4腳RS-485 AD5腳GND其他腳位可能涉及CAN或模擬量不要亂接注意A和B千萬別接反。接反的典型現(xiàn)象是一問一答完全沒響應但在示波器上又能看到波形。如果你把A、B對調(diào)以后通訊通了說明不是波特率問題就是線序問題。終端電阻RS-485總線要求在物理鏈路的兩端各接一個120Ω終端電阻用來消除信號反射。如果只有一臺PLC和一臺伺服點對點通訊那么干脆兩個都接上如果有好幾臺伺服掛在一條總線上那么只在最末端那一臺上接120Ω電阻中間的設備都不要接。終端電阻接太多的后果是總線負載過重通訊誤碼率會明顯上升別小看這個小電阻現(xiàn)場通訊不穩(wěn)定十有八九和它有關。另外布線方面我的經(jīng)驗是RS-485線盡量遠離變頻器輸出線、動力電纜這些強電干擾源。特別是伺服驅(qū)動器本身就在變頻器旁邊電氣柜里排線的時候通訊線務必單獨走線槽屏蔽層單端接地。我見過一個現(xiàn)場通訊時好時壞最后發(fā)現(xiàn)就是通訊線和伺服電機動力線捆在同一個線管里長達兩米分開以后問題立馬消失。3.2 驅(qū)動器通訊參數(shù)配置站地址、波特率、數(shù)據(jù)格式匯川伺服驅(qū)動器的參數(shù)通常用面板按鍵來設置。雖然不同系列菜單結構略有差異但通訊參數(shù)組一般集中在“H0D”這個組里分別是參數(shù)號功能常見取值我的建議H0D-00通訊站地址1~127單臺設為1多臺按1、2、3遞增H0D-01通訊波特率9600/19200/38400/115200推薦38400以上但S7-1200通訊穩(wěn)定性優(yōu)先選9600H0D-02數(shù)據(jù)格式8-N-1 / 8-E-1 / 8-O-1S7-1200默認推薦8-N-1H0D-03通訊協(xié)議Modbus-RTU / 自定義必須選Modbus-RTUH0D-04通訊超時時間0~255ms保持默認或設100ms以上有一個非常關鍵的容易踩的坑修改完通訊參數(shù)以后大多數(shù)匯川伺服需要斷點重啟或者確認參數(shù)生效否則面板上顯示的值變了但實際通訊協(xié)議棧還是舊的。我遇到過客戶說“波特率明明改成115200了怎么調(diào)試助手收不到”的情況其實就是改完沒重啟參數(shù)只在RAM里生效一斷電又變回去了。還有一點有的系列通訊參數(shù)組不叫H0D可能叫“CN組”或者“通訊組”面板菜單里翻到帶“通訊”字樣的那一組就對了。實在找不到直接在驅(qū)動器的用戶手冊里搜索“Modbus”或者“RS-485”先把參數(shù)清單打印出來再操作比瞎猜快得多。3.3 編碼器線數(shù)262144是什么為什么不要想著改題主提到的匯川伺服MS1H4在驅(qū)動器里顯示默認編碼器線數(shù)262144問能不能改。這個數(shù)字其實是2的18次方意味著電機編碼器的物理分辨率是每轉(zhuǎn)262144個脈沖也就是18位絕對式編碼器。這個值是編碼器硬件本身決定的由光柵/磁柵的刻線數(shù)和內(nèi)部細分電路共同固化出來的不是用戶參數(shù)。你試圖去改這個值要么發(fā)現(xiàn)參數(shù)是只讀的要么改了之后位置反饋全亂套。那為什么驅(qū)動器的參數(shù)列表里會出現(xiàn)類似“編碼器線數(shù)”的設置項這里要區(qū)分兩個概念編碼器內(nèi)部分辨率固定262144不可改獨立于任何通訊協(xié)議。編碼器輸出分頻/倍頻也就是從驅(qū)動器的ABZ脈沖輸出口向外發(fā)送的脈沖數(shù)這個是可以設置的。如果你通過驅(qū)動器后面的位置脈沖輸出口把位置反饋分頻成每轉(zhuǎn)10000個脈沖送給上位機改動的是“輸出分頻”不是編碼器物理分辨率。此時你通過Modbus去讀編碼器位置反饋讀回來的還是基于262144計數(shù)的原始值。所以這兩個東西千萬別混為一談。在Modbus通訊中262144這個數(shù)值對應到PLC側(cè)的數(shù)據(jù)類型換算很關鍵。262144大于16位的最大帶符號整數(shù)32767所以在讀取位置反饋時通常需要連續(xù)讀兩個寄存器組成32位數(shù)據(jù)。如果你只用單寄存器讀讀出來的數(shù)會莫名其妙地“跳變”甚至出現(xiàn)負數(shù)。這就是為什么通訊幀里讀位置一次要讀2個寄存器、4個字節(jié)而不是1個寄存器2個字節(jié)。很多新人在這一步掉進坑里以為是數(shù)據(jù)讀錯了其實是32位拆分合并沒處理對。3.4 關鍵參數(shù)核對表我在每次上電調(diào)試之前都會列一張核對表防止漏配、錯配。這里分享出來驅(qū)動器的Modbus站地址是否唯一如果是多臺掛一條總線絕對不能有兩個相同地址。波特率、數(shù)據(jù)位、校驗位、停止位是否和PLC側(cè)設置完全一致通訊協(xié)議是否選到了Modbus-RTU而不是匯川私有協(xié)議通訊超時時間是否設置合理太短的話驅(qū)動器會頻繁報通訊錯誤太長的話故障響應慢。伺服是否已經(jīng)處于“待機”狀態(tài)很多驅(qū)助在報HAL報警硬件過流或者急停狀態(tài)下通訊棧是不會正常響應主站指令的。編碼器線數(shù)參數(shù)是否保持默認值確認沒有人動過“編碼器線數(shù)”或“反饋分頻”相關參數(shù)。這一套檢查下來能過濾掉絕大多數(shù)“通訊不通”的初級問題。4. 西門子PLC側(cè)配置實戰(zhàn)以S7-1200為例西門子S7-1200跑Modbus-RTU主站核心就是博途軟件里的兩個指令MB_COMM_LOAD和MB_MASTER。前者負責初始化串口參數(shù)后者負責發(fā)起一次讀寫請求。下面我按從易到難的順序把每一步拆開講。4.1 硬件組態(tài)先讓CPU認識你的RS-485口S7-1200本身不帶RS-485物理接口一般通過兩種方式擴展通訊模塊CM1241 RS-422/485這也是最常用的一種。西門子CB1241這個是以RS-485為主的板載通訊板緊湊型CPU可以插。組態(tài)的時候把CM1241模塊拖到CPU左側(cè)的導軌上博途會自動分配一個硬件標識符。這個標識符在MB_COMM_LOAD里要用到具體值不用背在指令里拖拽Port口的時候直接選擇硬件標識符即可。很多新手容易漏掉的一步是CM1241模塊的接口類型要在設備視圖里確認選成“RS-485”而不是“RS-422”。RS-422是全雙工四線制RS-485是半雙工兩線制選錯了通訊肯定廢。還有如果通訊模塊上帶撥碼開關或DIP開關檢查工作模式要撥到RS-485側(cè)有的模塊出廠默認是RS-422不撥過來后面的工作全白搭。4.2 MB_COMM_LOAD端口初始化MB_COMM_LOAD負責把CM1241的串口初始化成Modbus-RTU模式。把指令拖進OB1之后輸入?yún)?shù)這么設置參數(shù)意義推薦值PORT通訊模塊硬件標識符拖拽硬件標識符BAUD波特率和伺服側(cè)一致比如9600PARITY校驗方式0表示無校驗1為奇校驗2為偶校驗MB_DB連接數(shù)據(jù)塊留空或新建空DBRTS_ON_DLY發(fā)送RTS延遲0RTS_OFF_DLY發(fā)送后RTS釋放延遲0RESP_TO應答超時時間100ms左右多從站建議加大有一點值得注意MB_COMM_LOAD的使能端REQ要接一個常ON信號也就是說這個指令要一直保持啟用狀態(tài)。很多新手用一個邊沿觸發(fā)去初始化端口結果發(fā)現(xiàn)只有第一個掃描周期端口被初始化了一下后面通訊全斷。RESP_TO這個參數(shù)是主站等待從站應答的超時時間。如果從站比較多或者走線比較長應答延時也會變大建議設到200ms以上。設太短會誤報超時設太長又會拖慢輪詢周期需要根據(jù)現(xiàn)場實測來權衡。4.3 MB_MASTER讀寫指令地址換算與觸發(fā)方式初始化完成以后真正干活的是MB_MASTER。它的幾個關鍵參數(shù)參數(shù)意義使用建議REQ觸發(fā)請求用一個周期脈沖或定時器脈沖不能一直常ONMB_MODE功能選擇0表示讀1表示寫MB_DATA_ADDR寄存器地址用40001偏移的方式MB_DATA_LEN數(shù)據(jù)長度單位是字Word讀32位數(shù)據(jù)請設2MB_DATA_PTR數(shù)據(jù)存放指針指向一個數(shù)組或DB變量DONE完成標志完成一次讀寫后置TRUE一個周期ERROR錯誤標志有錯誤時置TRUESTATUS錯誤代碼需要監(jiān)控的重點關鍵中的關鍵MB_DATA_ADDR的換算方法。S7-1200的MB_MASTER秉承Modbus傳統(tǒng)尋址習慣如果你要讀保持寄存器4區(qū)地址從40001開始。我前面寫的寄存器0x0200換算成十進制是512那么在MB_DATA_ADDR這一欄你應該填40001 512 40513如果你想一次讀兩個寄存器組成32位位置值那么MB_DATA_LEN就填2MB_DATA_PTR指向的數(shù)組至少要有2個字長的空間。博途里比較推薦的做法是新建一個全局數(shù)據(jù)塊里面放一個包含若干Word元素的數(shù)組比如DATA_BLOCK ModbusData {VERSION: 0.1, NON_RETAIN} VAR HoldingRegs : Array[0..31] of Word; ReadPos : DInt; // 用DInt接收32位位置值 CtrlWord : Word; StatusWord : Word; END_VAR讀回來的原始數(shù)據(jù)通過“合并字”操作高位字左移16位再或上低位字就能得到完整的32位位置。如果你用的是SCL可以直接這樣寫#ReadPos : WORD_TO_DINT(#HoldingRegs[0]) * 256 * 256 WORD_TO_DINT(#HoldingRegs[1]);這里的HoldingRegs[0]是高16位HoldingRegs[1]是低16位。有些驅(qū)動器回讀的時候寄存器排列順序可能相反如果算出來的位置值在跳變、數(shù)值不對把這兩個字的順序?qū)φ{(diào)就行。這個“字節(jié)序/字序不一致”的問題是Modbus調(diào)試里最折磨人的一個坑后面我會專門展開說。4.4 用監(jiān)控表驗證通訊狀態(tài)程序?qū)懞昧瞬⒉淮砣f事大吉。打開博途的監(jiān)控表把MB_MASTER的DONE、ERROR、STATUS變量拖進去實時監(jiān)控DONE置TRUE說明本次讀寫正常完成。ERROR置TRUE說明本次請求出錯看STATUS代碼定位問題。STATUS顯示16#8180經(jīng)典錯誤表示“從站無響應”優(yōu)先排查接線、站地址、波特率。STATUS顯示16#8185通常是“從站返回異常響應”需要去查伺服側(cè)的功能碼是否支持、寄存器地址是否存在。另外建議在MB_MASTER的REQ端用定時器做一個周期脈沖。最簡單的做法是用TON搭一個自復位定時器例如IF #timer.Q THEN #req : TRUE; #timer(IN : FALSE); ELSE #req : FALSE; #timer(IN : TRUE, PT : T#200MS); END_IF;這樣每200ms觸發(fā)一次MB_MASTER請求。200ms這個周期對于絕大多數(shù)定位控制來說足夠用了。如果你有急停、報警這類需要快速響應的信號建議不要靠Modbus輪詢來實現(xiàn)還是接硬線或者走PN口安全等級完全不是一個層面。MB_MODE的使用也不復雜讀操作填0寫操作填1。寫單個寄存器用功能碼06由塊內(nèi)部根據(jù)參數(shù)自動選擇寫多個寄存器的時候MB_DATA_LEN填要寫的字數(shù)即可。常見的應用比如把位置給定值連續(xù)寫兩個寄存器或者通過寫控制字去觸發(fā)伺服使能、復位報警。5. 聯(lián)調(diào)過程中踩過的坑與排查鏈路這一部分是我最想分享的因為我見過太多人在通訊聯(lián)調(diào)階段卡上兩三天最后發(fā)現(xiàn)都是些很基礎但容易被忽略的問題。5.1 從站無響應8180錯誤的完整排查順序當STATUS出現(xiàn)16#8180時我的排查順序是這樣先看一眼伺服驅(qū)動器面板有沒有報通訊錯誤或者通訊超時報警。如果伺服側(cè)報警了大概率是驅(qū)動器根本沒收到有效幀問題在幀格式或者物理連線上。第二步用電腦接串口調(diào)試助手替代PLC去發(fā)一幀標準的03讀寄存器報文。如果串口助手也得不到應答那么問題一定在伺服側(cè)和通訊線路上基本可以排除PLC的配置問題。這時候重點檢查三件事A/B是否接反、波特率數(shù)據(jù)格式是否一致、驅(qū)動器是否要重新上電才生效參數(shù)。如果串口助手能正常應答但PLC通訊依然是8180那么問題回到PLC側(cè)檢查MB_COMM_LOAD的PORT參數(shù)是否選對硬件標識符。檢查MB_COMM_LOAD的BAUD、PARITY是否和伺服完全一致。檢查MB_MASTER的MB_DATA_ADDR換算是否正確。很多人填了個40513結果寫成40531這種低級錯誤也會導致報錯。檢查REQ觸發(fā)方式如果REQ一直是TRUE而不產(chǎn)生邊沿MB_MASTER是不會發(fā)起請求的。8180這個錯誤在西門子的官方文檔里叫“無應答從站在應答時間窗內(nèi)未響應”。它不會告訴你從站在哪里斷的所以一定要配合串口調(diào)試助手做“雙端驗證”——一頭PLC發(fā)一頭電腦看RS-485線上到底有沒有數(shù)據(jù)在走。5.2 數(shù)據(jù)錯位或者說數(shù)據(jù)總是跳變的根因數(shù)據(jù)類型與字節(jié)序通訊通了數(shù)據(jù)卻有異常這比通訊不通更讓人頭疼。最常見的一種現(xiàn)象是讀回來的位置值一會兒是一個巨大正數(shù)一會兒是一個負數(shù)一會兒又是0。十有八九是32位數(shù)據(jù)拆成兩個16位寄存器后合并順序不對。PLC里Modbus寄存器默認按字處理。伺服保存一個32位位置值高16位在一個寄存器低16位在下一個寄存器。你用MB_MASTER連續(xù)讀兩個字返回的順序是先高后低。但問題是不同的驅(qū)動器和不同的PLC庫對于“哪個寄存器是高字”的規(guī)定偶爾會相反。所以我的做法是讀回來以后先不解釋成人眼看得懂的值直接把兩個原始字打印出來算一下實際電機轉(zhuǎn)一圈看變化的是哪個寄存器——如果轉(zhuǎn)一圈后高字寄存器有變化說明當前順序沒問題如果是低字寄存器在快速變化而高字幾乎不動說明這其實是一個32位數(shù)據(jù)的低位部分順序沒錯只是你沒把它和高字合起來。另外還有一個非常隱蔽的坑西門子自身的數(shù)據(jù)存儲是大端格式而有些伺服在寄存器里存數(shù)據(jù)時用的是小端格式。你讀回來一個字比如16#1234在PLC里顯示的是1234但實際物理意義可能是34 12。這就要在PLC側(cè)做“字節(jié)交換”處理。圖形化編程里可以用SWAP指令SCL里可以這樣寫#rawValue : SWAP(WORD_TO_BYTE(#HoldingRegs[0]), 1);更通用一點的做法是寫一個小的轉(zhuǎn)換函數(shù)把所有讀回來的字都過一遍字節(jié)交換除非你能確認驅(qū)動器手冊里明確寫了“高字節(jié)在前”。在匯川的協(xié)議手冊里通常會說Modbus寄存器默認為高字節(jié)在前但有些功能碼里嵌套的數(shù)據(jù)區(qū)會有特殊規(guī)則所以“先驗證再固化邏輯”才是正解。5.3 通訊抖動的元兇波特率、終端電阻與地電位如果你發(fā)現(xiàn)通訊時好時壞有一個規(guī)律性的“讀幾幀正常隔一會兒就失敗一幀”先別急著懷疑PLC程序。這類間歇性通訊問題絕大多數(shù)出在物理層。第一個要懷疑的就是終端電阻。兩根線之間沒接終端電阻信號在末端會反射造成波形畸變。你可以在RS-485總線兩端并上120Ω電阻試試很多“偶發(fā)通訊超時”立刻就好了。第二是波特率9600和115200在短距離點對點的情況下區(qū)別不大但如果線纜長度超過50米或者現(xiàn)場干擾源多建議保守選用9600或19200代價只是輪詢慢一點換來的是穩(wěn)定。第三個是地電位差。不同設備的GND如果沒有可靠共地A、B線之間存在較大的共模電壓超過收發(fā)器承受范圍通訊就會不正常。解決辦法是把PLC的M端和伺服驅(qū)動器的GND用一根線連起來。注意不是把保護地PE和信號地混為一談而是在設備之間接通信號參考地。我還遇到過一種情況通訊線屏蔽層兩端接地結果形成了地環(huán)路反而引入干擾。正確的做法是屏蔽層“單端接地”通常是靠近PLC那一端接地。這個話題在工控現(xiàn)場討論很多我的經(jīng)驗是先把“不接地、兩端都接地、單端接地”三種狀態(tài)都試一遍用示波器看效果哪種最干凈就保留哪種。5.4 伺服報警導致的通訊假正常還有一種現(xiàn)象特別迷惑人PLC和伺服之間通訊正常讀寫都返回成功但驅(qū)動就是不動或者一使能就報錯。這種情況多半不是通訊問題而是伺服本身的報警狀態(tài)沒有復位。匯川伺服的使能/停機一般通過控制字來控制常見的控制字包括伺服使能、清除報警、啟動正轉(zhuǎn)、啟動反轉(zhuǎn)。如果你通過Modbus寫了控制字但伺服沒反應先看驅(qū)動器面板有沒有報警碼。常見的報警比如HAL硬件過流、Et過載、SEr編碼器異常等這些報警不消除你不管寫什么控制字伺服都不會進入可運行狀態(tài)。清除報警的通用做法在控制字里把“故障復位”位置1保持一段時間后再復位為0。具體是哪一位取決于你用的是匯川私有控制字還是CiA402對象字典的0x6040控制字。如果是標準CiA402bit7是故障復位bit3是使能運行——操作順序一般是先給一個“上電”狀態(tài)的組合0x0006或0x0007再置位bit3然后保持。不要一上來就先把所有位都寫滿那樣很多驅(qū)動器會直接報控制字錯誤。6. 提速與穩(wěn)定性優(yōu)化建議通訊調(diào)通了能讀寫數(shù)據(jù)了只算完成了50%。剩下的一半是怎么讓系統(tǒng)在產(chǎn)線上穩(wěn)定跑幾個月不出幺蛾子。這里分享幾個我在現(xiàn)場總結的優(yōu)化思路。6.1 輪詢周期與寄存器批量讀取Modbus-RTU是半雙工一問一答通訊耗時主要取決于報文長度和波特率。在115200波特率下一個簡單的6字節(jié)請求幀加9字節(jié)應答幀傳輸時間大約在1.3ms左右加上驅(qū)動器的處理延遲和PLC的掃描周期實際一個完整問答大概要10~20ms。如果你有多個數(shù)據(jù)要讀千萬不要一次只讀一個寄存器。比如你要同時讀狀態(tài)字、當前位置、當前速度這三個數(shù)據(jù)如果分布在連續(xù)寄存器段就一次讀3個寄存器把MB_DATA_LEN設成3。這樣一次問答就把三個值全部拿回來效率翻倍還不起沖突。反過來寫入操作也要合并。比如設備啟動時既要給目標位置又要給速度、加速度如果這幾個寄存器是連續(xù)的優(yōu)先用寫多個寄存器的方式一次寫入而不是一條一條寫。這樣不僅通訊效率高更重要的是多個數(shù)據(jù)在伺服側(cè)是同一幀里被接收處理的不存在“先更了位置、后更了速度”這種中間狀態(tài)導致的誤動作。6.2 掉電重啟與故障恢復機制Modbus-RTU有個特性從站掉電再上電以后通訊??赡苄枰獛装俸撩氩拍苤匦戮途w。如果PLC在驅(qū)動器還在初始化的時候就開始發(fā)讀寫請求很可能會得到異常響應。因此我的程序里通常會加一個上電等待邏輯PLC啟動后先延遲1~2秒再開始正常的Modbus輪詢。這個邏輯雖然簡單但在冷啟動現(xiàn)場非常管用。另一個容易被忽略的是故障恢復。當通訊連續(xù)失敗幾次時程序里要有計數(shù)。超過閾值就置一個“通訊故障”標志讓設備進入安全狀態(tài)而不是一直盲目重試。因為Modbus的請求重試會占用PLC的掃描周期重試期間你可能其他邏輯都卡住了。我習慣的恢復策略是連續(xù)失敗5次置故障故障后每500ms重試一次連續(xù)成功2次后自動清除故障。這樣就避免了“偶爾一幀超時就必須人工復位”的尷尬情況又能保證真斷線時設備能停下來。6.3 從Modbus到EtherCAT這個方案的上限與下一步最后說句大實話Modbus-RTU這套方案解決的是“夠用”的問題不是“最優(yōu)”的問題。當你開始追求更短的周期、更小的通訊抖動、或者需要多軸聯(lián)動時就應該考慮切換到EtherCAT或者PROFINET了。但是切換到高速總線并不意味著Modbus的經(jīng)驗全部作廢。你在匯川伺服上設的站地址、編碼器分辨率、控制字邏輯在EtherCAT里依然存在只是訪問方式從“寄存器的03/06功能碼”變成了“對象字典的SDO/PDO映射”。你在Modbus階段把寄存器地址、控制字、狀態(tài)字的邏輯理清楚了到EtherCAT階段基本上就是把同樣的東西換個皮來做。以我個人的經(jīng)驗一臺匯川伺服從Modbus-RTU順利遷移到EtherCAT如果之前的基礎資料齊全整個改造大概只要半天。真正消耗時間的是物理接線和同步參數(shù)學調(diào)而不是那些控制邏輯。所以如果你的設備現(xiàn)在只是單軸定位、速度給定這種輕量級應用就放心用Modbus-RTU跑如果未來有明確的多軸同步規(guī)劃那從一開始選型就要考慮帶EtherCAT口的伺服別為了省一點硬件成本把后面的擴展路堵死。做設備選型的時候看得稍微遠一點后面會省很多事。