php对接Modbus设备详细讲解

Posted 泽一年

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了php对接Modbus设备详细讲解相关的知识,希望对你有一定的参考价值。

1、下载ModbusMaster类库文件

参考地址:https://hotexamples.com/examples/-/ModbusMaster/-/php-modbusmaster-class-examples.html

下载地址1:https://github.com/sergejey/majordomo-modbus    //功能码比较全,无案例

下载地址2:https://github.com/krakorj/phpmodbus  //类库功能码少,有案例

工具:

1.  Modbus Slave: 从机端模拟软件,这里测试可以把他作为服务端,PHP为客户端就是取该机子的数据。

2.   Modbus Poll: 主机仿真器,用于测试和调试Modbus从设备,这里测试也只是把他当做客户端使用。

3.   ModScan32:  主机/从机模拟程序 ,以后介绍。

4.   MThings:  一个国产免费软件, 既可以模拟主机设备 又可以模拟从机设备,以后介绍。

工具操作:

一.  Modbus Poll

1. 创建TCP/IP连接。

(1). 点击connection->connection,弹出参数窗口,可以按下面确

(2). 修改为slave机子对应的IP地址和端口,点击保存。

 

(3). 连接成功后,查看读写定义,可以按指定slave配置修改。

配置函数,点击setup->Read/Write Definition,弹出参数窗口,默认OK就可以。

Slave ID:设备从地址ID

Function:功能码

 

 

 

(4). 连接失败,Mbpoll面板会提示红色字体。面板文字说明如下。

Tx = 4表示向主站发送数据帧次数,图中为4次; Error = 0表示通讯错误次数,图中为0次; ID = 1表示模拟的Modbus子设备的设备地址,图中地址为1;F = 03表示所使用的Modbus功能码,图中为03功能码; SR = 1000ms表示扫描周期。红字部分,表示当前的错误状态,“No Connection”表示未连接状态。

(5). 查看读写数据。

 

 

 

 

 

FC3读取参数功能码PHP案例(readMultipleRegisters)

FC3参数讲解

require_once (__FILE__) . \'/modbus/ModbusMaster.php\';
// Create Modbus object
$modbus = new ModbusMaster($HOST, $PROTOCOL);
// FC3
$recData = $modbus->readMultipleRegisters($DEVICE_ID, $REQUEST_START, $REQUEST_TOTAL);

注释:
HOST: modbus设备IP地址
PROTOCOL:通讯协议(TCP/UDP)
DEVICE_ID:设备从地址(slave ID)
REQUEST_START:寄存器地址起始位置
REQUEST_TOTAL:要读多少个数据。当想读五个监控项数据时,返回的数据是做了转换的,返回的是有十个键值的一维数组,需要两两16进制合并在转换10进制才可得到真实值。

FC3读取参数php demo

require_once (__FILE__) . \'/modbus/ModbusMaster.php\';

// Create Modbus object
$modbus = new ModbusMaster("192.168.0.15", "TCP");
try 
    // FC3
        $recData = $modbus->readMultipleRegisters(1, 0, 5);

catch (Exception $e) 
    // Print error information if any
    echo $modbus;
    echo $e;
    exit;

// 获取到的$recData数据需要做一下转换

foreach($recData as $k =>$v)
        $recData[$k] = ($v); //转换成16

$con = [];
for($i=0;$i<($recData);$i++)
        $res = $i%2;
        if($res == 0)
                $str16=$recData[$i].$recData[$i+1]; //两两合并
                $con[] = ($str16); //转换成十进制
        

($con);die;

FC5写入单个状态功能码PHP案例(writeSingleCoil)

FC5写入单个状态php demo

require_once (__FILE__) . \'/modbus/ModbusMaster.php\';

// Create Modbus object
$modbus = new ModbusMaster("192.168.0.100", "TCP");
// Data to be writen
$data_set = array(TRUE);
try 
    // FC5
    $modbus->writeSingleCoil(1, 0, $data_set);

catch (Exception $e) 
    // Print error information if any
    echo $modbus;
    echo $e;
    exit;


// Print status information
echo $modbus;

FC6写入单个参数功能码PHP案例(writeSingleRegister)

FC6写入单个参数php demo

require_once (__FILE__) . \'/modbus/ModbusMaster.php\';

// Create Modbus object
//$modbus = new ModbusMaster("192.168.0.100", "UDP");
$modbus = new ModbusMaster("192.168.0.14", "TCP");
// Data to be writen
$data_set = array(16000);
$dataTypes = array("INT"); 
$swapregs = false;
try 
    // FC6
        $recData = $modbus->writeSingleRegister(1, 0, $data_set, $dataTypes, $swapregs);

catch (Exception $e) 
    // Print error information if any
    $rec[\'LOG\'] = (\'Y-m-d H:i:s\') . " FC6 Error: $modbus $e\\n" . $rec[\'LOG\'];
    exit;


// Print status information
echo $modbus;

 

物联网RTU(Modbus TCP协议)Java接口开发及Modbus Slave仿真使用

  在物联网体系中,经常用到RTU(远程终端单元),RTU是负责对现场信号、工业设备的监测和控制,通常由信号输入/出模块、微处理器、有线/无线通讯设备、电源及外壳等组成,由微处理器控制,并支持网络系统。

  在物联网应用平台上,需要通过RTU与现场设备对接,采集现场数据、控制设备,通过网络与RTU连接,主要是采用Modbus TCP协议。

  Modbus是应用于电子控制器上的一种通用语言。通过此协议,控制器相互之间、控制器经由网络(例如以太网)和其它设备之间可以通信。它已经成为一种通用工业标准。有了它,不同厂商生产的控制设备可以连成工业网络,进行集中监控。此协议定义了一个控制器能认识使用的消息结构,而不管它们是经过何种网络进行通信的。它描述了一个控制器请求访问其它设备的过程,如何回应来自其它设备的请求,以及怎样侦测错误并记录。它制定了消息域格局和内容的公共格式。

  物联网应用软件开发,需要与RTU接口,为了方便软件开发,降低对物联网设备的依赖,Modbus仿真软件也就出现,对此,物联网开发人员应该很熟悉,但是对于普通互联网开发人员,还是很陌生的,为此,此文介绍ModbusTCP仿真软件使用和基于Netty的RTU java接口开发。

1、ModbusTCP仿真

  ModbusSlave(软件官方网站地址)是一个从站设备仿真软件,它用于接收主设备的命令包,并回送数据包;可用于测试和调试Modbus主站设备,便于观察Modbus通信过程中的各种报文。ModbusPoll及ModbusSlave支持ModbusRTU, ASCII,TCP/IP等协议。

  首先,了解MODBUS支持的部分功能代码,以十进制表示,如下表所示。

代码中文名称英文名称位操作/字操作操作数量
01读线圈状态READ COIL STATUS位操作单个或多个
02读离散输入状态READ INPUT STATUS位操作单个或多个
03读保持寄存器READ HOLDING REGISTER字操作单个或多个
04读输入寄存器READ INPUT REGISTER字操作单个或多个
05写线圈状态WRITE SINGLE COIL位操作单个
06写单个保持寄存器WRITE SINGLE REGISTER字操作单个
15写多个线圈WRITE MULTIPLE COIL位操作多个
16写多个保持寄存器WRITE MULTIPLE REGISTER字操作多个

  参数设置:
  点击菜单“Setup”中“Slave Definition.. F2”进行参数设置,会弹出如下图对话框

  其中:
  (1)Slave ID:设备ID;
  (2)Function:对应上表所对应的Modbus功能,例如本文所选用的“03 Holding Register…”,与下文Java代码“见类ReadHoldingRegistersResponse ”所对应
  (3)Address:寄存器地址;
  (4)Quantity:数量。

  打开ModbusSlave软件,为方便起见,本文采用默认的地址(localhost,与下文第二段代码对应“见类ClientForTests ”),功能码,寄存器数量,单击Connection->connect,在弹出的窗口设置connection为TCP/IP,端口Port设置为30502,点击OK,如下图所示,从端配置完毕。

  注意:
  (1)本文连接Connection采用Modbus TCP/IP协议;
  (2)网络地址为本地地址,127.0.0.1;
  (3)端口与下文第二段代码“见类ClientForTests”中的地址和端口设置为“30502”;
  (4)选择“Ignore Unit ID”,如果不选择,测试程序返回空值。

2、基于Netty实现RTU接口

  本文Java代码,来源于modjn(https://github.com/klymenek/modjn),基于Netty 4.x实现Modbus TCP客户端和服务端(Modbus TCP client/server implementation in Java with Netty 4.x)。

package de.gandev.modjn.example;

import de.gandev.modjn.ModbusClient;
import de.gandev.modjn.entity.exception.ConnectionException;
import de.gandev.modjn.entity.exception.ErrorResponseException;
import de.gandev.modjn.entity.exception.NoResponseException;
import de.gandev.modjn.entity.func.response.ReadCoilsResponse;
import de.gandev.modjn.entity.func.response.ReadHoldingRegistersResponse;

import java.util.logging.Level;
import java.util.logging.Logger;
/**
 * @author XiaoYW
 *
 */
public class TestModbusSlave 

    public static void main(String[] args) 
        ModbusClient modbusClient = ClientForTests.getInstance().getModbusClient();

        ReadCoilsResponse readCoils = null;
        try 
            readCoils = modbusClient.readCoils(12321, 5);
         catch (NoResponseException | ErrorResponseException | ConnectionException ex) 
            Logger.getLogger(Example.class.getName()).log(Level.SEVERE, ex.getLocalizedMessage());
        
        System.out.println(readCoils);

        ReadHoldingRegistersResponse readHolding = null; 
        try 
            readHolding = modbusClient.readHoldingRegisters(2200,10);
         catch (NoResponseException | ErrorResponseException | ConnectionException ex) 
            Logger.getLogger(Example.class.getName()).log(Level.SEVERE, ex.getLocalizedMessage());
        
        System.out.println(readHolding);
        modbusClient.close();
    

  客户端测试代码,如下文所示。

package de.gandev.modjn.example;

import de.gandev.modjn.ModbusClient;
import de.gandev.modjn.entity.exception.ConnectionException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author ares
 */
public class ClientForTests 

    private final ModbusClient modbusClient;

    private ClientForTests() 
        modbusClient = new ModbusClient("localhost" /*
                 * "192.168.1.55"
                 */, 30502); //ModbusConstants.MODBUS_DEFAULT_PORT);

        try 
            modbusClient.setup();
         catch (ConnectionException ex) 
            Logger.getLogger(ClientForTests.class.getName()).log(Level.SEVERE, null, ex);
        
    

    public ModbusClient getModbusClient() 
        return modbusClient;
    

    public static ClientForTests getInstance() 
        return ClientAndServerHolder.INSTANCE;
    

    private static class ClientAndServerHolder 

        private static final ClientForTests INSTANCE = new ClientForTests();
    

  以Java应用程序运行,运行结果:

ReadCoilsResponsebyteCount=1, coilStatus=0, 3
ReadHoldingRegistersResponsebyteCount=20, 
inputRegisters=register_0=2, register_1=0, register_2=0, register_3=3, register_4=0, register_5=0, register_6=8, register_7=0, register_8=0, register_9=0

参考:

《谈谈基于Netty实现Restful搭建服务架构思路》 CSDN博客 肖永威 2018年7月
《Modbus学习总结》 CSDN博客 深之JohnChen的专栏 2017年9月

以上是关于php对接Modbus设备详细讲解的主要内容,如果未能解决你的问题,请参考以下文章

php modbus over tcp(设备网关)

使用PHP控制MODBUS-RTU设备

如何使用IoTSharp对接ModBus?

物联网RTU(Modbus TCP协议)Java接口开发及Modbus Slave仿真使用

Modbus RTU/ASCll+TCP+OPC电脑模拟+串口调试软件对接方案

智能家居填坑003 Modbus设备接入篇