espressif / esp-modbus

ESP-Modbus - the officially suppported library for Modbus protocol (serial RS485 + TCP over WiFi or Ethernet).
Apache License 2.0
85 stars 46 forks source link

How to organize polling of a large number of IP addresses via Modbus TCP (for example, 30)? (IDFGH-9251) #19

Open iamalek opened 1 year ago

iamalek commented 1 year ago

A maximum of 5 IP addresses with associated UIDs can be specified in the table. Or 1 IP address with many descriptors in which you can set any UID and all of them will be tied to only one IP address.

alisitsyn commented 1 year ago

Hello @iamalek ,

The esp-modbus communication approach assumes that the master connects to all defined slaves first before performing any communication with slaves. This approach follows the Modbus TCP application implementation document from the Modbus Association. This is because the connection timeout may be up to ~3 seconds. This is what can cause the response timeout management issue.The master supports the maximum CONFIG_FMB_TCP_PORT_MAX_CONN defined in kconfig. However, it is not recommended to make more than five connections simultaneously because it takes up enough resources and memory and can cause latency and other issues. The resources of the ESP32 chip and its memory are significantly constrained compared to a Linux-based device or other similar PLC. Because of this, please consider using fewer slaves with your master.

iamalek commented 1 year ago

Thanks for the answer! There is one more unpleasant drawback of this implementation of the library - if at least one connection with the slave cannot be established at the time of initialization by the master, then the master hangs on it, waiting for the connection and making it impossible to work with the rest of the available slaves. This is a very significant shortcoming, please advise how to organize the work of the master, regardless of the availability of connecting slaves during initialization! Thank you!

alisitsyn commented 1 year ago

Thank you for your feedback. I agree that this approach is not very good in some projects. For the mentioned functionality, the code shall include event-based state machine and according to the slave state will go through all the required phases and do re-connection as required. I implement this behavior and going to include this in some update of Modbus. However for existing approach we can do as below: It is possible to start communication while the connection cycle is not completed, but it requires some modification of port layer code. The simple approach is to change the connection cycle to pass just one asynchronous connect command xMBTCPPortMasterConnect() for each slave config in xMbPortConfig.pxMbSlaveInfo[slave] despite the errors: ERR_CONN - connection can not be established and ERR_INPROGRESS - connection in progress. Then start polling cycle even while the connection is not established. The read/write functions will return the errors for these broken slaves, and if the ERR_CON is returned, the connection command can be issued again for the appropriate slave. Also, the stop polling and re-connection functions here should be removed to continue polling in spite of errors.

see also here

alisitsyn commented 1 year ago

Hi @iamalek ,

This feature request is implemented in modbus stack v2.0.0_beta1. This version will be able to handle the connection and resolving stages for each slave individually.

pr200sd commented 2 months ago

Thank you for your feedback. I agree that this approach is not very good in some projects. For the mentioned functionality, the code shall include event-based state machine and according to the slave state will go through all the required phases and do re-connection as required. I implement this behavior and going to include this in some update of Modbus. However for existing approach we can do as below: It is possible to start communication while the connection cycle is not completed, but it requires some modification of port layer code. The simple approach is to change the connection cycle to pass just one asynchronous connect command xMBTCPPortMasterConnect() for each slave config in xMbPortConfig.pxMbSlaveInfo[slave] despite the errors: ERR_CONN - connection can not be established and ERR_INPROGRESS - connection in progress. Then start polling cycle even while the connection is not established. The read/write functions will return the errors for these broken slaves, and if the ERR_CON is returned, the connection command can be issued again for the appropriate slave. Also, the stop polling and re-connection functions here should be removed to continue polling in spite of errors.

see also here

Good afternoon. You can make changes to the Master TCP, I tried to make sure that if one of the slaves loses connection, the polling of the second one continues, but I can’t make it so that at startup, if there is no connection with the slave, the polling of the second one starts correctly, and after it appears on the network, a reconnection occurs. port_tcp_master.zip This is my file from version: "1.0.15"

alisitsyn commented 1 month ago

Hi @pr200sd,

I just took a look to your change and it seems the change you made

pucMBTCPFrame[MB_TCP_UID] = pxInfo->ucSlaveAddr;

is not needed. When the xMBMasterTCPPortSendResponse() is called the UID field in the frame buffer is already set correctly by transport layer. I think the change you made might help in your case but it is not required for stack. Please let me know if I miss something and you have some specific details. I will try to verify as soon as I can. The v1 stack starts the connection right after initialization of the stack as it recommended by implementation guide from association. The version v2 is able to configure network and start polling immediately. Each slave stage such as connection, address resolution, error tracking, re connection and communication is controlled independently for each slave node. I have the updated implementation of v2 stack but the test infrastructure does not adequately test this yet. I think you will need to use the new stack implementation for your project.

pr200sd commented 1 month ago

Hi @pr200sd,

I just took a look to your change and it seems the change you made

pucMBTCPFrame[MB_TCP_UID] = pxInfo->ucSlaveAddr;

is not needed. When the xMBMasterTCPPortSendResponse() is called the UID field in the frame buffer is already set correctly by transport layer. I think the change you made might help in your case but it is not required for stack. Please let me know if I miss something and you have some specific details. I will try to verify as soon as I can. The v1 stack starts the connection right after initialization of the stack as it recommended by implementation guide from association. The version v2 is able to configure network and start polling immediately. Each slave stage such as connection, address resolution, error tracking, re connection and communication is controlled independently for each slave node. I have the updated implementation of v2 stack but the test infrastructure does not adequately test this yet. I think you will need to use the new stack implementation for your project.

Thanks for the answer, yes, I saw your version V2, but everything has been changed there, and I’m not sure that I can run my project simply by replacing the esp-modbus folder with V2, and since with esp-modbus I use both modbus RTU and TCP and everything works almost perfectly. with the exception of not starting master tcp if at the initial stage there is no one of the configured Slaves, so I would like to get this version, according to the recommendations you gave above. I tried to make the edits myself, but couldn't figure it out completely. As for this edit, yes, I made it back in 22, then apparently it didn’t exist and wouldn’t work without it, and then I moved it to a more recent version. I'll check without her.

alisitsyn commented 1 month ago

Thanks for the answer, yes, I saw your version V2, but everything has been changed there, and I’m not sure that I can run my project simply by replacing the esp-modbus folder with V2, and since with esp-modbus I use both modbus RTU and TCP and everything works almost perfectly.

The v2, has changes but the adoption of your Modbus code will be pretty straight-forward. I need to complete test implementation the verification of this V2 version and will try to share it to get some feedback as soon as possible. Unfortunately, I am very limited on what can be updated or implemented in V1. The V2 will be the only version where the features will be implemented.

As for this edit, yes, I made it back in 22, then apparently it didn’t exist and wouldn’t work without it, and then I moved it to a more recent version. I'll check without her.

The code was changed long time ago to set the corresponded UID in the frame on transport layer.