-1

I am developing a C# application using the EasyModbus library to poll multiple Modbus RTU devices connected behind a single Modbus TCP Gateway.

The application works perfectly when the devices are online or when the gateway itself is disconnected (it properly throws a timeout exception). However, I am facing a critical issue with non-existent or offline Slave IDs.

If I query a Slave ID that is physically disconnected or simply doesn't exist on the RS485 bus, the gateway does not throw a timeout or a Modbus Exception. Instead, it intercepts the timeout and returns a perfectly valid Modbus packet filled with 0s (or sometimes repeats the data from the previous active Slave ID).

Since 0 is a completely normal value for some of my point sensors (e.g., normal state = 0, alarm = 1), I cannot distinguish between a "Healthy Sensor reading 0" and a "Missing Sensor returning fake 0s".

To bypass this hardware limitation, I implemented a "Ping" logic in C#. If I read a 0 from a point sensor, I immediately try to read a clearly invalid register address (e.g., 9999).

If the device is truly online, it responds with 02 Illegal Data Address (which I catch and consider as "Alive").

If the gateway is lying, it returns a successful read without any exception, proving the device is actually offline.

Here is a simplified version of my polling loop:

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();
    }
}```
New contributor
Yağız P. is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
2
  • Just to clarify, your gateway is responding with something like 0001 0000 0005 11 03 02 0000 when the device behind it is offline? If that is the case I don't see any way for your program to tell the difference between this and a real 0 value. Can you share details of the "specific Gateway"? Commented 13 hours ago
  • Yes, that's exactly the case. The gateway masks the timeout and returns a perfectly valid packet with 0 values. I've just come up with a potential workaround to test this: I will try sending a subsequent read request to an invalid register address (like 9999). If the sensor is online, it should respond with an exception like '02 Illegal Data Address'. If the gateway still returns a fake successful 0, then I'll know for sure the device is offline. I'm going to test this logic now. Thanks for confirming my suspicion! Commented 13 hours ago

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.