Multiple Modbus RTU Slaves causes error

Hi all,

I'm using thenode-red-contrib-modbus node, with two slave devices with addresses 1 and 101. Both have the same settings, for RTU-BUFFERED:

Baud rate: 9600
Data bits: 8
Stop bits: 1
Parity: None

I've confirmed that there are no wiring issues and all comms are good. I'm having an issue where setting up 'modbus-read' nodes for both only works if I have one slave set up. Enabling both causes one of them to fail to work.

The test case is as follows:

Two node-red tabs, one with this flow for slave 101 (using a flex getter here but the same happens with a normal modbus-read node):
50

and the other for slave 1:

11

If I enable both tabs, slave 1 will communicate properly and slave 101 won't (it gets stuck in a loop of 'initialize -> reconnecting after 2000 msec'). This happens at random - sometimes slave 1 works and slave 101 doesn't, sometimes the other way around. However if I disable one tab, the other modbus-read works fine. So the issue seems to be that only one device can be enabled and read throughout the whole node-red configuration.

As far as I'm aware, this should all be within the modbus RTU stack, as it's simply two slave devices on the same network with the same configuration and different addresses, so not sure of the problem here? I'm hesitant to create an 'issue' on the node-red-contrib-modbus GitHub page until confirm that this is actually a bug.

Here's an export of each flow pictured above:

[
    {
        "id": "94bb33c0.333ee",
        "type": "modbus-getter",
        "z": "b99ef0d6.d646d8",
        "name": "",
        "showStatusActivities": false,
        "showErrors": false,
        "logIOActivities": false,
        "unitid": "",
        "dataType": "HoldingRegister",
        "adr": "14",
        "quantity": "1",
        "server": "bf70619e.04833",
        "useIOFile": false,
        "ioFile": "",
        "useIOForPayload": false,
        "x": 300,
        "y": 80,
        "wires": [
            [
                "3c22e6a6.2a0e62"
            ],
            [
                "3c22e6a6.2a0e62"
            ]
        ]
    },
    {
        "id": "ba58a969.c0be08",
        "type": "inject",
        "z": "b99ef0d6.d646d8",
        "name": "",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 100,
        "y": 80,
        "wires": [
            [
                "94bb33c0.333ee"
            ]
        ]
    },
    {
        "id": "3c22e6a6.2a0e62",
        "type": "debug",
        "z": "b99ef0d6.d646d8",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 540,
        "y": 80,
        "wires": []
    },
    {
        "id": "bf70619e.04833",
        "type": "modbus-client",
        "z": "",
        "name": "Calex Addr",
        "clienttype": "serial",
        "bufferCommands": true,
        "stateLogEnabled": false,
        "tcpHost": "127.0.0.1",
        "tcpPort": "502",
        "tcpType": "DEFAULT",
        "serialPort": "/dev/ttyUSB0",
        "serialType": "RTU-BUFFERD",
        "serialBaudrate": "9600",
        "serialDatabits": "8",
        "serialStopbits": "1",
        "serialParity": "none",
        "serialConnectionDelay": "100",
        "unit_id": 101,
        "commandDelay": 1,
        "clientTimeout": 1000,
        "reconnectTimeout": 2000
    }
]

[
    {
        "id": "671858a1.3b5c48",
        "type": "modbus-read",
        "z": "7fed931b.b8862c",
        "name": "Meter L1 Volts",
        "topic": "",
        "showStatusActivities": false,
        "logIOActivities": false,
        "showErrors": false,
        "unitid": "",
        "dataType": "HoldingRegister",
        "adr": "768",
        "quantity": "1",
        "rate": "15",
        "rateUnit": "m",
        "delayOnStart": false,
        "startDelayTime": "",
        "server": "bc1028d0.8535f8",
        "useIOFile": false,
        "ioFile": "",
        "useIOForPayload": false,
        "x": 130,
        "y": 220,
        "wires": [
            [
                "3d3a6730.138c08",
                "2a504cb9.1e0a44"
            ],
            []
        ]
    },
    {
        "id": "3d3a6730.138c08",
        "type": "debug",
        "z": "7fed931b.b8862c",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 150,
        "y": 160,
        "wires": []
    },
    {
        "id": "bc1028d0.8535f8",
        "type": "modbus-client",
        "z": "",
        "name": "ND Multi Display Module",
        "clienttype": "serial",
        "bufferCommands": true,
        "stateLogEnabled": false,
        "tcpHost": "127.0.0.1",
        "tcpPort": "502",
        "tcpType": "DEFAULT",
        "serialPort": "/dev/ttyUSB0",
        "serialType": "RTU-BUFFERD",
        "serialBaudrate": "9600",
        "serialDatabits": "8",
        "serialStopbits": "1",
        "serialParity": "none",
        "serialConnectionDelay": "100",
        "unit_id": 1,
        "commandDelay": 1,
        "clientTimeout": 1000,
        "reconnectTimeout": 2000
    }
]

I've done some further digging and it looks like my issue is identical to this:

Also this:

Ok...so it looks like there's a fundamental flaw in the node-red-contrib-modbus node whereby you can only set up and communicate with one Modbus RTU slave per serial port, which defeats the object of Modbus...investigating further.

It seems like the contributor is away, however this is such a major issue.

When dealing with Modbus RTU, see to it that the communication traffic should be consider. When Master is trying to poll data from Slave 1, the master should dedicate its connection to the Slave 1, the same thing to slave 2. WIth modbus RTU, only 1 slave can be connected at a time. Maybe with your settings, there is a collision of data where the Master is trying to communicate on Both Slaves at the same time. Try to change their Polling rate.

I've tried this using the node-red-contrib-serial-modbus node, with success. This proves that the hardware setup is correct and that multiple serial slaves can be interfaced with, as per the modbus spec. I can't use this node for my setup however as it gives no ability to tune timeouts, reconnects etc, hence my dependancy on node-red-contrib-modbus.

Using node-red-contrib-modbus I have also set up two slaves with different polling times (6 seconds and 8 seconds), with the first having a 'delay on start' of 1 second, therefore their rates should not interfere. This still doesn't work as the node tries to initialise both slaves at the same time, causing the collision issue.

FYI - proper buffering of messages to be sent over a resource-constraint serial connection sits well within the modbus spec.

Feel free to contribute if are able to test!

1 Like

Hi @bianco-royal - awesome to hear from you :slight_smile: I'm just working my way through the codebase. I'm not a native javascript developer so it's not second nature to me, so may struggle to improve. It looks like there's a need to initialise and queue based on the server being used, opposed to the slave address of each modbus device.

I am definitely able to test. I have a test rig setup with 2 modbus slaves, but also have a larger remote setup with 10 slaves, all on a single serial port.

I could build a pre-release with some ideas to fix it and you could test it.(?)

I'd be more than happy to do this @bianco-royal - would you like to continue the comms here or shall I open a new issue on GitHub where the both of us can track better?

Thanks :slight_smile:

1 Like

Please, open an issue for that with reference to this!

2 Likes

@bianco-royal: https://github.com/BiancoRoyal/node-red-contrib-modbus/issues/161