2008年12月9日 星期二

充電一下 -- MODBUS 通訊技巧

前文提到MODBUS的傳送格式

至於接收的部分

我想跳過編碼的介紹

直接介紹通訊間的一些問題

編碼的部分

上一篇文章中所提供的PDF文件

有很完整的描述

只是內容是英文的

如果有人看了不太能理解的

再告訴我一聲吧~~~



我們都曉得

根據MODBUS所制定的格式來看

裝置端(slave)在接收指令的負擔是很輕的

以RTU模式來看

只要8Bytes就完成一組指令了

ASCII的話也只要17Bytes就搞定 (1+8x2)



但是回應的時候

RTU長一點就可能要30~40個Bytes

(假設一次要拿16組資料, 每組都2 Bytes)

同樣的ASCII就要近80Bytes 的資料在傳~~~

對於暫存區空間較少的MCU來說

這是一個夢魘!!!

因為通訊時別台裝置的回應碼

不單單只是回應給主控端

還同時會傳給其它的裝置端

如果串列中斷裡沒有規劃好因應的對策

災難很快就會發生

要不是系統的堆疊會爆掉

就是串列資料不小心改掉堆疊的內容

讓程式進入亂七八糟的鬼上身狀態



規劃的方向有幾個重點

提一下概念給大家思考看看





1. Timeout 機制 (逾時中止)



Timeout是MODBUS通訊中一定會用到的第一個概念

特別是在RTU傳送模式下

因為通訊碼裡面並沒有結束碼的設計

所以只能透過"經過多久時間沒有在送資料"來判斷它已經結束了



這個等待時間一般來說是5~10 個Bytes的時間間隔

拿9600bps的鮑率來看

1個Byte約需1mS

那麼適當的Timout時間就是5mS~10mS



為什麼要這樣設定?

因為資料在傳送的過程

主控端有可能受到其它多工運作的影響

導致指令並不是連續送出來的

把Timeout設得太低

有可能當指令傳到一半時

裝置就開始分析指令了

這樣一來

指令分析一定會錯誤

裝置也就不會正確動作及回應了!!





2. 循環指標歸零時機



一般在設計通訊碼的暫存空間

會使用循環旗標

意思就是讓暫存器透過串列中斷一直存放資料

不要去管內容是什麼

每存一個Byte指標就+1



當發生Timeout

或是旗標已經加到陣列的邊界

才把旗標歸零



分析指令時

如果是第一種歸零時機

通常是正確的通訊碼

第二種則是部分資料被覆蓋的不完整碼

透過歸零時機的判斷

可以拿到正確的通訊資料





3. 善用ASCII的啟始碼與結束碼



在ASCII的模式下

:是啟始碼

CRLF是結束碼


只要遇到啟始

就自動擺到暫存空間的最前面

遇到結束碼就立刻分析資料

這樣就能保證資料一定是從頭開始而且是完整的





以上

就是MODBUS的必勝秘訣

如果能依照這樣的原則來寫程式

一定可以避開很多莫須有的怪問題





不過

很多實際的應用還是會有出乎意料的狀況

此時就要善用示波器來觀察通訊的波形是否正確了~~~

19 則留言:

  1. 大大,想跟你請教一下有關modbus RTU mode的問題,由於我是剛開始碰這個的,想問一下

    RTU mode是不是由device address + function code + data + CRC check組成的,

    因為我現在要在linux c上寫一個讀modbus RTU mode的小程式,我是否先用write值到slave

    在用read就可以? 如果打擾到您,不好意思

    回覆刪除
    回覆
    1. 1. 站號 -- 2. 指令 -- 3. 資料位址 -- 4. 資料長度 -- 5. 檢查碼

      這是我在另外一篇文章上提到的MODBUS格式
      所以照你的說法來看
      你還少了一個data address
      正確的格式應該是
      device address + function code + data address + data + CRC check
      這樣才是正確的

      通訊時要留意一下資料長度
      因為詢問跟回應的資料長度是不一樣的
      先試試看吧!

      刪除
  2. 謝謝大大,我剛發現我送01 04 11 00 02 74 F7,它回傳給我01 04 04 45 EC 43 63 5E 64

    ,我在用廠商給我的格式去解45 EC 43 63,就可以解出值了,還有大大,我想問一下,如果我要在

    ulinux上把這01 04 11 00 02 74 F7送給機器,一開始是先用open("/dev/ttyS1", RDWR);

    再來是用write到open這個檔案描述值,再read這個檔案描述值,這樣就可以了嗎?

    **因為板子現在不在我手上,無法試ulinux上,所以先問一下大大觀念,謝謝!

    回覆刪除
    回覆
    1. 我沒用過ulinux
      所以也不曉得該怎麼建議你
      概念就是資料丟完要馬上收
      如果等待時間長一些才收
      很可能就收不到正確值

      刪除
  3. 請問大大有即時通或MSN嗎?!

    因為最近有些通訊上的問題想請教

    我現在有一台變頻器是要走MODBUS的通訊

    我用MODBUS的測試軟體可以通訊上

    可是我現在想用VB去連,但是卻連不上

    MODBUS他是不是只是把通訊的指令都設定好,然後我們再照著他的方式去做設定就可以使用了對吧?!

    我現在想要知道的是實際上MODBUS他傳出去的碼到底是什麼!

    如果知道了,是不是也就可以用VB下去寫MODBUS了?

    像我現在只是用VB丟個廠商給我的參數暫存器的字串下去測試

    可是都沒接收到回傳資料

    通訊上的設定我檢查過了9600.n.8.1

    問題有點多~"~

    可以幫我解答或是給我個參考資料嗎?!

    還是給我一些人多一點的技術論壇(很多都沒人...)

    回覆刪除
    回覆
    1. 所有modbus的指令都參照我在文章中分享的資料
      只是要看你用RTU模式或是ASCII模式
      如果是RTU模式的話
      在VB中指令要以byte的格式傳送
      而ASCII要以字串的格式傳送

      傳送上的概念雖然是這樣
      但是牽涉到PC系統規劃的問題
      還有很多硬體相容的問題

      VB並不能調整電腦傳送的方法
      除非您可以自己用C重新寫過VB的通訊元件
      不然應該會遇到不少問題(非軟體問題, 而是韌體)

      我沒有在用即時通
      MSN也很少開
      你可以在這裡留言就好
      我會撥空回答

      印象中介紹modbus的網站很多
      只要您google一下就有了
      關鍵字用"modbus rtu" 或 "modbus protocol"
      這樣應該就可以找到很多相關資料了
      中文網站介紹得很少
      大多數是英文網站
      如果不排斥簡體的話
      也可以上大陸的百度去找看看
      祝您順利!!

      刪除
  4. 大大,你好,不好意思,請教一下,我現在要在mcu上使用modbus rtu的協定,

    只是我從mcu上傳送data到slave端,可是slave端都沒有反應,可是我有用

    邏輯分析儀去看送的的資料,01 04 11 00 02 74 F7是這樣沒有錯,我用PC

    送01 04 11 00 02 74 F7,slave就有反應,可是用mcu就沒有反應,想請問

    這是什麼原因?

    回覆刪除
    回覆
    1. 1. 確認信號的準位夠不夠
      2. 鮑率設定有沒有問題(石英晶體的誤差要考慮進去)
      3. IO腳位的狀態設定是否正確(輸出後要把IO腳改為輸入腳)

      如果都不是
      那就是靈異現象 (可能MCU某部分已經異常了)

      刪除
  5. 大大您好

    小弟目前正在用GE-9030型的PLC

    由於日前有廠商送給學校一塊CMM321的通訊模組(乙太網路)

    目前老師丟給我們的議題是讓PLC不透過VersaPro(PLC程式編譯軟體)

    就可控制PLC的開關,想問一下大大能否提點一下



    小弟的MSN:b9607129@hotmail.com

    回覆刪除
    回覆
    1. 最簡單的開始
      就是先把原廠商丟的碼記錄下來
      改用不同的軟體再把同樣的碼丟一次
      看看通訊正不正常

      如果正常了
      再把可以使用的指令模組化
      這樣應該就OK了!!

      不過您的問題很大
      因為我不曉得您要用PC來通訊
      還是用控制板來通訊
      所以就先給個概念

      最近老婆做月子
      我都在月子房幫忙
      所以可能沒辦法上MSN
      有問題可以丟在這裡
      我有空再上來回......
      祝您順利~~

      刪除
  6. 目前就差在要如何使用winsock連上PLC進行資料交換, 若可以連上再用

    MODBUS的06H的功能傳送訊息,使開關動作,目前我們用廠商給的MODBUS軟

    體都可以動作.



    想問一下大大是否懂winsock所要注意的事項

    回覆刪除
    回覆
    1. winsock我沒用過
      如果一定要用的話
      建議先K一下winsock的架構
      看看通訊封包的組成如何
      硬體有沒有辦法把你所送的訊息解開成單純的MODBUS碼

      刪除
  7. 目前有一個疑問是

    我使用winsock來傳送資料給plc

    但是winsock必須要有一個sever端傳送資料

    一個client端接收資料

    但是PLC要如何寫入一個client程式來接收資料



    目前使用廠商給的modscan軟體 已經知道如何控制開關

    但現在唯一問題就是不知如何使用winsock來傳資料

    回覆刪除
    回覆
    1. 上網google一下winsock的編程方式
      我想應該有蠻多資料的
      不要排斥英文的資料
      因為大多數不錯的範例都是英文的
      祝你順利


      http://read.pudn.com/downloads117/ebook/498655/Winsock%20programming.pdf
      這裡有提到winsock的架構
      請先問一下廠商你的硬體設定如何
      再照這份文件的概念試試看

      刪除
  8. 嗯嗯~~ 先謝謝你囉

    回覆刪除
  9. 不好意思 又來麻煩您了, 最近的問題是 mbMasterV7.ocx 不知道如何載

    入到project當中. 不知您最近有空可以看一下我寫的程式嗎??

    回覆刪除
    回覆
    1. google一下 "如何引用ocx檔"
      這樣可以找到不少相關資料

      刪除
  10. 請問一下我有一個問題,困擾很久了,關於控制 IC 部份我要選一ㄍ比較好

    回覆刪除
    回覆
    1. 請問你要做什麼應用呢?
      基本上學習MODBUS我都會建議在PC上模擬就好
      因為這樣可以避開硬體問題
      減少因電路異常或是雜訊干擾所衍生的不正常現象
      等到確定通訊格式都熟悉之後再應用到MCU上
      事實上只要有UART功能的IC都適合用在MODBUS協定上
      只是因為MODBUS的用法在大型系統上需要較多的記憶體空間
      所以這部分可能是您所要考量的主要方向

      刪除