budulinek / arduino-modbus-rtu-tcp-gateway

Arduino-based Modbus RTU to Modbus TCP/UDP gateway with web interface. Allows you to connect Modbus RTU slaves (such as sensors, energy meters, HVAC devices) to Modbus TCP/UDP masters (such as home automation systems). You can adjust settings through web interface.
GNU General Public License v3.0
172 stars 51 forks source link

The connection to the Modbus master is broken after a few hours #7

Closed dl9msr closed 3 years ago

dl9msr commented 3 years ago

Hardware: Arduino Mega 2560, W5500 lite, 1 RTU Slave 0x01 Modbus Mode : Modbus TCP/UDP

Modbus Master TCP/502, query interval 120s ,timeout 5s

The connection to the web interface TCP/80 also breaks off. After pressing the reset button, the connection is re-established

budulinek commented 3 years ago

Only TCP connections break down? UDP packets and ping still working?

At the moment I use Modbus UDP (without problems), but I will switch to Modbus TCP and try to reproduce.

dl9msr commented 3 years ago

I have only TCP connections. Ping also don’t work

I tried to use the library ethernet2.h utility/w5500.h

but I got compiler failure

best regards

Michael

budulinek commented 3 years ago

So I have been using both Modbus UDP and Modbus TCP (simultaneously) for 2 days, no problem with the connection.

Arduino Nano + W5500 (8 sockets) + RS485 module with HW flow control. Modbus UDP query interval 1s, Modbus TCP query interval 5s.

If you are willing to do further tests, here are my suggestions:

  1. Stress test TCP connection.

Enable per socket diagnostics https://github.com/budulinek/arduino-modbus-rtu-tcp-gateway/blob/3a9afdfba7689f2c079b421252b8db301b681e2b/arduino-modbus-rtu-tcp-gateway/arduino-modbus-rtu-tcp-gateway.ino#L60

Use https://packetsender.com/ to test TCP (or UDP) connections. If you send Modbus TCP message (with correctly formated header) to the gateway, you will get a response (either a message with Modbus data, or a message with a Modbus error). You can try for example HEX: 00 01 00 00 00 06 01 04 00 00 00 01

Try both TCP and UDP.

Then you can set "Resend delay" to some low value, such as 0.1s and start sending TCP data periodically. This is the stress test (DoS) to the gateway. If the "Resend delay" is low enough, all sockets available on your ethernet module will quickly fill (you can see the status of all sockets it in the status web page of the gateway) and you will get connection errors (in Packet Sender and maybe also your web browser). If you stop the stress test, Arduino should gradually free up some sockets and everything should get to normal. If the TCP stress test is successful (= if Arduino correctly recovers sockets once you stop the stress test), you know that TCP socket allocation (and recovery) works correctly.

  1. Disable Web UI.

You can try to disable parts of the code (functionality) within the sketch and see if the problem with Modbus TCP connection persists. As the first step, you can disable Web UI by commenting out these lines:

https://github.com/budulinek/arduino-modbus-rtu-tcp-gateway/blob/3a9afdfba7689f2c079b421252b8db301b681e2b/arduino-modbus-rtu-tcp-gateway/04-webserver.ino#L111 https://github.com/budulinek/arduino-modbus-rtu-tcp-gateway/blob/3a9afdfba7689f2c079b421252b8db301b681e2b/arduino-modbus-rtu-tcp-gateway/04-webserver.ino#L140 https://github.com/budulinek/arduino-modbus-rtu-tcp-gateway/blob/3a9afdfba7689f2c079b421252b8db301b681e2b/arduino-modbus-rtu-tcp-gateway/04-webserver.ino#L142

There is a lot of code responsible for the Web UI and I did found some bugs over there in the past. PLS let me know if disabling Web UI helped or not.

P.S. ethernet2.h won't compile since I use some functions which are only available in default ethernet.h library

dl9msr commented 3 years ago

So I did the stress test and everything works as you wrote.

Now I disabled the Web UI by commenting out these lines: `111 // sendPage(client, 0xFF); // Send "please wait" page

140 // sendPage(client, reqPage); 141 // else if (!strcmp(uri, "/favicon.ico")) // a favicon 142 // send204(client); // if you don't have a favicon, send 204 143 // else // if the page is unknown, HTTP response code 404 ` I will then come back with the result

dl9msr commented 3 years ago

So I have been testing ModbusTCP for 2 days and have no problems with the connection. WEb UI current status active all the time Extra_Diag enabled other Web UI commented out Modbus/Master Settings for the test: read interval 10s timeout 10s

budulinek commented 3 years ago

Thanks for debugging!

OK, so it seems that the bug is somewhere in 05-pages.ino

We also know that status page (i.e. reqPage == 1 ) works OK.

If you are willing to proceed here are my suggestions.

Reverse your previous comments you made in 04-webserver.ino, we will focus on 05-pages.ino

Comment out references to functions responsible for other pages: https://github.com/budulinek/arduino-modbus-rtu-tcp-gateway/blob/3a9afdfba7689f2c079b421252b8db301b681e2b/arduino-modbus-rtu-tcp-gateway/05-pages.ino#L105 https://github.com/budulinek/arduino-modbus-rtu-tcp-gateway/blob/3a9afdfba7689f2c079b421252b8db301b681e2b/arduino-modbus-rtu-tcp-gateway/05-pages.ino#L108 https://github.com/budulinek/arduino-modbus-rtu-tcp-gateway/blob/3a9afdfba7689f2c079b421252b8db301b681e2b/arduino-modbus-rtu-tcp-gateway/05-pages.ino#L111 https://github.com/budulinek/arduino-modbus-rtu-tcp-gateway/blob/3a9afdfba7689f2c079b421252b8db301b681e2b/arduino-modbus-rtu-tcp-gateway/05-pages.ino#L114

You may also comment out the code responsible for autorefresh (lines 43-49) if (reqPage == 1 || reqPage == 0xFF) page.print(F(" http-equiv=refresh content=5")); if (reqPage == 0xFF) { page.print(F(";url=http://")); page.print((IPAddress)localConfig.ip); page.print(F(":")); page.print(localConfig.webPort); }

If there are no problems with connection, you can enable pages one after another in order to catch the bug.

Hmm, you know what? I have a suspicion that this line could be the cause of the bug:

https://github.com/budulinek/arduino-modbus-rtu-tcp-gateway/blob/3a9afdfba7689f2c079b421252b8db301b681e2b/arduino-modbus-rtu-tcp-gateway/05-pages.ino#L544

change it to

content.print((IPAddress)defaultConfig.ip);

defaultConfig.ip already is IPAddress type, so we probably do not need to use the (IPAddress) cast. But see

https://github.com/budulinek/arduino-modbus-rtu-tcp-gateway/blob/3a9afdfba7689f2c079b421252b8db301b681e2b/arduino-modbus-rtu-tcp-gateway/05-pages.ino#L46

where I had to use the (IPAddress) cast. Do not know why, but without the cast, line 46 caused Arduino freezing.

dl9msr commented 3 years ago

Thank you for response. I started the test with the change in line 544

dl9msr commented 3 years ago

That seems to be the bug. The test has been running for 48 hours without any problems. Many thanks for your help.

budulinek commented 3 years ago

Great to hear that!

Thanks for hunting the bug!