别再到处找破解版了!手把手教你用Python+PyModbus模拟Modbus Slave设备(附完整代码)
用Python构建Modbus从站模拟器的全流程指南在工业自动化领域Modbus协议因其简单可靠而成为设备通信的事实标准。许多工程师习惯使用商业软件如Modbus Slave进行测试但这类工具往往价格昂贵导致部分用户转向非授权版本。其实借助Python生态中的PyModbus库我们可以轻松构建功能完整的虚拟从站不仅完全合法还能根据项目需求灵活定制。1. 环境准备与基础概念Modbus协议诞生于1979年最初为PLC通信设计如今已发展出RTU、ASCII和TCP三种主要变体。无论哪种形式其核心都是主从架构下的寄存器读写机制。作为从站模拟器我们需要实现以下基础功能单元线圈Coils1位可读写布尔值常用于表示开关状态离散输入Discrete Inputs1位只读布尔值模拟传感器输入保持寄存器Holding Registers16位可读写数值存储设备参数输入寄存器Input Registers16位只读数值反映实时测量值安装所需环境仅需两条命令pip install pymodbus3.1.3 pip install pyserial3.5 # 如需RTU模式需额外安装提示建议使用Python 3.8环境某些旧版本可能存在兼容性问题。虚拟环境能有效隔离依赖避免与其他项目冲突。2. 构建基础从站服务器我们先从TCP模式的从站实现开始这是最易上手的方式。以下代码创建了一个包含所有四种数据类型的从站from pymodbus.server import StartTcpServer from pymodbus.datastore import ModbusSequentialDataBlock from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext def run_server(): # 初始化数据存储 coils ModbusSequentialDataBlock(0, [False]*100) # 100个线圈 inputs ModbusSequentialDataBlock(0, [True]*100) # 100个离散输入 hr ModbusSequentialDataBlock(0, [0]*100) # 100个保持寄存器 ir ModbusSequentialDataBlock(0, [0]*100) # 100个输入寄存器 # 创建从站上下文 slave_context ModbusSlaveContext( diinputs, cocoils, hrhr, irir, zero_modeTrue # 地址从0开始计数 ) # 注册到服务器上下文 context ModbusServerContext(slaves{1: slave_context}, singleFalse) # 启动TCP服务器 StartTcpServer(contextcontext, address(0.0.0.0, 502)) if __name__ __main__: run_server()启动后这个服务会监听502端口Modbus TCP标准端口响应单元ID为1的所有请求。我们可以使用Modbus Poll等主站工具进行测试功能码地址范围操作类型示例值010-99读线圈0x0001020-99读离散输入0x0000030-99读保持寄存器0x1234040-99读输入寄存器0x5678050-99写单个线圈0xFF00060-99写单个寄存器0xABCD3. 高级功能实现基础从站能满足简单测试需求但真实场景往往需要更复杂的功能。下面我们实现几个实用特性3.1 动态数据模拟保持寄存器中的静态数据缺乏真实感我们可以添加周期性变化from threading import Timer import random def simulate_dynamic_data(context): slave_context context[1] values [random.randint(0, 100) for _ in range(100)] slave_context.setValues(3, 0, values) # 3表示保持寄存器 Timer(1.0, simulate_dynamic_data, [context]).start()在run_server()的StartTcpServer调用前添加simulate_dynamic_data(context)3.2 多从站支持PyModbus支持在单个服务器实例中托管多个从站只需扩展上下文配置slaves { 1: ModbusSlaveContext(...), # 单元ID 1 2: ModbusSlaveContext(...), # 单元ID 2 3: ModbusSlaveContext(...) # 单元ID 3 } context ModbusServerContext(slavesslaves, singleFalse)3.3 异常响应与日志完善的从站应该正确处理异常并记录通信日志from pymodbus.exceptions import ModbusException from pymodbus.pdu import ExceptionResponse class CustomDataBlock(ModbusSequentialDataBlock): def validate(self, address, count1): if address count len(self.values): raise ModbusException(f地址越界 {address}) return True def getValues(self, address, count1): self.validate(address, count) return super().getValues(address, count)4. 串行通信RTU/ASCII实现对于硬件测试串行通信模式更为常见。RTU模式的服务器配置与TCP类似from pymodbus.server import StartSerialServer def run_rtu_server(): # ...相同的上下文配置... StartSerialServer( contextcontext, port/dev/ttyUSB0, # 串口设备 framerModbusRtuFramer, baudrate19200, timeout0.005 )关键参数配置建议参数典型值注意事项baudrate9600/19200/38400需与主站一致parityN/E/O无/偶/奇校验stopbits1/2通常为1bytesize7/8ASCII模式用7RTU用8timeout0.005-0.1过小可能导致响应丢失5. 实战PLC联调案例假设我们需要测试一个温控系统的PLC程序该程序会读取温度传感器值输入寄存器40001比较设定值保持寄存器40002控制加热器线圈00001对应的从站模拟器可以这样增强def simulate_heating_system(context): slave context[1] while True: # 当前温度模拟带随机波动 current_temp 25 random.uniform(-2, 2) slave.setValues(4, 0, [int(current_temp * 10)]) # 4输入寄存器 # 读取设定温度 set_temp slave.getValues(3, 1)[0] / 10 # 3保持寄存器 # 控制逻辑 heater_on current_temp set_temp - 0.5 slave.setValues(1, 0, [heater_on]) # 1线圈 time.sleep(1)这个案例展示了如何构建有业务逻辑的智能从站远超商业软件的固定模式。通过Python的灵活性我们可以模拟设备的各种特殊行为和异常场景这在真实测试中非常宝贵。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2574997.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!