Introduction to Modbus using LabVIEW

綜覽

The Modbus industrial protocol was developed in 1979 to make communication possible between automation devices. Originally implemented as an application-level protocol intended to transfer data over a serial layer, the protocol has expanded to include implementations over serial, TCP/IP, and the user datagram protocol (UDP). Today, it is a common protocol used by countless devices for simple, reliable, and efficient communication across a variety of modern networks.

Contents

Modbus 簡介

一般來說,Modbus 會用於裝置之間的監控與資料擷取 (Supervisory Control and Data Acquisition,SCADA) 類型的網路通訊。 舉例來說,大型的伺服器可能會用來管理程式化邏輯控制器 (PLC) 或程式化自動控制器 (PAC),PLC/PAC 則是用來管理感測器、閥門、馬達或其他各種嵌入式裝置。

為了滿足這些需求,Modbus 被設計成一種「需求-回應」協定,具有靈活的資料與函數模式,這也是此協定仍然沿用至今的原因。

「需求-回應」週期

Modbus 協定採用了主從架構,主要裝置會把需求傳送給附屬裝置,並且等候回應。 此架構讓主要裝置全權控制資訊流動,因此對舊型的多分支序列網路而言相當實用。 就算是現代的 TCP/IP 網路,主要裝置也可掌握高度的附屬裝置行為控制權,非常適合某些設計。

1. Modbus 裝置之間的主要裝置-附屬裝置、需求-回應關係

就 Modbus 而言,這種需求會是一組分層式資料。 第一層是應用資料單元 (ADU),也就是大多數人認為所使用的 Modbus 類型。 ADU 共有三種: ASCII、遠程終端單元 (RTU)、TCP/IP。

TCP 這種現代格式可透過軟體有效處理 Modbus 的需求和回應,還能夠透過每項需求專屬的連線和識別碼,達成有效的網路連線。 RTU 和 ASCII 都是較舊的序列 ADU 格式,兩者主要的差別在於,RTU 採用精密的二進制呈現格式,ASCII 則會把所有的需求當成 ASCII 字元串流加以傳送。

大部分的應用會偏向採用 ADU,但也取決於想要的實體網路 (乙太網路、序列或其他類型)、網路內的裝置數量、網路內主要裝置與附屬裝置可支援的 ADU。 就採用 Modbus 的應用而言,應該直接呈現資料,就像 ADU 不存在一樣。

每個 ADU 都有一個協定資料單元 (PDU),也就是 Modbus 協定的核心。 每個 PDU 則包含了函式代碼和相關資料。 每個函式代碼都具有定義完整的回應,我們可以把這個函式代碼當成要送給附屬裝置的指令。

有時候可能會出現錯誤。 Modbus 會針對例外情況定義特定的 PDU,以便讓主要裝置掌握狀況。 大部分的驅動程式還會進一步轉換成所使用語言或應用程式可以理解的格式。

Modbus 資料模式

Modbus 能夠以簡便有彈性的方式管理資料存取。 Modbus 本身即可支援兩種資料類型: Boolean 值和無正負號的 16 位元整數。

就 SCADA 系統而言,嵌入式裝置經常會把某些數值定義為輸入值,例如增益或比例積分微分 (PID) 設定,其他則是輸出值,例如目前的溫度或閥門位置。 為了滿足此需求,Modbus 資料值會分為四個範圍 (表 1)。 附屬裝置可針對每個範圍定義高達 65,536 個元素。

記憶體區塊資料類型主機裝置存取附屬裝置存取
CoilBoolean讀/寫讀/寫
離散輸入Boolean僅讀取讀/寫
保存暫存器無正負號字詞讀/寫讀/寫
輸入暫存器無正負號字詞僅讀取讀/寫

表 1. Modbus 資料模式

在很多情況下,感測器和其他裝置所產生的資料類型不只有 Boolean 和無正負號整數。 因此附屬裝置通常會把這些較大的資料類型轉換成暫存器。 舉例來說,壓力感測器會在兩個 16 位元的暫存器之間劃分一個 32 位元的浮點數。

Modbus 會以徹底的概念方式呈現這些數值,也就是說,這些數值可能不會實際存在於記憶體內。 舉例來說,附屬裝置的定義可能是保存暫存器和輸入暫存器會共用記憶體,前提是這對附屬裝置而言屬於合理行為。 在大多數情況下,附屬裝置會把可支援的資料類型儲存在不同的記憶體內,並且限制主要裝置可存取的資料元素數量。 這種彈性取決於透過 Modbus 函式代碼完整定義的行為而呈現資料的方式。

Modbus 函式代碼

Modbus 函式代碼決定了主要裝置存取並修改資料的方式。 不同於概念性質的資料範圍,函式代碼具有定義完整的行為。 如果附屬裝置必須執行某個函式代碼,就會使用此函式的參數來執行這個定義完整的行為。 圖 2 顯示了函式需求和此裝置實際記憶體之間的關係。

圖 2. 函式代碼、資料範圍、附屬裝置實際記憶體之間的對應關係

常見的函式代碼都是根據所修改或存取的概念資料範圍而命名的。 舉例來說,「read holding registers」會從定義為保存暫存器的記憶體中擷取資料,並且傳回主要裝置。 表 2 列出了最常見的函式代碼。

表 2. 常見的函式代碼

開始使用 Modbus 搭配 LabVIEW

NI 提供三種主要的 Modbus 裝置銜接機制: (1) 高階 OPC 伺服器、(2) Modbus I/O 伺服器,以及 (3) 初階 Modbus API (NI LabVIEW 2014 軟體透過 LabVIEW Real-Time Module 或 LabVIEW 資料記錄與監控 (DSC) 模組所推出的新功能。

LabVIEW Modbus API

如果您的應用必須高度控制 Modbus 需求的序列與時序,初階的 Modbus API 就會是相當理想的選項。 如果關鍵需求還包含了靈活彈性,通常也會選用初階 API。 相對的,LabVIEW Modbus API 可提供彈性和功能,這也代表應用程式碼必須具有一定的複雜度,才能夠管理 API。 為了協助您了解這種複雜度,LabVIEW 提供了兩個範例。

Modbus 準備範例

第一個範例是 Modbus Library.lvproj,提供了 API 功能的基本概述。 此外也說明了實作 PC 與 Real-Time 目標系統之間的差異。 圖 3 顯示了 Real-Time Modbus Master 範例的程式碼。

圖 3. Master on RT Target.vi

這個範例說明了使用 LabVIEW API 的時候,Modbus 應用的核心需求。 首先會建立一個 Modbus 實體。 在此情況下,這個實體會是一個 TCP 主要裝置。 然而,您也可以使用多元實體選擇器,藉此把這個範例切換至序列主要裝置。

圖 4. 改變 Modbus 主要裝置的類型

建立實體之後,就可以開始輪詢附屬裝置以取得資料。 此範例採用了 Read Input Registers 這個函式代碼。 這個 API 可支援的所有 Modbus 函式代碼都會顯示在對應的面板中。 因為實作協定的關係,附屬 API 具有主要裝置無法實作的額外函式。 舉例來說,附屬裝置可以寫入輸入暫存器範圍,但是主機裝置僅能讀取此範圍。 圖 5 顯示了函式代碼。

圖 5. Modbus Master 和 Modbus Slave 面板顯示了函式代碼

最後會關閉 Modbus 實體,取消分配此實體的相關記憶體。 這樣一來也會關閉所有的參考,包含此實體所使用的 TCP 連線或 NI-VISA 序列參考。

目前僅討論了主要裝置範例;但是基本上每個範例皆採用了大多數 LabVIEW 使用者都很熟悉的基本架構: 開啟、讀/寫、關閉。

最後,雖然 API 看起來一模一樣,但還是要了解其中的主要區別。 如果您的裝置是一個主要裝置,就必須透過網路把需求傳送至合適的附屬裝置,進而擷取資料。 另一方面,附屬裝置擁有自己的本端資料儲存空間,可以快速存取。

備援主要裝置範例

這個基本範例或許可滿足某些應用需求;但如果有些複雜的應用必須與感測器或閘道通訊,可能就無法派上用場。 為了克服這個問題,可透過一項簡易的應用項目,用兩個主要裝置與一個附屬裝置通訊。 如果其中一個主要裝置無法與附屬裝置或人機介面 (HMI) 通訊,另一個主要裝置就可以接管此功能。

圖 6. 備援主要裝置範例設計

如果這種設計可以滿足您的應用需求,或者您想要了解更複雜的 Modbus 通訊範例,請參考 Example Finder 內的 Redundant Modbus Masters.lvproj

Modbus I/O 伺服器

Modbus I/O 伺服器位於 LabVIEW DSC 模組和 LabVIEW Real-Time Module 內,可透過 Modbus 提供高階的通訊引擎。 您不必指定想要傳送的函式代碼,而是記錄想要存取的資料集,I/O 伺服器就會根據所指定的速度自動安排需求。

如要使用 I/O 伺服器,可把全新的 I/O 伺服器加入專案中所需的目標系統。 至於初階 API,可選擇 Modbus 主要或附屬裝置,這樣一來就會產生額外參數。 舉例來說,主要裝置具有已定義的輪詢率,也就是需求送至附屬裝置的速度;同時,附屬裝置必須等待這些需求,也沒有事先定義的時序。

建立 I/O 伺服器之後,必須指定想要讀取的裝置項目。 不同於您必須自行產生並處理需求的初階 API,Modbus I/O 伺服器可供選擇豐富的格式與資料類型。 舉例來說,您可以把變數對映至項目 400001,進而讀取位於位址 0 的保存暫存器;選擇 400001.1 以讀取這個暫存器的第一個位元;最後選取 F400001,讀取儲存於暫存器 0 和 1 的單精度浮點資料。

選取好要存取的變數之後,即可使用程式方塊圖上的共用變數節點,進而讀取或寫入這些變數。 甚至可以針對變數名稱設定別名。

圖 7. 簡易的 I/O 伺服器應用

I/O 伺服器應用幾乎不需要程式設計,而且簡單好懂。 然而請記得,簡單好用的特性也是有限制的。 資料僅能以預先定義的速度更新,而且無法在 Run Time 新增或移除資料需求。 如果您的應用可以接受這些限制,即可考慮選擇 I/O 伺服器這種跨平台選項。

如需更多資訊和逐步指南,請參閱透過 Modbus 把 LabVIEW 連接至各種 PLC 一文。

NI OPC 伺服器搭配 OPC I/O 伺服器或 OPC UA

如果複雜的應用涉及了許多附屬裝置,而且必須透過不同的協定彼此通訊,那麼標準的 Modbus I/O 可能會不夠用。 常見的解決方案就是使用 OPC 伺服器,這個伺服器會做為所有系統的資料聚合器,接著使用 LabVIEW DSC 模組隨附的 OPC I/O 伺服器與 OPC 伺服器通訊。

圖 8 為此架構範例,NI OPC 伺服器使用 Modbus 直接和感測器通訊,同時使用 OPC UA 和 NI CompactRIO PAC 通訊。 等到資料聚合至 NI OPC 伺服器之後,OPC I/O 伺服器就會擷取資料,並且與 LabVIEW 應用程式共用此資料。

圖 8. 使用 Modbus、NI OPC 伺服器和 OPC I/O 伺服器的 SCADA 應用

您也可以使用 LabVIEW DSC 模組中的 OPC UA 驅動程式,取代 OPC I/O 伺服器,開發出類似的架構。 然而,OPC UA 驅動程式屬於初階的驅動程式,不像 OPC I/O 伺服器那樣簡單好用。

如要開發這種應用程式,必須產生有效的 NI OPC 伺服器設定,以便和附屬裝置通訊。 這樣一來就得先產生通道 (藉此定義驅動程式設定) 與裝置 (藉此定義驅動程式的個別終端)。 裝置設定完成之後,就可以產生標籤。

圖 9. 針對上述架構的 NI OPC 伺服器設定範例

完成 NI OPC 伺服器設定之後,即可設定 OPC I/O 伺服器,以便和這些標籤通訊。 設定 Modbus I/O 伺服器是為了存取暫存器,設定 OPC I/O 伺服器則是為了存取 OPC 伺服器的標籤。

圖 10. 設定 OPC I/O 伺服器

這個綁定程序會產生之後可用於應用程式中的變數。

圖 11. 使用 OPC I/O 伺服器的簡單應用程式

如需完整的程序說明,請參閱透過 Modbus 把 LabVIEW 連接至各種 PLC 一文。

滿足您的應用需求

Modbus 是一種簡單的協定,可透過多種方式實作出強大的應用。

針對 Modbus 通訊,NI 提供三種主要選項,其中囊括了豐富的功能,有助於滿足應用需求。 第一,初階 API 可深入控制協定,提供出色的效能,但是不太容易使用。 使用初階 API 的時候,一切都要靠自己動手。 針對較簡單的監測應用,Modbus I/O 伺服器提供更簡單方便的 API,能夠存取或提出 Modbus 資料。 方便好用的 I/O 伺服器犧牲了深入的協定控制效能,這也是某些應用項目的需求。 最後,大型的複雜系統可考慮選用全功能的 OPC 伺服器,此伺服器可充當資料聚合器。 這樣一來,只要使用 LabVIEW OPC UA 驅動程式或 OPC I/O 伺服器之類的工具,即可讓應用程式存取資料。