pyhys/minimalmodbus

Timeout after frame

pfrl opened this issue · 0 comments

pfrl commented

Timeout after request frame does not take into account request length (examples below have no physical Modbus devices connected, those are only the requests).

Test script:

from minimalmodbus import _MAX_NUMBER_OF_REGISTERS_TO_WRITE, Instrument  # type: ignore

device = Instrument("/dev/ttyUSB0", 1)
if device.serial is not None:
    device.serial.baudrate = 38400
    device.serial.parity = "E"
    device.serial.timeout = 0.1

while True:
    try:
        device.write_registers(0, [0] * _MAX_NUMBER_OF_REGISTERS_TO_WRITE)
    except:
        pass
System info
Minimalmodbus version: 2.1.1
pySerial version: 3.5

Platform: Arch Linux x86_64 / 6.4.12-arch1-1
Filesystem encoding: 'utf-8'
Byteorder: little
Python version: 3.11.5 (main, Aug 28 2023, 20:02:58) [GCC 13.2.1 20230801]
Python version info: sys.version_info(major=3, minor=11, micro=5, releaselevel='final', serial=0)
Python flags: sys.flags(debug=0, inspect=0, interactive=0, optimize=0, dont_write_bytecode=0, no_user_site=0, no_site=0, ignore_environment=0, verbose=0, bytes_warning=0, quiet=0, hash_randomization=1, isolated=0, dev_mode=False, utf8_mode=0, warn_default_encoding=0, safe_path=False, int_max_str_digits=-1)
Python argv: ['/usr/bin/ipython']
Python prefix: '/usr'
Python exec prefix: '/usr'
Python executable: '/usr/bin/python'
Float repr style: 'short'

Variable __name__: minimalmodbus
1. Writing maximum number of registers with timeout set to 100ms.

100ms

Time between frames ~41ms

2. Writing maximum number of registers with timeout set to 50ms. Request frame "eats" away the wait period for response.

50ms
Time between frames 0ms

3. Writing 40 registers with timeout set to 50ms.

40data_50ms
Time between frames ~29ms

To prevent the issue I've added serial.flush after serial.write in minimalmodbus.py, line 1468

        # Write request
        write_time = time.monotonic()
        self.serial.write(request)
        self.serial.flush() ## added line

After the changes:

1. Writing maximum number of registers with timeout set to 100ms.

100ms

2. Writing maximum number of registers with timeout set to 50ms.

50ms

3. Writing 40 registers with timeout set to 50ms.

40data_50ms

I've used flush with conviction that it is a nondestructive wait operation. I do not know if that change is adequate to be implemented.

Response times are a little bit longer then expected (possibly extended by MODBUS RTU 3.5 character time).

The issue came around when stress testing some older siemens PLC (slow response times) with faster devices.