MODBUS Polls in Series

Hello all,

I frequently read that it is not best practice to trigger MODBUS nodes in parallel due to causing issues with crashing etc.

I believe that I could optimize this better, and I also have issues where the node goes into a disconnected state and has to reconnect quite often.
My question is: How can I wire this in series to better optimize it?
I am on Node-Red v1.03

Firstly, are any of the registers in consecutive registers? If so, there is a bank read mode for that node.

If not, then duplicate the modbus node and make a big long line of the function, then modbus, then next function, then next modbus and so on, in each function after the modbus, move the msg.payload to a new msg property so out the end of the chain you will have all your msg.stuffIwant in its own message.

EDIT: Like this…
Inject (~5 second for example) → Function → modbus → Function msg.flow1 = msg.payload → modbus → Function msg.flow2 = msg.payload → modbus → Function msg.flow3 = msg.payload → modbus → Function msg.flow4 = msg.payload → rest of the flow that reads msg.flow1 etc

Of course each function node also as the code in your current function nodes, just add that one line of moving the result of the modbus call into a different msg so it does not get over written by the next call.

2 Likes

The flow meters totalizer / rate registers are ~20 registers apart so I don’t believe I could do a bank read. I have to go to the field for a bit, but when I get a chance I’ll make a sample flow and post it here to verify I modified it correctly and hopefully get some feedback.

Thanks!

I am trying to do as you explained, but I am not getting good data from this flow.

Do you think you could help me a bit more with this?
Here is the example flow I am testing with :

[{"id":"fd9f784f.61b9f8","type":"function","z":"80e97bb0.998628","name":"","func":"msg.PH18 = msg.payload\nreturn msg;","outputs":1,"noerr":0,"x":450,"y":280,"wires":[["95c7bb14.ad5668"]]}]

There is not enough in that example to go on.
Please take a screenshot of the debug tab of the flow meter output (just one) from the Modbus and expand all the objects so we can see what msg.payload object you need - I just gave an example of msg.payload because I don’t have your flow meter and don’t know what the msg. output structure is.

I changed my flow slightly because I forgot a line in my function.

[{"id":"80e97bb0.998628","type":"tab","label":"Test MODBUSREAD","disabled":false,"info":""},{"id":"31d93fce.0cc12","type":"function","z":"80e97bb0.998628","name":"PH-17","func":"msg.payload = { 'unitid': 172, 'fc': 3, 'address': 3, 'quantity': 8 }\nreturn msg;","outputs":1,"noerr":0,"x":230,"y":220,"wires":[["76f15f0.ccef1a"]]},{"id":"76f15f0.ccef1a","type":"modbus-flex-getter","z":"80e97bb0.998628","name":"MB Poll","showStatusActivities":false,"showErrors":true,"logIOActivities":false,"server":"90681391.decbc","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":true,"keepMsgProperties":false,"x":360,"y":220,"wires":[[],["8d0f5e45.d0c83"]]},{"id":"27bf2f31.5602c","type":"function","z":"80e97bb0.998628","name":"PH-18","func":"msg.payload = { 'unitid': 182, 'fc': 3, 'address': 3, 'quantity': 4 }\nreturn msg;","outputs":1,"noerr":0,"x":230,"y":280,"wires":[["80077e8a.1a643"]]},{"id":"80077e8a.1a643","type":"modbus-flex-getter","z":"80e97bb0.998628","name":"MB Poll","showStatusActivities":false,"showErrors":true,"logIOActivities":false,"server":"90681391.decbc","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":true,"keepMsgProperties":false,"x":360,"y":280,"wires":[[],["98a0e5e.9826f18"]]},{"id":"d1ef7419.d5af98","type":"inject","z":"80e97bb0.998628","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":120,"y":160,"wires":[["31d93fce.0cc12"]]},{"id":"8d0f5e45.d0c83","type":"function","z":"80e97bb0.998628","name":"","func":"msg.PH17 = msg.payload.buffer.readFloatBE(0);\n\nreturn msg;","outputs":1,"noerr":0,"x":490,"y":220,"wires":[["9fd706b.076aef8","27bf2f31.5602c"]]},{"id":"9fd706b.076aef8","type":"debug","z":"80e97bb0.998628","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"PH17","targetType":"msg","x":710,"y":220,"wires":[]},{"id":"98a0e5e.9826f18","type":"function","z":"80e97bb0.998628","name":"","func":"msg.PH18 = msg.payload.buffer.readFloatBE(0);\n\nreturn msg;","outputs":1,"noerr":0,"x":490,"y":280,"wires":[["284dfd34.e38a12"]]},{"id":"284dfd34.e38a12","type":"debug","z":"80e97bb0.998628","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"PH18","targetType":"msg","x":530,"y":360,"wires":[]},{"id":"90681391.decbc","type":"modbus-client","z":"","name":"SerPort1","clienttype":"serial","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"tcpHost":"127.0.0.1","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttySerMod0.1","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"2","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"","unit_id":"1","commandDelay":"500","clientTimeout":"5000","reconnectOnTimeout":false,"reconnectTimeout":"2000","parallelUnitIdsAllowed":false}]

I am able to read each value independently, but I am unsure how you would get all the “msg.flow1,msg.flow2” as you said, or in my case “msg.PH17,msg.PH18” at the end of flow.

Here is the debug output:

Ah. Cool. Your up and running. Nice.

What do you do with the info from the original flow? The answer to that is the answer to your question.
You now have every flow meter reading, now you can just address each meter as and when needed by its payload name.

I am doing 2 things with the data after retrieving it here.

  1. Writing to a Groov Data Store tag to use on a Groov View screen.
  2. Sending to Mosquitto broker using the sparkplug node

So, I can simply place the groov-write-node and a link-out (to mosquitto flow) where the debuggers are currently?

Sure. That’s probably the cleanest way for you to proceed.
The point is, you are now giving the Modbus time to get the data before it does the next request. You are not slamming the modbus node all at once like you were.
This should fix your timeout issues.

Thanks for taking the extra time to explain everything for me here. I’m still pretty new to the OT world.

One last question, could the same thing be accomplished on my original flow if I were to just place a delay-node (set to Rate Limit) before the modbus node? If this would work, can you set “Rate Limit” to be milliseconds? The drop down only lists seconds as an option, so I wasn’t sure if it would accept something like 0.2 seconds.

Correct you could use the delay node like this:

You should not be pounding on the modbus node every 200ms.

1 Like

Leaving it at 1 msg/second is acceptable though?

I cant say either way without knowing a lot more about your application and flow.

1 Like