ModbusPal 是什么?
ModbusPal 是一个基于 Java 的开源 Modbus 从站(Slave)模拟器,项目托管在 SourceForge:https://modbuspal.sourceforge.net/。它的核心特色是通过内嵌的 Jython(Java 版 Python)脚本引擎动态生成寄存器值,而不是仅仅返回预先设定的静态数据。这意味着你可以模拟真实工业设备的各种行为——温度传感器的季节波动、变频器的加速曲线、甚至带有噪声的模拟量信号。
在开发 Modbus 主站程序时,工程师经常面临”没有真实硬件”的困境。ModbusPal 就是为解决这个问题而设计的——它可以在一台普通电脑上同时模拟数十个不同类型的 Modbus 从站设备,支持 Modbus RTU(串口)和 Modbus TCP(以太网)两种传输模式。
ModbusPal 核心功能特性
- 动态寄存器生成:通过内置的数学函数(正弦波、斜坡、随机数)或用户自定义 Python 脚本实时计算每个寄存器的值
- 多从站并发:同时模拟多个不同 Slave ID 的 Modbus RTU/TCP 设备
- 自动化机制:支持定时任务自动修改寄存器值,模拟设备状态变化(如开关量翻转、模拟量渐变)
- Jython 脚本引擎:内嵌 Jython 2.x,允许编写复杂业务逻辑(状态机、通信仿真等)
- 跨平台运行:基于 Java Swing,Windows / Linux / macOS 均可运行
- 串口支持:通过 RxTx 库支持物理串口通信,可连接真实的 RS-232/RS-485 网络
安装 ModbusPal
前提条件
ModbusPal 依赖 Java 运行环境(JRE 8 或以上)。如需使用物理串口功能,还需要安装 RxTx 串口通信库。
Linux 安装
# 安装 Java 运行时
sudo apt-get update
sudo apt-get install default-jre
# 下载 ModbusPal(SourceForge 最新版)
wget -O modbuspal.jar "https://sourceforge.net/projects/modbuspal/files/latest/download"
# 启动程序
java -jar modbuspal.jar
# 如果需要串口支持,安装 RxTx
sudo apt-get install librxtx-java
Windows 安装
下载 modbuspal.jar 后,如果系统已安装 Java,双击即可运行。如需串口功能,下载 RxTx 的 Windows DLL 文件(rxtxSerial.dll),复制到 C:Program FilesJavajrebin 目录。
创建第一个 Modbus TCP 从站
启动 ModbusPal 后,主界面从上到下分为菜单栏、工程树、配置面板和日志输出区。创建基础从站只需 5 步:
- 菜单栏点击 Add → Modbus Slave
- 在弹出的对话框中,选择协议类型为 TCP
- 设置监听端口(默认 502),如需多从站可分配不同端口(如 502, 503, 504)
- 设置从站地址(Slave ID),例如 1
- 右键点击新创建的从站,选择 Add → Holding Registers,设置起始地址和数量
点击工具栏的 Run 按钮启动从站。此时从站已经在 TCP 502 端口监听,可以用 Modbus Poll 或 Modpoll 等主站工具连接并读取寄存器值。
用 Python 脚本生成动态数据
这是 ModbusPal 的杀手级功能。以下示例模拟一个温度传感器,让寄存器值以正弦波形式在 20°C 到 30°C 之间波动:
# temperature_simulator.py
# 模拟温度传感器,值在 20.0 - 30.0°C 间以正弦波周期变化
import time
import math
def getValue(register):
"""
ModbusPal 每次读寄存器时调用此函数
register: 寄存器地址 (int)
返回值: 寄存器值 (int, 0-65535)
"""
t = time.time()
# 中心温度 25°C,振幅 5°C,周期 60 秒
temperature = 25.0 + 5.0 * math.sin(2.0 * math.pi * t / 60.0)
# 乘以 10 保留一位小数精度,如 25.3°C → 253
return int(temperature * 10)
def setValue(register, value):
"""可选:处理主站写入的命令"""
print("Register %d written with value %d" % (register, value))
在 ModbusPal 中绑定脚本:右键点击目标寄存器 → Bindings → Add Python Binding → 选择脚本文件 → 指定绑定的寄存器地址范围。启动从站后,用主站工具持续读取该寄存器地址,即可观察到温度值随时间的正弦变化。
进阶场景:模拟完整的多设备工业网络
实际工业场景中,一条 RS-485 总线上通常挂载多个从站设备。我们可以用 ModbusPal 模拟以下典型配置:
| 从站 ID | 设备类型 | 寄存器映射 |
|---|---|---|
| 1 | 温湿度传感器 | R0: 温度(x10), R1: 湿度(x10) |
| 2 | 三相电表 | R0: A相电压, R1: A相电流, R2-3: 有功功率(32-bit) |
| 3 | 变频器 | R0: 运行频率(x100), R1: 输出电流(x10), R2: 运行状态(bit编码) |
| 4 | 液位计 | R0-1: 液位高度(mm, 32-bit), R2: 温度(x10) |
在 ModbusPal 中依次添加 4 个从站,为每个从站创建对应的寄存器组,再为需要动态值的寄存器绑定 Python 脚本。这样做的好处是:无需购买和连接真实硬件,即可在开发机上完成多设备通信联调和协议逻辑验证。
设计复杂的模拟行为
模拟变频器启停和转速变化
# vfd_simulator.py
# 模拟变频器:接收启停命令,转速按斜坡函数变化
import time
# 全局状态变量
target_freq = 0.0 # 目标频率 (Hz)
current_freq = 0.0 # 当前频率 (Hz)
running = False # 运行状态
RAMP_RATE = 2.0 # 斜坡速率:2 Hz/秒
last_time = time.time()
def getValue(register):
global current_freq, last_time
now = time.time()
dt = now - last_time
last_time = now
if register == 0:
# 频率寄存器:按斜坡速率逼近目标值
if abs(current_freq - target_freq) > 0.01:
if current_freq = 0:
status |= 0x02
return status
return 0
def setValue(register, value):
global target_freq, running
if register == 0:
# 主站写入控制命令
# value bit0: 启动/停止, bit1: 方向
running = bool(value & 0x01)
if not running:
target_freq = 0.0
elif register == 1:
# 主站写入目标频率(乘以 100)
target_freq = value / 100.0
模拟带噪声的模拟量传感器
# noisy_sensor.py
# 模拟带噪声的 4-20mA 压力变送器
import time
import math
import random
def getValue(register):
t = time.time()
# 基准压力:0.5 MPa,叠加小幅正弦波动
base_pressure = 500.0 # kPa
ripple = 10.0 * math.sin(2 * math.pi * t / 30.0)
# 添加随机噪声(±2 kPa)
noise = random.uniform(-2.0, 2.0)
pressure = base_pressure + ripple + noise
if register == 0:
# 压力值(kPa,整数)
return int(pressure)
elif register == 1:
# 压力值小数部分(Pa)
frac = pressure - int(pressure)
return int(frac * 1000)
return 0
与自动化测试结合
ModbusPal 可以配置为项目文件(.mbp 格式),通过命令行加载:
# 加载预配置的工程文件并启动
java -jar modbuspal.jar --load my_project.mbp &
这使其可以集成到自动化测试流程中。测试脚本的典型流程:
- 启动 ModbusPal 并加载测试工程(后台运行)
- 等待从站就绪
- 运行 Modbus 主站测试用例(如用 Modpoll 读写寄存器)
- 验证返回值是否符合预期
- 生成测试报告
- 停止 ModbusPal
ModbusPal 的局限性
使用 ModbusPal 时需要注意以下几点:
- 项目活跃度:ModbusPal 是一个较早期的开源项目,近几年更新频率降低。对于一些较新的 Modbus 功能(如 FC43/14 读取设备标识),支持可能不完整。
- Jython 版本:内置的 Jython 引擎基于 Python 2.x 语法,不支持 f-string、type hints 等 Python 3 特性。
- 高分辨率显示:基于 Java Swing 的 GUI 在 4K 高 DPI 屏幕上可能显示不佳,需要调整 Java 的 DPI 缩放设置。
- 性能上限:模拟大量从站(超过 20 个)时,Java 的串口处理可能成为瓶颈。
替代方案对比
- pymodbus(Python):灵活性最高,支持 TCP/RTU/TLS,适合构建自定义模拟器,但需要编写完整代码
- ModRSsim2:Windows 平台的免费 Modbus 从站模拟器,有 GUI 但不支持 Python 脚本
- Modbus Slave(商业软件):功能最全的商业 Modbus 模拟工具,但不是免费的
- Unslave Modbus Simulator:较新的免费选择,界面更现代
总结
ModbusPal 以其 Python 脚本驱动的动态寄存器生成能力,在开源 Modbus 模拟器领域独具特色。它特别适合以下应用场景:Modbus 主站程序开发阶段没有目标硬件时的协议联调与验证;需要模拟多个不同类型从站设备(仪表、PLC、变频器)的复杂系统集成测试;以及需要通过动态波形、随机噪声、斜坡函数等来复现真实工业现场行为的场景。如果你正在开发 Modbus 上位机软件、SCADA 系统或物联网数据采集网关,ModbusPal 是验证通信逻辑的得力工具。
发表回复