Modbus timeout exception with 2 devices

Commication with two modbus devices on the same bus in a row throws a timeout exception for second device. Adding a short delay between communicating with each device appears to fix it.

static void MyModbus()
    {
        Modbus modbus = new Modbus(6);
        DateTime dtOld = DateTime.Now;
        TimeSpan ts;
        while (true)
        {
            dtOld = DateTime.Now;
            
            modbus.Send(11);
            Thread.Sleep(10);
            modbus.Send(10);
            ts = DateTime.Now - dtOld;

            Debug.WriteLine($"MyModbus {ts.TotalMilliseconds}");
            Thread.Sleep(10);
        }
    }

internal class Modbus
{
    UartController serial;
    ModbusMaster mbMaster;

    byte modbusAddr = 0;

    ushort[] reply = null;
    int count = 0;
    int TotalCount = 0;
    public Modbus(int portNr)
    {
        IModbusInterface mbInterface;
        UartSetting uartSetting;
        if (portNr == 6)
        {
            serial = UartController.FromName(SC20100.UartPort.Uart7);
            modbusAddr = 10;
            uartSetting = new UartSetting()
            {
                BaudRate = 57600,
                DataBits = 8,
                Parity = UartParity.None,
                StopBits = UartStopBitCount.One,
                EnableDePin = true,
                InvertDePolarity = true,
            };
            mbInterface = new ModbusRtuInterface(serial, 57600, 8, UartStopBitCount.One, UartParity.None);
        }
        else
        {
            serial = UartController.FromName(SC20100.UartPort.Uart2);
            modbusAddr = 11;
            uartSetting = new UartSetting()
            {
                BaudRate = 9600,
                DataBits = 8,
                Parity = UartParity.None,
                StopBits = UartStopBitCount.One,
                EnableDePin = true,
                InvertDePolarity = true,
            };
            mbInterface = new ModbusRtuInterface(serial, 9600, 8, UartStopBitCount.One, UartParity.None);
        }


        mbMaster = new ModbusMaster(mbInterface);
        serial.SetActiveSettings(uartSetting);
     
        serial.Enable();
    }

    public void Send(byte addr)
    {

        try
        {
            TotalCount++;
            reply = mbMaster.ReadInputRegisters(addr, 49, 20, 2000);
            count++;
        }
        catch (System.Exception error)
        {
            Debug.WriteLine($"Modbus Timeout: {modbusAddr} + {error}");
            Thread.Sleep(100);
        }

        if(TotalCount % 30 == 0)
        {
            Debug.WriteLine($"Modbus addr:{modbusAddr}, Total:{TotalCount}, succed: {count}, diff: {TotalCount-count}");
        }
    }
}

I have a similar issue and GHI are looking into this. How are you controlling the Modbus transceiver TX/RX?

I am using an SP3485 with RTS control using the DE function of the UART.

We need exactly sample to reproduce. Are there 3 devices, one master and 2 slaves and all of them are SITCore?

1 master and two slaves on 57600Baud, 8 databits, No parity and 1 stopbit. only the master is a SITCore SCM20260D.

Yes using the inbuilt support for controlling the DE pin on RS485 transceivers. can’t remember if it was the uarts RTS.

Master is SITcore, slaves are not? We are just trying to reproduce with what we have here?

If you can reproduce with all SITCore master and slaves then easier for us. :))).

Hi Dat, if you need slaves, use Simply Modbus Slave on the PC with an RS232-RS485 interface. Worth the low cost to test Modbus with.

We can do that. But more information is better. The thing is, hardware or software are different between customers and us, result could be “could not reproduce”.

Example, just add sleep somewhere then cause differnt result. :)).

We always try to find issue. But after spent half or a day with guessing what customer did, then final result is “could not reproduce” :)). We dont want to say that, and customers dont want to hear that. :)).

That is why we sometime bother customers (and you) about code or setup :)).

Correct slaves are our own embedded platform. Unfortunately I do not have enough SITCore devices for making that setup.

please note that I did some quick testing with the amount of the delay required for it to work

modbus.Send(11);
Thread.Sleep(10);
modbus.Send(10);
ts = DateTime.Now - dtOld;
Debug.WriteLine($"MyModbus {ts.TotalMilliseconds}");
Thread.Sleep(10);

When setting it to 5ms it would failed with 7ms sometimes errors would occur and I didin’t see any errors at 10ms.

Your slave slow response and need more time?

How long do your slaves hold the transmit on after the last byte has been sent? That could cause the bus to be still active.

Hmm took out my logic analyzer and it appears as the SITCore does indeed send Modbus requests but the slave does not respond to the second request. My issues might be the time of 3.8ms between a slave respond and new master request shown as green. This would explain why delaying requests appears to fix the issue.

I guess I could implement logic to delay between responds and request if a minimum time has not passed but a general fix would be nice.