Modbus TCP Server setup

hello
I am a newbie on node-red.

I want to setup a modbus TCP SERVER on my rasp PI which would have a certain IP address and aswer to requests coming from a remote Modbus TCP client (etiher coils or holding register)

I have uploaded Modbus contrib, node-red is working fine.

I am very confuse with how to setup a flow which would:
Create a Modbus TCP Server being able to get connected to a Modbus TCP Client
use nodes that would allow this server to send values to the client, based on functions codes (3 / 5 / 15 / ...)

I found many examples on how to setup a Modbus TCP CLIENT getting data from remote servers, I want to develop the opposite, i.e. have my PI being a server, which would react to queries from a remote client (which in that case would be a PLC polling data from multiple slaves/servers)

Any help would be wellcome, or indication about an example of flow which I could look into

Thanks

JL

I searched for modbus on the modbus flows site and found this, which says that it can be used to create a modbus server.

Hi, you can use node-red-contrib-modbus' Modbus Server or Modbus Flex Server nodes to do this. What is frequently confusing at first is that you need to use the Modbus write nodes to set register values (can't do it directly). You can inject to the server nodes to make them dump the registers so that you can read them, but to set register values you have to use the write nodes (TCP client nodes).

Thanks a lot.

I had figured that out after many hours of trials and mistakes. But you definitely confirm that I am on the right path.

Now trying to figure out how to pass coils (bits) vs registers (intergers) a proper way, especially for conducting multiple coils/register writes at once

Thanks again

JL

Hey Jake

I got something that works now.

Only thing I can’t figure out at the moment is how to ‘’group’’ data per device number.

When using Modbus RTU (over RS485), each device has a unique address and you can get data from either device by setting up its address in the address field of
the request.

On the flow I have created (see below) the server would send the same data for ANY address I am using ….

The two Writes at the bottom write data to registers that are supposed to belong to Address 1.

Whatever the address I use on the Read/Getter, I get the same value: the one that were written on address 1.

I can’t figure out whether there would be a specific setup to tell the server it is serving data for MULTIPLE slaves …

Hope this is clear.

Would appreciate if you would have any clue … but would understand you’re busy

Thanks !

JL

Hi JL, I get what you are saying. It looks like these nodes falsely take advantage of the fact that in industry, unit/slave ID is largely ignored on the TCP side and only used for serial (RTU and ASCII) Modbus applications. Modbus flex server allows you to pick a unit ID, but when you try to use 2 nodes to listen on the same port for different unit IDs it crashes Node-RED.

You could either have multiple TCP servers on different ports, or code your own TCP server using the TCP in/out nodes and some function blocks. Modbus TCP is significantly easier than RTU (no CRC checks to perform), it wouldn't be too difficult to write your own TCP server for a limited subset of function codes. Using different servers for different ports and perhaps using some additional nodes to sync the registers might be quicker though. HTH.

If it's crashing then that should be raised as an issue against that node so they can fix it - or at least catch the error and alert the users.

Hi @dceejay, honestly a waste of time. Although these are probably the best Modbus nodes for Node-RED, the developer doesn't really care about fixing fundamental issues as much as he cares about soliciting for donations, and as such isn't friendly about helping others modify his code. I use 'his' loosely, as this is just a wrapper over the jsmodbus and modbus-serial npm packages.

Time better spent trying to develop either a new or work on an existing alternate package. I would if I had the time and understood Node-RED better.

Really ? I don’t see this issue on his issue list. Or a reply saying he won’t fix it. If you raised the issue at least others would be able to see it and know about it directly. (Even if then at some point you add a reply pointing to an all improved alternative :slight_smile:

1 Like

@dceejay this is actually why I requested the change to the serial node way back, Dynamically change characters expected in serial request , because node-red-contrib-modbus does not queue serial messages correctly. I wanted to pass a serial message and the number of return message bytes to expect to the serial request node.

Modbus is so simple that it does not take much at all on top of the serial or TCP nodes to cover about 95% of Modbus real-world use cases.

@dceejay Just for you: https://github.com/biancode/node-red-contrib-modbus/issues/143

1 Like

@dceejay, package maintainer already dismissed and closed the issue...lol. Knew it.

Have dinged him also... moving forwards...

1 Like

Thanks At least my trial is stable and does not crash when requesting data from different slaves. Only the data do not change from slave address to slave address

I will explore having multiple.servers on multiple ports to differentiate. Need to check my PLC can "ping" multiple ports.

Thanks again

JL

I don't know if this would work for you, but another option would be to use register ranges based on unit ID. Example: device 1 uses the first 1000 registers, device 2 2nd 1000 registers, and so on. So instead of specifying different unit IDs for your different devices, just use different register ranges.

I'm still not able to do this. Please guide me how this works.
The Pi on which I'm running node red needs to be have an IP Address that the Remote Modbus query device must address. If the IP Address of the PI is 192.168.1.14 ( lets say ), then the modes server, using the Modbus flex node will also be the same?

Hi jlr,
I am creating a modbus tcp server and able to read/write holding registers. but i also want to send simulated values to some particular input registers so that third party client can read it.
i used this code but its not helpful when i try to simulate some value to a particular input register address.
msg.payload = {
'value': msg.payload,
'register': 'input',
'address': 0,
'disableMsgOutput' : 0
};
return msg;
could you please help me with this?

Hi Jlr,
It seems you have solved a problem I am desperately looking for the solution. Trying to read holding registers from a TA CMI with node red via modbus. Seems I need the top part of your picture in your post above. What did you put in the FC 3: Read Register 1 & 2 function node? I tried numerous things but never get back any data.
Any help is welcome.
Thanks ahead