Unsolved QModbus timeout error (windows only error)
-
Qt version:
5.10.1
System(s):Windows 10
/Arch Linux
I have made a poller class to handle modbus read/write requests using Qt's modbus component[1]. An application I'm developing for a client uses this library in order to handle read/write requests. I develop mainly on linux. All is well until recently I found out that the modbus requests were failing due to a timeout on the windows build.
When making a request I wait for the
QModbusReply::finished()
signal and act upon that. As you can see from the code, i then use a singleshot timer to time the burst for the next modbus action to run (read/write). When running on windows, this breaks and gives me atimeout
error.I think my issue can be related to the following bugs[2][3] but I wanted other people's opinion hoping there might be a solution.
Am i using the Qt module in a wrong manner?
P.S: another guy with, what seems to be, my problem changed Qt version. I'll try that if all fails.
-
Hi
For me it looks like
https://bugreports.qt.io/browse/QTBUG-53767
is still not fixed in 5.10.1
And i agree it really sounds like what you are experiencing. -
Any ideas on how to temporarily fix the problem?
-
I'm not aware of any changes in Qt's Modbus implementation between Qt 5.8 and 5.9 - but you could try if using the older version solves your problem (It may be, that another change in Qt changes the behavior).
You can of course try to debug QtModbus and search for the root cause of your problem. Maybe its just a race condition that occurs on Windows but not on Linux.
If you cannot do this, a minimal example that illustrates the problem can help others to debug the QtModbus code. That would most likely require some "remote station" program.
-
Unfortunately I didn't/don't have that much time to manage to get a look at the Qt code for the component. Client is down my neck. What I did do instread was integrate a second solution that I wanted to share with you and for others that might end up encountering this problem.
What I did was integratelibmodbus
[1] as a possible backend for the library[2] I created as a wrapper around QtModbus.
It's still under development (got some refactoring to do and integrate tcp connection) but it's usable both under windows and linux. I'll be adding a "Readme" soon with basic info on how to build and use the lib with an example and tagging the first stable version as soon as these few things are in place.(keep an eye out on the
development
branch where i'm finishing off the libmodbus integration)Feel free to give it a spin and use it to your needs if it helps you solve the problem i'm currently having.
-
actually, I just checked the qmodbusrtuserialmaster_p.h
there is a change there.
m_sendTimer is started with
m_sendTimer.start(m_interFrameDelayMilliseconds);
and m_interFrameDelayMilliseconds is calculated this way
void calculateInterFrameDelay() { // The spec recommends a timeout value of 1.750 msec. Without such // precise single-shot timers use a approximated value of 1.750 msec. int delayMilliSeconds = 2; if (m_baudRate < 19200) { // Example: 9600 baud, 11 bit per packet -> 872 char/sec // so: 1000 ms / 872 char = 1.147 ms/char * 3.5 character // Always round up because the spec requests at least 3.5 char. delayMilliSeconds = qCeil(3500. / (qreal(m_baudRate) / 11.)); } if (m_interFrameDelayMilliseconds < delayMilliSeconds) m_interFrameDelayMilliseconds = delayMilliSeconds; }
So the timeout is at least 2 ms. That should be enough for for baud rates > 19200
have you tried your code on a different PC (but same OS, of course)?
-
@J.Hilk said in QModbus timeout error (windows only error):
actually, I just checked the qmodbusrtuserialmaster_p.h
there is a change there.
m_sendTimer is started with
m_sendTimer.start(m_interFrameDelayMilliseconds);
and m_interFrameDelayMilliseconds is calculated this way
void calculateInterFrameDelay() { // The spec recommends a timeout value of 1.750 msec. Without such // precise single-shot timers use a approximated value of 1.750 msec. int delayMilliSeconds = 2; if (m_baudRate < 19200) { // Example: 9600 baud, 11 bit per packet -> 872 char/sec // so: 1000 ms / 872 char = 1.147 ms/char * 3.5 character // Always round up because the spec requests at least 3.5 char. delayMilliSeconds = qCeil(3500. / (qreal(m_baudRate) / 11.)); } if (m_interFrameDelayMilliseconds < delayMilliSeconds) m_interFrameDelayMilliseconds = delayMilliSeconds; }
So the timeout is at least 2 ms. That should be enough for for baud rates > 19200
have you tried your code on a different PC (but same OS, of course)?
Hi there. Yeah, three different pcs:
- mine
- clients x 2 different pcs