【物聯網篇】PHP通過Modbus Tcp實時獲取設備數據


前言:

        最近接觸了一個關於PLC工控的小項目,大概場景是,對方一個茶葉工廠。已經通過各種設備組成了自動化的工控系統。並且也讓我的一個朋友做了茶園監控和茶園天氣環境等的web頁面展示,但是還沒有工控設備的數據顯示。

需求:

        工控設備已經連接到了一台作為上機位的電腦上,所以要獲取設備數據。需要在同一局域網上,通過modbus tcp請求對方已經開放的端口。拿到數據儲存到數據庫,最后web界面只用按時間順序獲取數據庫的數據。

        因為訪問對方電腦需要他們提供授權,所以這里演示就以modbus的調試工具,以及后面PHP代碼請求示例。

 

工具:

1.  Modbus Slave: 從機端模擬軟件,這里測試可以把他作為服務端,PHP為客戶端就是取該機子的數據。

2.   Modbus Poll: 主機仿真器,用於測試和調試Modbus從設備,這里測試也只是把他當做客戶端使用。

3.   ModScan32:  主機/從機模擬程序 ,以后介紹。

4.   MThings:  一個國產免費軟件, 既可以模擬主機設備 又可以模擬從機設備,以后介紹。

以上軟件,可以掃描下面二維碼,輸入“modbus模擬” 獲取地址。

 

工具操作:

一.  Modbus Slave

1. 創建TCP/IP連接。

(1). 點擊connection->connection,彈出參數窗口,可以按下面確認。

(2). 配置函數,點擊setup->slave definition,彈出參數窗口,默認OK就可以。

(3). 修改某項數據的值,雙擊對應的框,彈出后修改OK就可以。

2. 從機參數說明:

(1). ID, 機子的設備標識,是slave definition的slave ID

(2). F, 當前節點的函數碼,主機獲取代碼獲取設置數據,需要指定的函數。

 

3. 查看發送和接收數據明細。

(1). 點擊display,彈出面板。

4. 注意

modbus slave每次連接只能維持10分鍾,可能是沒有激活。

 

一.  Modbus Poll

1.  通過Tcp獲取從機上的數據。

(1).  連接,點擊connection->connection, 選擇TCP/IP。

(2). 修改為slave機子對應的IP地址和端口,點擊保存。

 

(3). 連接成功后,查看讀寫定義,可以按指定slave配置修改。

(4). 連接失敗,Mbpoll面板會提示紅色字體。面板文字說明如下。

Tx = 4表示向主站發送數據幀次數,圖中為4次; Error = 0表示通訊錯誤次數,圖中為0次; ID = 1表示模擬的Modbus子設備的設備地址,圖中地址為1;F = 03表示所使用的Modbus功能碼,圖中為03功能碼; SR = 1000ms表示掃描周期。紅字部分,表示當前的錯誤狀態,“No Connection”表示未連接狀態。

(5). 查看讀寫數據。

 

PHP代碼演示:

1. modbus類庫包下載。

composer require adduc/phpmodbus

2. 編寫請求 "03 Read Holding Registers"函數示例代碼。

<?php /** * author: bqs * desc: 請求modbus地址 * 公眾號: ZERO開發 */ require_once 'vendor/adduc/phpmodbus/Phpmodbus/ModbusMaster.php'; // Modbus master UDP $modbus = new ModbusMaster("127.0.0.1", "TCP"); // Read multiple registers try { $recData = $modbus->readMultipleRegisters(1, 0, 5); } catch (Exception $e) { // Print error information if any echo $modbus; echo $e; exit; } var_dump($recData);die; // Print data in string format echo PhpType::bytes2string($recData); ?>

3. 環境要求。

1. PHP的LAMP環境已經搭建完畢 2. 可以不用配置虛擬域名,直接localhost訪問modubus_tcp_pro.php文件 3. PHP版本最好是5.5,因為7.0以上運行會對類的構造函數命名報錯 4. PHP5.5擴展開啟了php_sockets 5. 運行成功后,返回數據,數組的索引需要計算匹配modbus slave的地址名 6. 計算方式: (索引-1)/2

4. readMultipleRegisters說明。

參數1:unitId, modbus設備ID,參考slave的slave ID
參數2:reference, 地址號,在設備內存中,數據的地址引用,參考slave配置的地址
參數3:quantity,線圈,要去設備中讀取的數據量,參考slave配置的quantity

 

5. 請求異常的幾種情況。

(1). socket_connect() failed

slave的連接停止了,需要重新開啟。

(2). Modbus response error code: 2 (ILLEGAL DATA ADDRESS)

從機設備上數據的內容地址不對,可以根據slave的definition的參數,報錯可以查看ModbusMaster類的responseCode方法。

請求的quantity數超過slave定義的quantity數量也會報內容地址錯誤,請求只能小於定義的數量。

6.  關於返回的數組。

如果請求的是5個數據,phpmodbus會返回元素為10的數組。如果是2個,則返回4個元素數組,以此類推。

7. 關於返回數組與slave的數據塊地址數據對應的方式。

8. 獲取設備上指定數據塊的實際的數據。

(1). 枚舉某數據塊下索引對應的標識。

// 數據庫設備的數據描述 $devicesDataBlock = [ "0" => "weather", "1" => "water", "2" => "voice", "3" => "electric", "4" => "air" ];

(2).  根據返回數組的過濾出有用的索引,並匹配設備數據標識。

實際的數據塊索引 = (返回數組的索引-1)/2 

前提處於2的不能有余數,所以只需要對結果做判斷,完整代碼如下。

<?php /** * author: bqs * desc: 請求modbus地址 * 公眾號: ZERO開發 */ require_once 'vendor/adduc/phpmodbus/Phpmodbus/ModbusMaster.php'; // Modbus master UDP $modbus = new ModbusMaster("127.0.0.1", "TCP"); // Read multiple registers try { $recData = $modbus->readMultipleRegisters(1, 0, 5); } catch (Exception $e) { // Print error information if any echo $modbus; echo $e; exit; } // 數據庫設備的數據描述 $devicesDataBlock = [ "0" => "weather", "1" => "water", "2" => "voice", "3" => "electric", "4" => "air" ]; $realData = []; foreach($recData as $key => $value) { $indexs = ($key-1)/2; if (($key-1)%2 == 0) { $realData[$devicesDataBlock[$indexs]] = $value; } } var_dump($realData);die; // Print data in string format echo PhpType::bytes2string($recData); // 00050000000601030000000A ?>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM