跳转到内容

Modbus 集成

FX Viewer Modbus 集成功能手册

1. 功能简介

这是用于将 FX Viewer 的实时声学相机数据(波束功率、报警状态等)与外部系统(PLC、SCADA、HMI 等)进行集成的 Modbus TCP 服务器功能。

通过该功能,可以在 PLC 等外部控制设备上监视 FX Viewer 的相机数据,并直接控制部分设置。

2. 基本设置与连接信息

自动启动

FX Viewer 程序启动后,Modbus 服务器会自动运行。无需另行设置。

连接信息

  • IP 地址:运行 FX Viewer 的 PC 的 IP 地址

  • 端口5020(默认)或 502

    • 考虑到部分环境没有使用 1024 以下端口的权限,服务器会优先绑定 5020 端口。如果 5020 端口绑定失败,服务器会尝试在 502 端口上监听。

    • 在客户端请先尝试连接 5020 端口,如果无法连接,再尝试连接 502 端口。

  • 协议:Modbus TCP

3. 相机设置

要使 Modbus 功能正常工作,必须按照约定的格式设置相机昵称

⚠️ 重要:昵称与以下规则不一致的相机将被排除在 Modbus 集成之外。这是查询不到数据时最常见的原因,因此请在集成前首先确认这一点。

Unit ID必需昵称允许的其他格式Device ID
1FX_01FX01, FX-010x4601
2FX_02FX02, FX-020x4602
3FX_03FX03, FX-030x4603
  • 不区分大小写。(可以使用 fx_01

  • 第四台及以后的相机同样沿用该规则。Unit ID 会按照在 FX Viewer 中注册使用的相机数量依次分配。

4. 寄存器映射

  • 地址方式:建议 PLC 等客户端使用从 0 开始的线地址(Offset)。(例如:40009 号地址 → 按 8 号地址请求)
Modbus 地址线地址寄存器名称数据类型R/W说明
400010DEVICE_IDU16R设备唯一 ID(例如:0x4601
400021DEVICE_CONNECTEDU16R相机连接状态(1:已连接,0:已断开)
400032YEARU16R当前时间(年)
400043MONTHU16R当前时间(月)
400054DAYU16R当前时间(日)
400065HOURU16R当前时间(时)
400076MINUTEU16R当前时间(分)
400087SECONDU16R当前时间(秒)
400098MAX_DBx10S16R最大声压(dB 值 x 10),例如:45.2dB → 452
400109ALARM_FLAGU16R报警状态(1:发生报警,0:正常)
4001110THRESH_DBx10S16R/W阈值(dB 值 x 10),例如:42.5dB → 425
4001211THRESH_HOLDx10S16R/W保持时间(秒值 x 10),例如:3.5 秒 → 35
40013-1412-13FREQ_LOW_HZU32R/W频率下限(Hz)
40015-1614-15FREQ_HIGH_HZU32R/W频率上限(Hz)

客户端的数据类型设置

在 PLC Modbus 客户端中按寄存器地址选择数据类型(INT、WORD、DWORD 等)的设置界面示例

这是在 PLC Modbus 客户端中按寄存器地址选择数据类型的设置界面示例。对于使用 1 个寄存器的项目,请按照上表中的类型,将有符号整数(S16)读取为 INT,将无符号整数(U16)读取为 WORD;对于使用 2 个寄存器(32 位)的 FREQ_LOW_HZ·FREQ_HIGH_HZ,请以 DWORD 系列类型读取。

5. 主要功能与使用示例(Python)

启用自动触发模式

  • 在 PLC 中向阈值(40011)或保持时间(40012)寄存器写入值后,该相机的录制方式会自动启用为“触发录制”模式

⚠️ 注意:对阈值·保持时间寄存器执行写入会产生改变相机录制方式的副作用。如果只需要监视数据,请仅使用读取请求;只有在有意切换为触发录制时,才发送写入请求。

Python 示例代码

以下示例使用 Python pymodbus 库(以 3.x 为准)。请先安装该库。

Terminal window
pip install pymodbus

💡 参考:pymodbus 指定 Unit ID 的关键字因版本而异。以下示例中的 slave= 以 3.x 为准,旧版本(2.x)使用 unit=。请使用与所安装版本相符的关键字。

from pymodbus.client import ModbusTcpClient
# 设置为运行 FX Viewer 的 PC 的 IP 和端口
FX_VIEWER_IP = '127.0.0.1'
FX_VIEWER_PORT = 5020
client = ModbusTcpClient(FX_VIEWER_IP, port=FX_VIEWER_PORT)
client.connect()
# -- 数据读取示例 ---
# 读取 FX_01 相机 (Unit ID = 1) 的数据
# 从线地址 8 号 (MAX_DBx10) 开始读取 2 个寄存器 (声压、报警)
result = client.read_holding_registers(8, count=2, slave=1)
if not result.isError():
max_db_x10 = result.registers[0]
alarm_flag = result.registers[1]
# 转换为有符号 16 位后除以 10
import struct
signed_max_db_x10 = struct.unpack('>h', struct.pack('>H', max_db_x10))[0]
print(f"FX_01 最大声压: {signed_max_db_x10 / 10.0} dB")
print(f"FX_01 报警状态: {'发生' if alarm_flag == 1 else '正常'}")
# -- 数据写入示例 ---
# 将 FX_02 相机 (Unit ID = 2) 的阈值设置为 45.5 dB
# 向线地址 10 号 (THRESH_DBx10) 写入值
new_threshold = 45.5
threshold_to_write = int(new_threshold * 10)
client.write_register(10, threshold_to_write, slave=2)
print(f"FX_02 阈值设置为 {new_threshold} dB 的请求已完成")
client.close()

运行结果示例

这是 FX_01 相机的最大声压为 45.2 dB(寄存器值 452)、报警处于正常状态时的输出示例。

FX_01 最大声压: 45.2 dB
FX_01 报警状态: 正常
FX_02 阈值设置为 45.5 dB 的请求已完成

6. 故障排除(Troubleshooting)

  • 无法连接时:

    • 确认 FX Viewer PC 的 IP 地址和端口(5020)是否正确。

    • 确认是否已在 Windows 防火墙的入站规则中允许端口 5020502

  • 数据仅显示为 0 时:

    • 确认在 FX Viewer 中相机已启用,并且正在接收实时数据。

    • 再次确认相机的昵称是否正确设置为 FX_01FX_02 等。(最常见的原因)

  • 部分值(如频率)读取异常时:

    • 确认客户端的数据类型设置是否与寄存器映射中的类型(S16/U16/U32)一致。特别是使用 2 个寄存器的 FREQ_LOW_HZ·FREQ_HIGH_HZ 必须以 DWORD 系列类型读取。(请参考第 4 节的数据类型设置界面)

7. 相关文档