戰(zhàn):ADPRW與RS2指令詳解)
1. 絕對值編碼器接入FX3U的真實(shí)場景與需求拆解絕對值編碼器在工業(yè)現(xiàn)場用得很多尤其是那些斷電后不能丟位置的場合——比如升降機(jī)構(gòu)、旋轉(zhuǎn)刀塔、閘門開度控制。它和普通的增量式編碼器最大的區(qū)別在于增量式斷電后位置就沒了每次上電都得回原點(diǎn)絕對值編碼器不管斷電多久重新上電后讀到的還是那個絕對位置值。三菱FX3U本身是個小型PLCCPU自帶一個RS-422編程口和一個RS-485通訊口8針圓口。但實(shí)際項目里我們很少直接用CPU自帶的那個圓口去接編碼器原因有兩個一是那個口通常要留給觸摸屏或者編程用二是它的通訊參數(shù)配置靈活性有限。更常見的做法是加一塊FX3U-485ADP-MB通訊擴(kuò)展板或者用FX3U-485ADP配合RS/RS2指令來做。這里先厘清一個容易混淆的點(diǎn)FX3U-485ADP-MB這塊板子支持兩種工作模式——一種是Modbus RTU主站模式用ADPRW指令直接讀寫從站寄存器另一種是通用通訊模式用RS/RS2指令收發(fā)自定義報文。絕對值編碼器如果支持標(biāo)準(zhǔn)Modbus RTU協(xié)議那用ADPRW最省事如果編碼器是廠家自定義的串口協(xié)議很多國產(chǎn)絕對值編碼器都是這種那就得用RS2指令自己拼報文。我這次調(diào)試的是一臺支持Modbus RTU的絕對值編碼器型號就不說了反正協(xié)議是標(biāo)準(zhǔn)的03功能碼讀保持寄存器。波特率96008位數(shù)據(jù)位無校驗(yàn)1位停止位。編碼器作為從站站號設(shè)為1位置值放在兩個連續(xù)的保持寄存器里高字在前低字在后組成一個32位有符號整數(shù)。注意絕對值編碼器的分辨率直接決定了位置值的量程。比如17位單圈編碼器一圈就是131072個脈沖如果是多圈編碼器還要考慮圈數(shù)位數(shù)。讀回來的32位數(shù)據(jù)要搞清楚哪幾位是圈數(shù)、哪幾位是單圈角度不然算出來的位置是錯的。2. 硬件接線與通訊參數(shù)確認(rèn)別在第一步就翻車2.1 RS-485兩線制的接線邏輯FX3U-485ADP-MB的接線端子一般標(biāo)著SDA、SDB、RDA、RDB、SG、FG。做兩線制通訊時把SDA和RDA短接SDB和RDB短接然后SDA接編碼器的A或DSDB接編碼器的B或D-。SG是信號地如果通訊距離超過幾十米建議把SG也接上能明顯改善通訊質(zhì)量。FG是屏蔽層接地接控制柜的接地排。這里有個新手特別容易犯的錯把A和B接反了。RS-485的A和B在不同廠家的定義有時候是反的有的廠家標(biāo)D和D-有的標(biāo)A和B還有的標(biāo)TR和TR-。最穩(wěn)妥的辦法是看編碼器手冊里的接線圖確認(rèn)哪個是正哪個是負(fù)。如果接反了通訊完全不通但硬件不會燒只是收不到數(shù)據(jù)。終端電阻的問題也值得說一句。RS-485總線在通訊速率較高或者距離較遠(yuǎn)時需要在總線兩端各接一個120歐姆的終端電阻。9600這種低速短距離的場合不接也能通但如果現(xiàn)場干擾大或者通訊時斷時續(xù)加終端電阻往往能解決問題。FX3U-485ADP-MB板子上沒有內(nèi)置終端電阻需要自己在外圍電路上加。2.2 通訊參數(shù)的匹配編碼器側(cè)的參數(shù)一般通過撥碼開關(guān)或者廠家上位機(jī)軟件設(shè)置。需要確認(rèn)的參數(shù)包括波特率、數(shù)據(jù)位、停止位、校驗(yàn)方式、站號。這些參數(shù)必須和PLC側(cè)完全一致任何一個不匹配都通不了。FX3U-485ADP-MB在Modbus RTU主站模式下通訊參數(shù)是通過特殊數(shù)據(jù)寄存器D8400系列來設(shè)置的。具體來說寄存器含義我這次用的值D8400通訊格式H0C81D8401站號H0001D8402超時H000AD8403重試次數(shù)H0003D8404延遲時間H0000D8400這個值需要拆開看。H0C81對應(yīng)的二進(jìn)制是0000 1100 1000 0001。從低位往高位看bit0是數(shù)據(jù)長度1表示8位bit1-bit2是校驗(yàn)方式00表示無校驗(yàn)bit3是停止位1表示1位停止位bit4-bit7是波特率1000表示9600bpsbit8-bit15是通訊協(xié)議相關(guān)設(shè)置。這個值算錯了通訊參數(shù)就不對報文發(fā)出去編碼器也認(rèn)不出來。實(shí)操心得D8400的值我建議用三菱官方手冊里的通訊格式表來查不要自己憑感覺拼二進(jìn)制。我見過有人把校驗(yàn)位設(shè)成偶校驗(yàn)結(jié)果編碼器是無校驗(yàn)調(diào)了半天以為是接線問題。3. ADPRW指令的報文邏輯與梯形圖實(shí)現(xiàn)3.1 ADPRW指令的參數(shù)含義ADPRW是三菱FX3U在Modbus RTU主站模式下的專用通訊指令格式是ADPRW S1 S2 S3 S4 DS1從站站號S2功能碼03讀保持寄存器06寫單個寄存器16寫多個寄存器等S3從站寄存器起始地址S4讀寫點(diǎn)數(shù)D本地PLC存儲起始地址比如我要讀站號1的編碼器從寄存器地址0開始讀2個寄存器存到PLC的D100和D101里指令就是ADPRW H1 H03 H0 H2 D100這條指令執(zhí)行后PLC會自動拼出Modbus RTU報文站號01 功能碼03 起始地址0000 寄存器數(shù)量0002 CRC校驗(yàn)然后通過485ADP板發(fā)出去。編碼器收到后回復(fù)站號01 功能碼03 字節(jié)數(shù)04 數(shù)據(jù)高字 數(shù)據(jù)低字 CRC。PLC自動解析后把數(shù)據(jù)存到D100和D101。3.2 梯形圖程序的完整結(jié)構(gòu)實(shí)際程序里ADPRW不能一直觸發(fā)否則會連續(xù)發(fā)報文導(dǎo)致通訊混亂。通常用一個脈沖觸發(fā)配合完成標(biāo)志位來判斷通訊是否結(jié)束。我用的梯形圖邏輯是這樣的第一段上電初始化。用M8002初始脈沖把通訊參數(shù)寫入D8400到D8404同時把M8411置位表示使用485ADP-MB的Modbus模式。第二段定時觸發(fā)。用T0做一個1秒的定時器T0常開觸點(diǎn)觸發(fā)ADPRW指令。ADPRW執(zhí)行完成后M8029指令完成標(biāo)志會導(dǎo)通一個掃描周期用這個信號復(fù)位定時器形成循環(huán)。第三段數(shù)據(jù)處理。D100和D101組成32位數(shù)據(jù)用DMOV指令把D100和D101傳送到D200和D201然后根據(jù)編碼器的分辨率做換算。比如17位單圈編碼器一圈131072脈沖那實(shí)際角度就是(D200/131072)*360度。第四段錯誤處理。M8260到M8269是通訊錯誤標(biāo)志位如果ADPRW執(zhí)行出錯對應(yīng)的錯誤標(biāo)志會置位。我在程序里加了判斷如果連續(xù)3次通訊失敗就輸出一個報警信號到Y(jié)0提示操作人員檢查接線。注意ADPRW指令的S3參數(shù)是Modbus寄存器地址不是PLC的D寄存器地址。有些編碼器手冊上寫的寄存器地址是從1開始的比如40001而Modbus協(xié)議里是從0開始的需要減1。這個細(xì)節(jié)不注意讀回來的數(shù)據(jù)就是錯的或者直接通訊異常。3.3 32位數(shù)據(jù)的拼接與符號處理絕對值編碼器返回的位置值通常是32位有符號整數(shù)。D100存高16位D101存低16位。拼接的時候要注意字節(jié)順序和字順序。三菱PLC里用DMOV D100 D200就是把D100和D101組成32位數(shù)據(jù)存到D200和D201。但這里有個坑Modbus RTU報文里的數(shù)據(jù)是高字在前、低字在后而三菱PLC的DMOV指令是D100為高字、D101為低字。如果編碼器手冊寫的是低字在前那就得手動交換。符號處理也很關(guān)鍵。32位有符號整數(shù)的最高位是符號位如果編碼器返回的是負(fù)數(shù)比如位置在零點(diǎn)以下直接當(dāng)無符號數(shù)處理就會得到一個巨大的正數(shù)。我一般用D200和D201做比較判斷或者直接用32位比較指令來處理。4. RS2指令自定義報文當(dāng)編碼器不走標(biāo)準(zhǔn)Modbus時4.1 RS2指令的收發(fā)機(jī)制有些絕對值編碼器用的是廠家自定義的串口協(xié)議比如發(fā)一串特定的命令碼編碼器回一串固定格式的數(shù)據(jù)。這種場合就得用RS2指令。RS2指令的格式是RS2 S1 S2 S3 D1 D2S1發(fā)送數(shù)據(jù)的起始軟元件S2發(fā)送字節(jié)數(shù)S3接收數(shù)據(jù)的起始軟元件D1接收字節(jié)數(shù)D2執(zhí)行標(biāo)志比如我要發(fā)8個字節(jié)的命令存在D300到D303里接收10個字節(jié)存到D400到D404里指令就是RS2 D300 K8 D400 K10 M100M100導(dǎo)通時PLC通過485ADP板把D300開始的8個字節(jié)發(fā)出去然后等待接收。接收完成后M100自動復(fù)位接收到的數(shù)據(jù)存在D400開始的區(qū)域。4.2 自定義報文的拼裝與校驗(yàn)自定義協(xié)議最麻煩的地方是校驗(yàn)。常見的校驗(yàn)方式有和校驗(yàn)、CRC校驗(yàn)、異或校驗(yàn)。和校驗(yàn)最簡單把前面所有字節(jié)加起來取低8位就行。CRC校驗(yàn)復(fù)雜一些但Modbus RTU用的就是CRC16。如果編碼器用的是CRC16校驗(yàn)PLC里沒有現(xiàn)成的CRC指令得自己寫一段程序來算。我一般用查表法或者逐位計算法。逐位計算法的邏輯是CRC初始值FFFF每個字節(jié)和CRC異或后循環(huán)右移8次每次如果移出的位是1就和多項式A001異或。這段程序?qū)懫饋泶蟾哦畮撞降阋淮蜟RC大概需要幾十毫秒對于9600波特率來說完全夠用。實(shí)操心得自定義協(xié)議的編碼器廠家一般會提供通訊協(xié)議文檔里面會寫清楚命令格式、返回格式、校驗(yàn)方式。如果沒有文檔可以用串口助手先抓一下編碼器上電后主動發(fā)出的數(shù)據(jù)或者用廠家調(diào)試軟件發(fā)一條命令用串口助手監(jiān)聽把報文抓下來分析。4.3 RS2與ADPRW的選型對比對比項ADPRWModbus RTURS2自定義協(xié)議適用場景編碼器支持標(biāo)準(zhǔn)Modbus RTU編碼器用廠家私有協(xié)議編程復(fù)雜度低一條指令搞定高需要自己拼報文和校驗(yàn)靈活性受Modbus協(xié)議限制完全自由想發(fā)什么發(fā)什么調(diào)試難度低報文格式固定高需要抓包分析通訊效率中等有協(xié)議開銷高可以精簡報文我個人的建議是如果編碼器支持Modbus RTU優(yōu)先用ADPRW省時省力。如果編碼器只支持自定義協(xié)議那就老老實(shí)實(shí)用RS2把協(xié)議文檔吃透先用串口助手在電腦上把報文調(diào)通再移植到PLC里。5. 調(diào)試過程中最容易卡住的幾個環(huán)節(jié)5.1 通訊完全不通的排查順序第一步確認(rèn)接線。用萬用表量一下A和B之間的電壓靜態(tài)時應(yīng)該有幾百毫伏的壓差。如果電壓是0說明接線斷了或者編碼器沒上電。第二步確認(rèn)參數(shù)。波特率、數(shù)據(jù)位、停止位、校驗(yàn)、站號這五個參數(shù)必須和編碼器完全一致。我習(xí)慣用串口助手先在電腦上試電腦能通再換PLC這樣能排除一半的問題。第三步確認(rèn)指令。ADPRW的站號、功能碼、寄存器地址、點(diǎn)數(shù)這四個參數(shù)任何一個錯了都通不了。特別是寄存器地址有的編碼器手冊寫的是十進(jìn)制有的是十六進(jìn)制要看清。第四步看錯誤標(biāo)志。M8260到M8269會給出具體的錯誤代碼比如M8260是超時錯誤M8261是校驗(yàn)錯誤M8262是站號錯誤。根據(jù)錯誤代碼能快速定位問題。5.2 數(shù)據(jù)讀回來但不對的情況通訊通了但數(shù)據(jù)不對通常有幾種可能寄存器地址偏移。Modbus協(xié)議里寄存器地址從0開始但有些編碼器手冊從1開始需要減1。數(shù)據(jù)類型理解錯誤。編碼器返回的是32位有符號數(shù)但程序里當(dāng)16位處理了。字節(jié)順序問題。高字和低字的位置搞反了。分辨率換算錯誤。編碼器的實(shí)際分辨率和手冊寫的不一致或者多圈編碼器的圈數(shù)位數(shù)沒算對。我遇到過一次編碼器手冊寫的是17位單圈但實(shí)際讀回來的數(shù)據(jù)范圍是0到65535明顯是16位。后來查了半天發(fā)現(xiàn)是編碼器的一個撥碼開關(guān)設(shè)置錯了把多圈功能關(guān)了變成了16位單圈。這種硬件配置問題光看程序是查不出來的。5.3 通訊不穩(wěn)定的干擾問題RS-485通訊在工業(yè)現(xiàn)場受干擾是常態(tài)。如果發(fā)現(xiàn)通訊時斷時續(xù)數(shù)據(jù)偶爾出錯可以從以下幾個方面改善加終端電阻。總線兩端各接一個120歐姆電阻。屏蔽層接地。編碼器電纜的屏蔽層接控制柜接地排但不要兩端都接避免地環(huán)路。遠(yuǎn)離干擾源。編碼器電纜不要和變頻器輸出線、伺服電機(jī)動力線走同一個線槽。降低波特率。9600不行就降到4800通訊速率越低抗干擾能力越強(qiáng)。增加重試次數(shù)。D8403里設(shè)置重試次數(shù)通訊失敗時自動重發(fā)。注意如果現(xiàn)場有多臺變頻器或者伺服驅(qū)動器RS-485通訊受到干擾的概率會明顯增加。這種情況下除了做好屏蔽和接地還可以考慮在通訊線上加磁環(huán)或者用帶隔離的485中繼器。6. 從單臺編碼器到多站輪詢的擴(kuò)展思路6.1 多站輪詢的程序框架實(shí)際項目里往往不止一臺編碼器可能有好幾臺掛在同一條485總線上。這時候就需要輪詢——依次和每個站通訊而不是同時發(fā)指令。輪詢的程序框架大概是這樣的用一個寄存器記錄當(dāng)前要通訊的站號ADPRW執(zhí)行完成后站號加1如果超過最大站號就回到1。每個站的通訊結(jié)果存到不同的D寄存器區(qū)域互不干擾。輪詢的間隔時間要算好。9600波特率下一條ADPRW報文大概10個字節(jié)加上編碼器回復(fù)的報文一來一回大概20到30毫秒。如果掛8臺編碼器一輪輪詢下來大概200到300毫秒。這個刷新周期對于大多數(shù)位置檢測應(yīng)用是夠用的但如果要求更高的實(shí)時性就得提高波特率或者減少站數(shù)。6.2 輪詢中的超時處理輪詢最怕的是某一臺站壞了或者掉線了導(dǎo)致整個輪詢卡死。所以每臺站的通訊都要有超時判斷。ADPRW指令本身有超時設(shè)置D8402但輪詢程序里最好再加一層邏輯如果某臺站連續(xù)幾次通訊失敗就跳過它繼續(xù)輪詢下一臺同時輸出一個報警提示。我一般用計數(shù)器來實(shí)現(xiàn)每臺站對應(yīng)一個失敗計數(shù)器通訊成功清零通訊失敗加1加到3就跳過。這樣即使某臺編碼器臨時出問題也不會影響其他站的正常通訊。6.3 數(shù)據(jù)緩存與上位機(jī)交互多站輪詢讀回來的數(shù)據(jù)通常要傳給觸摸屏或者上位機(jī)。我習(xí)慣把每臺編碼器的位置值存到連續(xù)的D寄存器區(qū)域比如第一臺存D500和D501第二臺存D502和D503以此類推。觸摸屏直接讀這些寄存器就行不需要關(guān)心底層的通訊細(xì)節(jié)。如果上位機(jī)是組態(tài)軟件或者SCADA系統(tǒng)可以通過FX3U的以太網(wǎng)模塊或者串口模塊把數(shù)據(jù)轉(zhuǎn)發(fā)出去。轉(zhuǎn)發(fā)的時候要注意數(shù)據(jù)格式的統(tǒng)一比如都轉(zhuǎn)成32位有符號整數(shù)或者都轉(zhuǎn)成浮點(diǎn)數(shù)避免上位機(jī)解析出錯。7. 幾個容易被忽略的細(xì)節(jié)與個人經(jīng)驗(yàn)7.1 編碼器上電后的初始化時間絕對值編碼器上電后需要一定的初始化時間通常是幾百毫秒到幾秒不等。如果PLC上電后立刻開始發(fā)通訊指令編碼器可能還沒準(zhǔn)備好導(dǎo)致前幾次通訊失敗。我的做法是在程序里加一個上電延時比如用T0做一個3秒的延時延時到了再開始輪詢。7.2 485ADP-MB的站號設(shè)置FX3U-485ADP-MB作為Modbus主站時本身也有一個站號通過D8401設(shè)置。這個站號是主站自己的標(biāo)識和從站編碼器的站號是兩回事。有些新手會混淆這兩個概念把D8401設(shè)成編碼器的站號結(jié)果通訊異常。D8401設(shè)成0或者1都行只要不和從站沖突就可以。7.3 通訊電纜的選擇RS-485通訊建議用雙絞屏蔽線線徑0.5平方毫米以上。雙絞的作用是抵消差分信號上的共模干擾屏蔽層的作用是阻擋外部電磁干擾。我見過有人用普通的平行線做485通訊短距離低速還能湊合一旦距離超過20米或者波特率提高到19200以上通訊就很不穩(wěn)定。7.4 程序注釋和文檔記錄最后說一個不是技術(shù)但很重要的點(diǎn)程序注釋。ADPRW指令的S3參數(shù)是寄存器地址過幾個月回頭看根本記不住這個地址對應(yīng)編碼器的哪個參數(shù)。我習(xí)慣在程序里把每個ADPRW指令的站號、功能碼、寄存器地址、數(shù)據(jù)含義都注釋清楚這樣以后維護(hù)或者換人接手能省很多時間。同樣編碼器的通訊協(xié)議文檔、接線圖、參數(shù)設(shè)置最好整理成一個文檔存檔?,F(xiàn)場調(diào)試的時候可能覺得都記住了但過半年再回來改程序沒有文檔就得重新翻手冊。實(shí)操心得我一般會在PLC程序里留一個調(diào)試模式用一個M位控制。調(diào)試模式下ADPRW的觸發(fā)周期縮短到200毫秒方便快速觀察數(shù)據(jù)變化正常模式下觸發(fā)周期是1秒減少總線負(fù)載。這個技巧在多站輪詢的時候特別有用調(diào)試階段能快速定位是哪臺站出了問題。