evranch
https://github.com/evranch/modbus-aggregator

OpenPLC has a couple weaknesses to do with Modbus/TCP handling. Namely, it works fine with a wired test device, but if you add unreliable wireless links or large numbers of slave devices, these issues become apparent:

- will block main polling loop if device is unavailable or slow to respond
- forces coils on every cycle, making distributed control a challenge
- doesn't read coils, only writes them
- addressing is dependent on order devices are added to configuration

Rather than introduce asynchronous polling and threads into an unfamiliar codebase, I decided to write this application that acts as a modbus server: https://github.com/evranch/modbus-aggregator

Written in C with pthreads, it will asynchronously poll as many nodes as you want and load them into a single modbus mapping with configurable offsets. Just point OpenPLC at a "Generic Modbus TCP Device" as wide as you like. It will never block regardless of network state. Your network layout is in its own simple config file, which obviously is not affected by any changes you make in OpenPLC.

It also has a few more features:

- propagates changes between master and slaves. This allows more practical distributed control systems. A simple example: The exterior lights on my farm buildings are controlled by modbus devices with local pushbutton toggles. OpenPLC in the house reads the state of these lights, displaying them on the HMI. Any light can be switched on and off by either the local button OR the PLC. OpenPLC on its own will not allow this, but will force the outputs to its internal state on every cycle.

- this mode can be disabled on a per-device basis if you don't need local controls and would prefer the devices act as simple slave cards

- mirrors coils into the input address space. As OpenPLC does not implement (01) Read Coils, this feature is essential for feedback on uses such as the lighting control mentioned. This plus a SEL block allows the PLC to track or override the state of each device.

- presents a discrete input for each device proving if the last poll cycle was successful

I hope this will be useful anywhere you have a bunch of unreliable Modbus devices or just want to simplify your configuration. Usage cases are as wide-ranging as bringing together a distributed control system spanning multiple buildings, to detecting presence and status of vehicles.
Quote 1 0
thiagoralves
Thanks for sharing! The serial polling in OpenPLC has bugged me for a while. There are some developments to make it asynchronous on the dev branch, but nothing is tested yet.
Quote 0 0
evranch
The serial interface itself isn't that bad, but combining TCP and its associated timeouts with the serial polling loop is the real problem IMO. You can be down to 1 second polling rates on serial pretty fast with a single TCP device not responding, and that's not something you expect to happen on a serial interface.

If there's one thing that the serial interface could use, it's a direction control pin on the RPi hardware drivers to allow use of an RS485 interface rather than only a single serial device. I do have a USB RS485 interface I plan to experiment with on OpenPLC, but USB ports on the Pi are at a premium, especially when using devices with bulky physical hardware due to the tight layout.

I also am not a fan of not being able to set addressing on a per-device level as you know, which was one of the driving factors behind writing this application.
Quote 0 0