Connection timeout caused by delay after write operation in rtu_send
libmodbus version
libmodbus-3.4.1
OS and/or distribution and Environment
Linux 3.4.7 compiled for ARM
Configuration: RTU with 9600 bauds (N, 8, 1)
Modbus meter Garo with response time 4ms!
Description
The function _modbus_rtu_send delays with ctx_rtu->onebyte_time * req_length after each write operation. As onebyte_time can't be set from the library, it's will fix a min delay after each write operation. During this delay no response will be read. If a meter replies to quick, it's response is missed out the libmodbus returns a connection time out.
Expected behaviour
- Option1: onebyte_time should be configurable via a set/get function. (pull request)
int modbus_rtu_set_onebyte_time(modbus_t *ctx, int us)
int modbus_rtu_get_onebyte_time(modbus_t *ctx)
- Option 2: Allow setting the delay after the write operation directly
usleep(ctx_rtu->rts_delay);
size = write(ctx->s, req, req_length);
usleep(new_delay_after_write /*ctx_rtu->onebyte_time * req_length +ctx_rtu->rts_delay */ );
Actual behaviour
The delay that causes the time out can't be reduced under the initial value of onebyte_time. However the onebyte_time depends on the used hardware.
Steps to reproduce the behavior (commands or source code)
- Use a modbus meter with a response_time < 8ms (min delay for rtu_send)
- Or increase onebyte_time to something > response_time of your meter
libmodbus output with debug mode enabled
# ERROR Connection timed out: select <F3>[01][03][00][34][00][02][85][C5] Sending request using RTS signal Waiting for a confirmation... ERROR Connection timed out: select error libnfc.driver.pn532_uart pn53x_check_communication error <B5><FE>[01][03][00][34][00][02][85][C5] Sending request using RTS signal Waiting for a confirmation... ERROR Connection timed out: select ...
I understand that the usleep(ctx_rtu->onebyte_time * req_length + ctx_rtu->rts_delay); is supposed to wait for all the bytes to be send. Is there any reason why tcdrain(ctx->s); cannot be used there? It might be good to handle EINTR (simply keep calling tcdrain() until it returns either success or error other than EINTR).
I sent a pull requet (#210) on this matter 4 years ago. However, it has been leaved for some reason.
@habu1010 you're right, my bad. If we remove this discutable computation, do you think we should add set/get methods to define the RTS delay (the delay before and after transmission)?
Please provide me more information about the RTS needs. Do we need a different delays before and after the write? Etc.