2. Modbus TCP从站模拟器开发
任务目标
开发一个基于Python的Modbus TCP从站模拟器,模拟PLC的保持寄存器与线圈区域,供Modbus主站(如SCADA、上位机或调试工具)进行读写测试。从站启动后监听指定端口,响应主站的读写请求,并维护可动态修改的寄存器数据。
环境依赖
需要Python 3.8+,并安装pymodbus库(版本≥3.0):
pip install pymodbus
关键完整代码
以下代码实现了一个完整的Modbus TCP从站,模拟4个保持寄存器(地址0~3)和8个线圈(地址0~7)。从站启动后可通过主站工具(如Modbus Poll)或pymodbus客户端进行读写验证。
# modbus_slave.py
import logging
from pymodbus.server import StartTcpServer
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
from pymodbus.datastore import ModbusSequentialDataBlock
# 配置日志(可选,便于观察请求)
logging.basicConfig(level=logging.INFO)
# 初始化数据存储:保持寄存器(3x)与线圈(0x)
# 保持寄存器地址0~3,初始值分别为 10, 20, 30, 40
# 线圈地址0~7,初始值分别为 1,0,1,0,1,0,1,0
store = ModbusSlaveContext(
di=ModbusSequentialDataBlock(0, [0]*8), # 离散输入(本案例不使用)
co=ModbusSequentialDataBlock(0, [1,0,1,0,1,0,1,0]), # 线圈
hr=ModbusSequentialDataBlock(0, [10,20,30,40]), # 保持寄存器
ir=ModbusSequentialDataBlock(0, [0]*8) # 输入寄存器(本案例不使用)
)
context = ModbusServerContext(slaves=store, single=True)
if __name__ == "__main__":
# 启动TCP从站,监听502端口(需管理员权限)或改用5020等非特权端口
print("Modbus TCP Slave 启动,监听端口 5020...")
StartTcpServer(context=context, address=("0.0.0.0", 5020))
运行与验证
启动从站:
python modbus_slave.py
从站将监听本机5020端口(若需使用标准502端口,在Linux/macOS下用sudo运行,Windows下以管理员身份运行)。
验证方法(使用pymodbus客户端脚本):
# test_client.py
from pymodbus.client import ModbusTcpClient
client = ModbusTcpClient("127.0.0.1", port=5020)
assert client.connect()
# 读保持寄存器(地址0,读4个)
rr = client.read_holding_registers(0, 4)
print("保持寄存器:", rr.registers) # 预期输出: [10, 20, 30, 40]
# 写保持寄存器(地址2,写值99)
client.write_register(2, 99)
rr = client.read_holding_registers(0, 4)
print("写后保持寄存器:", rr.registers) # 预期输出: [10, 20, 99, 40]
# 读线圈(地址0,读8个)
cr = client.read_coils(0, 8)
print("线圈:", cr.bits) # 预期输出: [True, False, True, False, True, False, True, False]
# 写单个线圈(地址1,写True)
client.write_coil(1, True)
cr = client.read_coils(0, 8)
print("写后线圈:", cr.bits) # 预期输出: [True, True, True, False, True, False, True, False]
client.close()
print("验证通过")
运行客户端:
python test_client.py
通过条件:客户端脚本输出的寄存器与线圈值符合上述注释中的预期值,且无异常抛出。也可使用Modbus Poll等图形工具连接127.0.0.1:5020进行手动读写验证。
常见问题
- 端口占用:若5020被占用,修改代码中
address的端口号即可。 - 权限问题:使用标准502端口时需管理员/root权限,否则监听失败。
- 数据持久性:从站数据仅保存在内存中,重启后恢复初始值,适合测试场景。