Skip to content

Commit

Permalink
- add "strict" flag to serial MODBUS setup allowing to reset inter_by…
Browse files Browse the repository at this point in the history
…te_timeout on connecting via serial MODBUS if the flag is disabled

- updates Trinitas setups
  • Loading branch information
MAKOMO committed Sep 15, 2024
1 parent b299dfb commit dc2816f
Show file tree
Hide file tree
Showing 9 changed files with 29 additions and 4 deletions.
6 changes: 5 additions & 1 deletion src/artisanlib/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4173,6 +4173,7 @@ def blockTicks(self) -> int:
def setSamplingRate(self, rate:int) -> None:
self.qmc.delay = max(self.qmc.min_delay, rate)
self.sampling_ticks_to_block_quantifiction = self.blockTicks() # we update the quantification block ticks
_log.info('setSamplingRate(%s)', self.qmc.delay)

@pyqtSlot()
def updateMessageLog(self) -> None:
Expand Down Expand Up @@ -17110,6 +17111,7 @@ def settingsLoad(self, filename:Optional[str] = None, theme:bool = False, machin
self.modbus.stopbits = toInt(settings.value('stopbits',self.modbus.stopbits))
self.modbus.parity = s2a(toString(settings.value('parity',self.modbus.parity)))
self.modbus.timeout = max(0.3, float2float(toFloat(settings.value('timeout',self.modbus.timeout)))) # min serial MODBUS timeout is 300ms
self.modbus.serial_strict_timing = bool(toBool(settings.value('serial_strict_timing',self.modbus.serial_strict_timing)))
self.modbus.modbus_serial_extra_read_delay = toFloat(settings.value('modbus_serial_extra_read_delay',self.modbus.modbus_serial_extra_read_delay))
self.modbus.serial_readRetries = toInt(settings.value('serial_readRetries',self.modbus.serial_readRetries))
self.modbus.IP_timeout = float2float(toFloat(settings.value('IP_timeout',self.modbus.IP_timeout)))
Expand Down Expand Up @@ -18835,6 +18837,7 @@ def saveAllSettings(self, settings:QSettings, default_settings:Optional[Dict[str
self.settingsSetValue(settings, default_settings, 'stopbits',self.modbus.stopbits, read_defaults)
self.settingsSetValue(settings, default_settings, 'parity',self.modbus.parity, read_defaults)
self.settingsSetValue(settings, default_settings, 'timeout',self.modbus.timeout, read_defaults)
self.settingsSetValue(settings, default_settings, 'serial_strict_timing',self.modbus.serial_strict_timing, read_defaults)
self.settingsSetValue(settings, default_settings, 'modbus_serial_extra_read_delay',self.modbus.modbus_serial_extra_read_delay, read_defaults)
self.settingsSetValue(settings, default_settings, 'serial_readRetries',self.modbus.serial_readRetries, read_defaults)
self.settingsSetValue(settings, default_settings, 'IP_timeout',self.modbus.IP_timeout, read_defaults)
Expand Down Expand Up @@ -22816,6 +22819,7 @@ def setcommport(self, _:bool = False) -> None:
self.modbus.IP_timeout = float2float(toFloat(str(dialog.modbus_IP_timeoutEdit.text())))
except Exception: # pylint: disable=broad-except
pass
self.modbus.serial_strict_timing = bool(dialog.modbus_Serial_strict.isChecked())
self.modbus.IP_retries = dialog.modbus_IP_retriesComboBox.currentIndex()
self.modbus.PID_slave_ID = int(str(dialog.modbus_PIDslave_Edit.text()))
self.modbus.PID_SV_register = int(str(dialog.modbus_SVregister_Edit.text()))
Expand Down Expand Up @@ -25853,7 +25857,7 @@ def initialize_locale(my_app:Artisan) -> str:
qt_translation_modules:List[str] = [
'qtbase',
'qtconnectivity',
# 'qtwebengine'
# 'qtwebengine' # we do not use any UI
]

# NOTE: on updates, need to update util.py:locale2full_local() as well
Expand Down
12 changes: 9 additions & 3 deletions src/artisanlib/modbusport.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import sys
import time
import logging
import serial
from typing import Final, Optional, List, Dict, Tuple, Union, Any, Awaitable, TYPE_CHECKING

if TYPE_CHECKING:
Expand Down Expand Up @@ -100,7 +101,7 @@ def getBinaryPayloadDecoderFromRegisters(registers:List[int], byteorderLittle:bo
class modbusport:
""" this class handles the communications with all the modbus devices"""

__slots__ = [ 'aw', 'modbus_serial_read_delay', 'modbus_serial_extra_read_delay', 'modbus_serial_write_delay', 'maxCount', 'readRetries', 'default_comport', 'comport', 'baudrate', 'bytesize', 'parity', 'stopbits',
__slots__ = [ 'aw', 'modbus_serial_read_delay', 'modbus_serial_extra_read_delay', 'modbus_serial_write_delay', 'maxCount', 'readRetries', 'serial_strict_timing', 'default_comport', 'comport', 'baudrate', 'bytesize', 'parity', 'stopbits',
'timeout', 'IP_timeout', 'IP_retries', 'serial_readRetries', 'PID_slave_ID', 'PID_SV_register', 'PID_p_register', 'PID_i_register', 'PID_d_register', 'PID_ON_action', 'PID_OFF_action',
'channels', 'inputSlaves', 'inputRegisters', 'inputFloats', 'inputBCDs', 'inputFloatsAsInt', 'inputBCDsAsInt', 'inputSigned', 'inputCodes', 'inputDivs',
'inputModes', 'optimizer', 'fetch_max_blocks', 'fail_on_cache_miss', 'disconnect_on_error', 'acceptable_errors', 'reset_socket', 'activeRegisters', 'readingsCache', 'SVmultiplier', 'PIDmultiplier',
Expand All @@ -124,6 +125,7 @@ def __init__(self, aw:'ApplicationWindow') -> None:
self.stopbits:int = 1
self.timeout:float = 0.3 # serial MODBUS timeout
self.serial_readRetries:int = 0 # user configurable, defaults to 0
self.serial_strict_timing:bool = False
self.IP_timeout:float = 0.2 # UDP/TCP MODBUS timeout in seconds
self.IP_retries:int = 1 # UDP/TCP MODBUS retries (max 3)
self.PID_slave_ID:int = 0
Expand Down Expand Up @@ -240,7 +242,7 @@ def formatMS(start:float, end:float) -> str:

# @staticmethod
# def reconnect() -> None:
# _log.info('reconnect()')
# _log.info('reonnect()')

def connect(self) -> None:
if not self.isConnected():
Expand Down Expand Up @@ -357,7 +359,7 @@ def connect(self) -> None:
# retry_on_invalid=True, # retry on invalid response; by default False # retired
# close_comm_on_error=self.reset_socket,
# reset_socket=self.reset_socket, # retired
# strict=False, # settings this to False disables the inter char timeout restriction # retired
# strict=False, # settings this to False disables the inter char timeout restriction # retired and replaced by self.serial_strict_timing
reconnect_delay=0, # avoid automatic reconnection
# on_reconnect_callback=self.reconnect, # removed in pymodbus 3.7
timeout=min((self.aw.qmc.delay/2000), self.timeout)) # the timeout should not be larger than half of the sampling interval
Expand All @@ -366,6 +368,10 @@ def connect(self) -> None:
time.sleep(.2) # avoid possible hickups on startup
if self.master is not None:
self.master.connect() # type:ignore[no-untyped-call,unused-ignore]
# on connect() of serial connections we reset the inter_byte_timeout of the serial socket if serial_strict_timing is False
# by default pymodbus v3.7 sets a calculated inter_byte_timeout on connect()
if not self.serial_strict_timing and self.type in {0,1} and self.master.socket is not None and isinstance(self.master.socket, serial.Serial):
self.master.socket.inter_byte_timeout = None
if self.isConnected():
self.updateActiveRegisters()
self.clearReadingsCache()
Expand Down
9 changes: 9 additions & 0 deletions src/artisanlib/ports.py
Original file line number Diff line number Diff line change
Expand Up @@ -685,18 +685,26 @@ def __init__(self, parent:'QWidget', aw:'ApplicationWindow') -> None:
self.modbus_Serial_delayEdit = QLineEdit(str(int(self.aw.modbus.modbus_serial_extra_read_delay*1000)))
self.modbus_Serial_delayEdit.setValidator(self.aw.createCLocaleDoubleValidator(0,99,0,self.modbus_Serial_delayEdit))
self.modbus_Serial_delayEdit.setFixedWidth(50)
self.modbus_Serial_delayEdit.setAlignment(Qt.AlignmentFlag.AlignRight)
self.modbus_Serial_delayEdit.setToolTip(QApplication.translate('Tooltip', 'Extra delay in Milliseconds between MODBUS Serial commands'))
modbus_Serial_retries = QLabel(QApplication.translate('Label', 'Retries'))
self.modbus_Serial_retriesComboBox = QComboBox()
# modbus_Serial_retries.setBuddy(self.modbus_Serial_retriesComboBox)
self.modbus_Serial_retriesComboBox.addItems([str(n) for n in range(3)])
self.modbus_Serial_retriesComboBox.setCurrentIndex(self.aw.modbus.serial_readRetries)

modbus_Serial_strict_label = QLabel(QApplication.translate('Label', 'Strict'))
self.modbus_Serial_strict = QCheckBox()
self.modbus_Serial_strict.setChecked(self.aw.modbus.serial_strict_timing)
self.modbus_Serial_strict.setFocusPolicy(Qt.FocusPolicy.NoFocus)

modbus_Serial_grid = QGridLayout()
modbus_Serial_grid.addWidget(modbus_Serial_delaylabel,0,0,Qt.AlignmentFlag.AlignRight)
modbus_Serial_grid.addWidget(self.modbus_Serial_delayEdit,0,1,Qt.AlignmentFlag.AlignRight)
modbus_Serial_grid.addWidget(modbus_Serial_retries,1,0,Qt.AlignmentFlag.AlignRight)
modbus_Serial_grid.addWidget(self.modbus_Serial_retriesComboBox,1,1,Qt.AlignmentFlag.AlignRight)
modbus_Serial_grid.addWidget(modbus_Serial_strict_label,2,0,Qt.AlignmentFlag.AlignRight)
modbus_Serial_grid.addWidget(self.modbus_Serial_strict,2,1,Qt.AlignmentFlag.AlignLeft)

modbus_Serial_layout = QVBoxLayout()
modbus_Serial_layout.addLayout(modbus_Serial_grid)
Expand All @@ -711,6 +719,7 @@ def __init__(self, parent:'QWidget', aw:'ApplicationWindow') -> None:
self.modbus_IP_timeoutEdit = QLineEdit(str(self.aw.modbus.IP_timeout))
self.modbus_IP_timeoutEdit.setValidator(self.aw.createCLocaleDoubleValidator(0,5,1,self.modbus_IP_timeoutEdit))
self.modbus_IP_timeoutEdit.setFixedWidth(50)
self.modbus_IP_timeoutEdit.setAlignment(Qt.AlignmentFlag.AlignRight)
self.modbus_IP_timeoutEdit.setToolTip(QApplication.translate('Tooltip', 'IP timeout in seconds, not larger than half of the sampling interval'))
modbus_IP_retries = QLabel(QApplication.translate('Label', 'Retries'))
self.modbus_IP_retriesComboBox = QComboBox()
Expand Down
1 change: 1 addition & 0 deletions src/includes/Machines/TRINITAS/T2.aset
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ type=0
wordorderLittle=true
optimizer=true
fetch_max_blocks=false
serial_strict_timing=false

[MachineSetup]
capacity=2
1 change: 1 addition & 0 deletions src/includes/Machines/TRINITAS/T2_air.aset
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ type=0
wordorderLittle=true
optimizer=true
fetch_max_blocks=false
serial_strict_timing=false

[MachineSetup]
capacity=2
1 change: 1 addition & 0 deletions src/includes/Machines/TRINITAS/T2_legacy.aset
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ type=0
wordorderLittle=true
optimizer=true
fetch_max_blocks=false
serial_strict_timing=false

[MachineSetup]
capacity=2
1 change: 1 addition & 0 deletions src/includes/Machines/TRINITAS/T7.aset
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ type=0
wordorderLittle=true
optimizer=true
fetch_max_blocks=false
serial_strict_timing=false

[MachineSetup]
capacity=7
1 change: 1 addition & 0 deletions src/includes/Machines/TRINITAS/T7_gas.aset
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ type=0
wordorderLittle=true
optimizer=true
fetch_max_blocks=false
serial_strict_timing=false

[MachineSetup]
capacity=7
1 change: 1 addition & 0 deletions src/includes/Machines/TRINITAS/T7_legacy.aset
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ type=0
wordorderLittle=true
optimizer=true
fetch_max_blocks=false
serial_strict_timing=false

[MachineSetup]
capacity=7

0 comments on commit dc2816f

Please sign in to comment.