使用 Modbus 实现主从多设备互联¶
概述¶
Modbus是一种串行通信协议,是Modicon公司(现在的施耐德电气)于1979年为使用可编程逻辑控制器(PLC)通信而发表。Modbus已经成为工业领域通信协议事实上的业界标准,并且现在是工业电子设备之间常用的连接方式。
Modbus允许多个 (大约240个) 设备连接在同一个网络上进行通信。举个例子:一个由测量温度和湿度的装置,并且将结果发送给计算机。
在数据采集与监视控制系统(SCADA)中,Modbus通常用来连接监控计算机和远程终端控制系统(RTU)。
接口¶
Modbus协议目前存在用于串口、以太网以及其他支持互联网协议的网络的版本。大多数Modbus设备通信通过串口EIA-485物理层进行。
工作模式¶
Modbus协议是一个master/slave架构的协议。有一个节点是master节点,其他使用Modbus协议参与通信的节点是slave节点。 每一个slave设备都有一个唯一的地址。在串行和MB+网络中,只有被指定为主节点的节点可以启动一个命令。
一个ModBus命令包含了打算执行的设备的Modbus地址。所有设备都会收到命令,但只有指定位置的设备会执行及回应指令 (地址0例外,指定地址0的指令是广播指令,所有收到指令的设备都会运行,不过不回应指令)。 所有的Modbus命令包含了检查码,以确定到达的命令没有被破坏。
基本的ModBus命令能指令一个RTU改变它的寄存器的某个值,控制或者读取一个I/O端口,以及指挥设备回送一个或者多个其寄存器中的数据。
有许多modems和网关支持Modbus协议,因为Modbus协议很简单而且容易复制。它们当中一些为这个协议特别设计的。 有使用有线、无线通信甚至短消息和GPRS的不同实现。不过设计者需要克服一些包括高延迟和时序的问题。
案例¶
案例中我们以左边的板子为主机,右边的板子为从机,实现两个设备的命令发送及响应。更多的设备均可以通过 Modbus 总线连接,这里我们不做更多扩展。
Python轻应用支持的 Modbus 接口可以参考 modbus — Modbus协议
示例演示¶
示例代码:
在主机设备上运行命令:
在从机设备上运行命令:
最终可以从主机从机上得到不同的输出:
主机输出:
(ash:/data)# python /data/pyamp/main.py master
Welcome to MicroPython
modbus master write Holding Reg result: (0, 1, 2, 0)
modbus master read Holding Regs result: (0, 20)
modbus master write Holding Reg result: (0, 1, 2, 0)
modbus master read Holding Regs result: (0, 20)
modbus master write Holding Reg result: (0, 1, 2, 0)
modbus master read Holding Regs result: (0, 20)
modbus master write Holding Reg result: (0, 1, 2, 0)
modbus master read Holding Regs result: (0, 20)
modbus master write Holding Reg result: (0, 1, 2, 0)
modbus master read Holding Regs result: (0, 20)
从机输出:
(ash:/data)# python /data/pyamp/main.py slave
Welcome to MicroPython
[ 108.558]<E>modbusm frame is too short or CRC error
[ 108.558]<E>modbus Failed to disassemble frame
resp data: bytearray(b'\x06\x00\x01\x00\x02')
resp data: bytearray(b'\x03\x14\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\t')
resp data: bytearray(b'\x06\x00\x01\x00\x02')
resp data: bytearray(b'\x03\x14\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\t')
resp data: bytearray(b'\x06\x00\x01\x00\x02')
resp data: bytearray(b'\x03\x14\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\t')
resp data: bytearray(b'\x06\x00\x01\x00\x02')
resp data: bytearray(b'\x03\x14\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\t')
resp data: bytearray(b'\x06\x00\x01\x00\x02')
resp data: bytearray(b'\x03\x14\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\t')
可以看到从机正确地响应了主机的请求并给予回答,主机的返回状态码 为0,主从机通信正常。