libmodbus icon indicating copy to clipboard operation
libmodbus copied to clipboard

Connection timeout caused by delay after write operation in rtu_send

Open gtth opened this issue 9 years ago • 4 comments

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 ...

gtth avatar Dec 06 '16 18:12 gtth

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).

desowin avatar Apr 30 '18 16:04 desowin

I sent a pull requet (#210) on this matter 4 years ago. However, it has been leaved for some reason.

habu1010 avatar May 01 '18 03:05 habu1010

@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)?

stephane avatar Oct 22 '24 14:10 stephane

Please provide me more information about the RTS needs. Do we need a different delays before and after the write? Etc.

stephane avatar Oct 22 '24 14:10 stephane