Modbus TCP网关对不存在的从站地址返回0,表示成功,而不是超时。如何可靠地检测离线设备?
我正在使用EasyModbus库开发一个C#应用,以轮询通过单个Modbus TCP网关连接在后面的多个Modbus RTU设备。
当设备在线或网关自身断开连接时,应用程序工作正常(它会正确抛出超时异常)。然而,我在不存在或离线的从站地址(Slave ID)方面遇到了一个严重问题。
如果我查询一个物理上已断开连接的从站地址,或在RS485总线上根本不存在的从站,网关不会抛出超时或Modbus异常。相反,它会拦截超时并返回一个填充为0 的完全有效的Modbus数据包(有时也会重复前一个活动从站的数 据)。
对我一些点传感器来说,0是一个完全正常的值(例如,正常状态为0,报警为1),因此我无法区分“健康传感器读数为0”和“丢失传感器返回伪造的0”的情况。
为绕过这个硬件限制,我在C#中实现了一个“Ping”逻辑。如果从点传感器读取到0,我会立即尝试读取一个明显无效的寄存器地址(例如9999)。
- 如果设备确实在线,它会返回 "02 Illegal Data Address"(我会捕获它并视为“存活”)。
- 如果网关在说谎,它在没有任何异常的情况下返回一个成功的读取,证明设备实际上已离线。
以下是我的轮询循环的一个简化版本:
using System;
using System.Diagnostics;
public void PollSensors()
{
ModbusClient modbusClient = new ModbusClient("192.168.1.100", 502)
{
ConnectionTimeout = 1500
};
try
{
modbusClient.Connect();
// Let's say Slave ID 5 is currently disconnected
modbusClient.UnitIdentifier = 5;
// Read 1 register starting from address 0
int[] registers = modbusClient.ReadHoldingRegisters(0, 1);
if (registers.Length > 0 && registers[0] == 0)
{
try
{
// PING TEST: Try reading an invalid address to force an exception
modbusClient.ReadHoldingRegisters(9999, 1);
// If we reach here, the gateway swallowed the error. The device is offline.
throw new Exception("Gateway returned fake 0. Device is actually offline.");
}
catch (EasyModbus.Exceptions.ModbusException)
{
// Device threw "02 Illegal Address". It is physically online and healthy.
Debug.WriteLine("Sensor is online.");
}
}
}
catch (Exception ex)
{
Debug.WriteLine($"Network Failure: {ex.Message}");
}
finally
{
if (modbusClient.Connected) modbusClient.Disconnect();
}
}```
解决方案
我通过重新配置网关解决了这个问题。我注意到有一个设置,如果从站ID缺失时会返回0。在我之前配置它的人很可能被界面主题所误导;由于复选框有颜色(白色 = 启用,橙色 = 关闭/禁用),他们以为它已启用。但事实证明,橙色表示该选项被禁用。我现在勾选了“Return Error”选项,问题因此得到修复。感谢大家! 
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。