#

Modbus是工業控制領域常用的通訊協定標準,像近代的PLC、電表、保護電譯、I/O模組...等,都會支援Modbus,如果你想要寫類似圖控軟體的程式,那Modbus將是必要學習的一門課。這一篇文章介紹如何使用modbus-tcl套件來和Modbus設備通訊,內容會介紹自製的modbus-tcl套件及其的使用方法,也會介紹一個支援Modbus的PLC模擬器,至於Modbus協定的細節,維基百科可以找到完整資訊,所以這邊就不會深入的介紹。

E06.1 Free Modbus PLC Simulator

為了方便我們接下來測試modbus-tcl,這邊需要請大家先安裝一個支援Modbus的PLC模擬器,請先到Free Modbus PLC Simulator Home找到你需要的版本,然後下載它,像下面的圖一樣:

圖 E06-1


下載後解壓縮就可以用了。注意哦!!最新版的軟體是需要註冊的,而較舊的版本則有提供註冊檔,請看到圖中紅包框的下方,有註冊檔可以下載。如果沒有註冊的話,程式還是可以正常的執行45分鐘,只是過了45分鐘程式後,程式就會一直提醒你要註冊,但只要重開程式它又會安靜的執行45分鐘。個人覺得我們只用來測試所以45分鐘很夠用了,因此我都下載最新的版本,然後等它跳出提醒再重開它就好。

□ 執行Modbus PLC模擬器

現在請執行模擬器,這個模擬器的使用介面蠻簡單的,只有幾個設定值需要注意。首先「紅色1」指示的位置可以讓你切換PLC內部的記憶體頁面,你可以依需求去設定PLC的接點、線圈或是暫存器的值,例如你要設定PLC的輸出線圈,就可以切到「Coil Outputs」,然後直接在「紅色2」指示的表格中編輯每一個線圈的設定值。「紅色3」可以用來指定這台模擬器聽取通訊埠,因為我沒有真的要透過RS-485來讀取它,所以這邊我選擇Modbus TCP,最後請勾取「紅色4」的方塊,然後用「紅色5」指示的按鈕來切換聽取Modbus TCP或是Commport。

圖 E06-2


如果都沒問題的話,當你按上圖「紅色5」指示的按鈕之後模擬器就會顯示目前正在聽取TCP。

圖 E06-3


E06.2 modbus-tcl介紹

modbus-tcl是一個用Tcl實作Modbus協定的套件,目前它支援Modbus RTU及Modbus TCP等兩種方式的通訊,且支援如下的功能:

  • 01 Read Coil Status (讀線圈)
  • 02 Read Input Status (讀輸入接點)
  • 03 Read Holding Registers (讀保持型暫存器)
  • 04 Read Input Registers (讀輸入暫存器)
  • 05 Force Single Coil (設定單一線圈)
  • 06 Preset Single Register (設定單一保持型暫存器)
  • 15 Force Multiple Coils (設定多個線圈)
  • 16 Preset Multiple Registers (設定多個保持型暫存器)

大家可以在它的官方網站,也就是...本站下載它~

下載modbus-tcl套件

□ 安裝modbus-tcl套件

下載完成後請把它解壓縮,然後放在你的Tcl library資料夾裡面。注意哦!! modbus-tcl需要tcllib裡crc16套件,所以你可能需要先用teacup安裝它,像下面:

teacup install crc16

接下來我們可以開始使用它了。

E06.2 設定及讀取線圈

現在讓我們先測試讀取線圈的值,讀取線圈的命令如下:

::modbus::cmd 0x01 id start len

上面的命令中,第一個參數永遠是01,因為在Modbus的標準裡讀線圈的Function code就是01,接下來的id可以是數值0~255的值,它用來表示要通訊的設備站號,start是要讀取的起始線圈編號,然後len是要讀取的線圈數量。

下面是一個程式的實例,它透過Modbus TCP去讀取設備站號1,線圈0~5的狀態。


package require modbus
::modbus::configure -mode "TCP" -ip "127.0.0.1" -port 502
puts [::modbus::cmd 0x01 0x01 0x00 0x06]

程式的第1行引入了剛剛下載的modbus-tcl套件,然後程式的第2行設定使用TCP模式(-mode)通訊,然後ip是127.0.0.1(-ip),port是Modbus TCP標準的502(-port)。成功的話程式會輸出6個0或1組成的清單,失敗的話會輸出空字串。這個例子會有類似下方的輸出:

0 1 0 0 1 0

注意哦!!上面的輸出會根據你在PLC模擬器上的設定來決定,所以你可以試試在模擬器上修改編號0~5的線圈,然後再執行上面的程式,看看輸出的結果。

另外,如果你真的有Modbus RTU的設備接在Commport上,那你可以把-mode設定為RTU,然後用-com指定通訊埠,用-settings設定通訊參數,這樣程式就會真的讀出設備線圈的狀態,例如在Windows下可以這樣設定:


::modbus::configure -mode "RTU" -com "com1:" -settings "9600,n,8,1"

或是在Linux下這樣設定:


::modbus::configure -mode "RTU" -com "/dev/ttyUSB0" -settings "9600,n,8,1"

□ 寫入單一圈線狀態

寫單一線圈的語法如下:

::modbus::cmd 0x05 id addr value

第一個參數永遠是05,因為在Modbus的標準裡寫單一線圈的Function code就是05,然後接下來的id可以是數值0~255的值,它用來表示要通訊的設備站號,接下來的addr是要寫入的線圈編號,然後value是0或是1用來表示要寫入的狀態。寫入成功的話回傳1,否則回傳0。

下面是一個程式的實例,它會把站號1,線圈5的狀態設定為1。


package require modbus
::modbus::configure -mode "TCP" -ip "127.0.0.1" -port 502
puts [::modbus::cmd 0x05 0x01 0x05 0x01]

□ 讀取輸入接點

讀取輸入接點的方法和讀取線圈是一樣的,唯一的不同點只有Function code,如果要讀取輸入接點的狀態,只要用改用02可以了,語法如下:

::modbus::cmd 0x02 id start len

E06.2 設定及讀取保持型暫存器

讀保持型暫存器的語法如下:

::modbus::cmd 0x03 id start len

就如同讀取線圈的命令,03是Modbus規定用來讀保持型暫存器的Function code,然後依序是站號(id),開始讀取的位置(start)及讀取長度(len)。命令執行成功的話會以清單的方式回傳每一個暫存器的值,失敗的話會回傳空字串。如下是一個使用的範例:


::modbus::configure -mode "TCP" -ip "127.0.0.1" -port 502
puts [::modbus::cmd 0x03 0x01 0x00 0x03]

因為我在模擬器上的暫存器0和2分別設定了1234和5678,所以我讀回來的值如下:

1234 0 5678

□ 寫入單一保持型暫存器

寫入單一保持型暫存器的語法如下:

::modbus::cmd 0x06 id addr value

就如同寫入線圈的命令,06是Modbus規定用來寫入保持型暫存器的Function code,然後依序是站號(id),寫入位置(addr)及寫入值(value)。寫入成功的話回傳1,否則回傳0。如下是使用的範例:


::modbus::configure -mode "TCP" -ip "127.0.0.1" -port 502
puts [::modbus::cmd 0x06 0x01 0x00 0x05]

這個例子會把站號1的設備,編號0的保持型暫存器填為5。

Theme Design by devolux.org. Converted by Wordpress To Blogger for WP Blogger Themes. Sponsored by iBlogtoBlog
This template is brought to you by : allblogtools.com | Blogger Templates