|

【Maker電子學】Modbus over TCP 實作(上)

   

作者:Ryan Hu

在前兩篇文章(認識 Modbus協定Modbus RTU的傳輸資料格式)大致解釋完 Modbus protocol 後,接下來就是實作的部分。記得第一篇在談 Modbus protocol時有提到,這次要實現的系統架構長相,這是由於客戶希望可以透過 PC 去指定某個特定 IP 的 Modbus TCP Slave,讓它去控制底下的 Modbus RTU Slave。

比方說,總共有 3 組同網域中的不同 IP(即 Mobus TCP Slave,例如:192.168.1.3 and .4 and .5), PC(Modbus TCP Master)透過 Modbus TCP 傳輸自定義的 data content 給特定 IP(例如:192.168.1.3)的 Modbus TCP Slave,Modbus TCP Slave 在接到訊息後會自定義的 spec 去 decode 來自 Master 的 data content,接著 Modbus RTU Master(和 Modbus TCP Slave 是同一人)會利用 Modbus RTU 透過 RS485 傳送 decode 完的資料給特定 address 的 Modbus RTU Slave,如此就完成了控制。

這篇文章就會從上圖的右半邊 Modbus TCP(Slave)<——Ethernet——> Modbus TCP(Master)的部分開始說起,而下一篇就會接續實作剩下的左半邊,也就是 Modbus RTU(Master)對 Modbus RTU (Slave)(即這次的主角 — 電子標籤)。為了更清楚地展示實驗內容,我做了簡圖幫助大家快速理解:

(圖片來源:作者提供)

整體的硬體配置如上圖,因為我是用我的雷蛇筆電做開發,其本身不包含 RJ45 的網路孔,因此有兩個選擇,第一是利用 USB 外接網路卡神器,第二則是利用 WiFi(因為是在同個網域底下測試)。

另一邊的 ENC28J60 本身就是一個 Arduino,它是用來使用 Ethernet 很好的外掛 module,那當然就是利用它來搭起 AP 與 Uno 之間 Ethernet 的橋樑囉!

至於軟體方面,透過點亮或熄滅 UNO 上外掛的一顆 LED 作為實驗 Modbus TCP 的依據,藉此評判  Modbus protocol 是否被打通,畢竟一條 IP 打通了,要接個 10 條也不會是問題,只要 AP(或用 switch)LAN 孔夠多就行。

Modbus TCP Slave — UNO R3

現在就從 Modbus TCP slave 端開始吧!Slave 端我是利用 Mac 作為開發環境,而 ENC28J60 在網路上有相當多的資源可以參考,在此附上我使用的 Github repo 連結:EtherCard。repo README.md 有清楚地附上硬體接線,利用 SPI 和 UNO 做溝通,這部分我想照著做應該是不會出現太大的問題!當然,也還要準備 RJ45 網路線將 EtherCard 和家裡的 AP 接上。

軟體部分,我建議如果是 Mac 開發者,直接利用 Arduino 內建的 library manager 下載 EtherCard 這個 library,下載後開啟 library 底下的 testDHCP sample code 編譯燒錄,打開 console 看看是否有抓到 MAC address 和 My IP,如下圖:

(圖片來源:作者提供)

這個資訊很重要,是之後要作為 Modbus TCP slave 的資訊同時也是讓 TCP Master 辨別的依據。確定 ENC28J60 能順利運作後,接著就是重頭戲—Modbus protcol library for Arduino 了,由於網路上也有蠻多的資源,經過測試後在這邊也附上我認為最好用的 library github repo:modbus-arduino。這個 library 包山包海,不過我們只會用到 ModbusIP_ENC28J60 這個 directory 裡面的東西,此 dir 底下有四個 sample,我們會利用 Lamp 做實驗,看能不能順利透過 Modbus protocol 的 single bit coil 將 LED 點亮。

Lamp 的 sample code 中,可以看到 setup function 內的 mac 和 ip byte array,如下圖:

(圖片來源:作者提供)

將這兩個 byte array 的內容改成剛剛在 testDHCP sample 中得到的 MAC address 和 My ip,這是等等要註冊給 Modbus object(如圖片中最後那行 configuration)的資訊。

另外在 Lamp sample code 中也有一個值得分享的東西—LAMP1_COIL 這個常數。如同上篇介紹 Modbus protocol 時,提到 registers type 的概念,00001 – 09999 屬於 Coils 的部分,code 中 LAMP1_COIL 的 default 是 100(事實上在有效的範圍要設多少都是沒問題的)。

Slave 端的最後是最簡單的 LED,我將 GPIO 7 作為我的 LED pin,編譯燒錄後就一切就緒,只要保持接電狀態,搞定 Master 端後就萬事俱備了。

(圖片來源:作者提供)

Modbus TCP Master — Razer blade

由於客戶打算自己設計 PC 端程式,而我只是為了打通 Modbus over TCP,因此便在網路上尋找是否有免費的 Modbus 軟體能讓我做打通的測試,結果發現還不少,最終在眾多選擇中找到了一個比較好用的,稱作 simply Modbus

在 simply Modbus 的官網上,可從裡面看到許多先前在第二篇提到的名詞(例:RTU、ASCII、TCP),我們在這裡選用 TCP Client 的版本作為我們實驗的媒介(目前 simply Modbus 的軟體只有支援 Windows,Mac 並不支援!)

在上面 slave 的部分有提到,slave 端利用 single bit coil 對 Modbus 註冊 LED 的狀態,而由於 LED 只有兩個狀態 ON(HIGH)和 OFF(LOW),因此用 coil 綽綽有餘,在 Master 端直接 Write Coils 即可控制 LED 的亮滅!(對原理比較沒興趣的人也不用了解沒關係,因為 simply Modbus 有提供 UI 介面,選一選就可以了,然後下載後打開 Modbus TCP client 會看到下圖):

(圖片來源:作者提供)

在此僅說明必要操作的部分,其他部分有興趣的可以自行研究。首先,在 IP address 的 textbox 輸入剛剛在準備 Modbus TCP slave 端時,利用 testDHCP sample code 所獲得的 My IP(我的是 192.168.0.20),至於 port 502 是 Modbus default port 不用動,接著按下 CONNECT,若無誤,會如上圖顯示變為 DISCONNECT,表示確實連上了 Modbus TCP slave(即 UNO R3)。

然而,這個 UI 介面是給 read function 使用的,而我們要做的是 Write Coil,因此得按下上圖紅圈圈起來的 Write 的鍵,看到的畫面如下:

(圖片來源:作者提供)

上面分享 Modbus TCP slave 時有提到,由於 00001 – 09999 皆屬於 Coil 的有效範圍,所以我在這邊也做了一個小更改,將原先 default 的 100 改成如上圖圈圈內的 11(即 First Register 的 textbox);另外,其旁的 values to write 並不是對某個 register 進行值的設定,而是要對多少個 register 進行動作(詳見 function code 介紹的部分),而在此我只對 number 11 這個 Coil 動作,因此設為 1。

接著就是比較需要注意的地方,如圖可以看到我有圈 minus offset 的部分,必須為 0,因為若有值會導致位置錯誤而不動。最後就是真正的 value to write(最接近底部的圈圈),設定要 write 進 coil 的值,非 0 即 1,在此我設定了 1,然後按下 SEND,最後也如我所願地控制 LED 亮滅,Modbus TCP 的部分順利打通了。

(圖片來源:作者提供)

這邊給一個小提醒,若是照著上方步驟一步步將 Modbus 打通,在使用 simply Modbus 按下 SEND 的瞬間,LED 會動作沒錯,不過 simply Modbus 會顯示 error,說是 connection 的問題,這是正常的!因為 arduino uno 內的 sample code 所使用的 library 是 default 一旦收到東西就會先 close 那次的 connection。

談完整個 Modbus TCP 實作的過程後,下篇將介紹本次專案主角的部分 — Modbus RTU 實作,敬請期待。

(責任編輯:賴佩萱)

Ryan Hu
Hu Ryan

Author: Ryan Hu

對於 IOT 軟硬整合相關有極大興趣,鍾愛無人機,目前獨自完成的專案像是瓦力號、GPS 自動語音導覽系統、NTP 網路自動校時時鐘,喜歡流浪。

Share This Post On

1 Comment

  1. 文章內容對我相當有幫助,感謝您的分享

    Post a Reply

Submit a Comment

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *