From 147d729ad4377cff2e9cece69e5d4cc95451fb76 Mon Sep 17 00:00:00 2001 From: penguintamer <159223587+penguintamer@users.noreply.github.com> Date: Tue, 2 Apr 2024 23:40:47 -0800 Subject: [PATCH 1/7] Add tests for ignoreslaveaddress feature --- tests/test_minimalmodbus.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/test_minimalmodbus.py b/tests/test_minimalmodbus.py index 5d35c7f..9de0556 100644 --- a/tests/test_minimalmodbus.py +++ b/tests/test_minimalmodbus.py @@ -1503,6 +1503,20 @@ def testKnownValues(self) -> None: ) self.assertEqual(result, known_result) + def testIgnoredSlaveAddress(self) -> None: + for value in [3, 95, 128, 247, 255]: + for ( + slaveaddress, + functioncode, + mode, + known_result, + inputbytes, + ) in self.known_values: + result = minimalmodbus._extract_payload( + inputbytes, value, mode, functioncode, True + ) # Wrong slave address. Check explicitly disabled. + self.assertEqual(result, known_result) + def testWrongInputValue(self) -> None: self.assertRaises( InvalidResponseError, @@ -1622,6 +1636,16 @@ def testWrongInputValue(self) -> None: "rtu", 2, ) # Wrong slave address + for value in [3, 95, 128]: + self.assertRaises( + InvalidResponseError, + minimalmodbus._extract_payload, + b"\x02\x02123X\xc2", + value, + "rtu", + 2, + False, + ) # Wrong slave address. Check explicitly enabled. for value in [128, 256, -1]: self.assertRaises( ValueError, From 870dfe3bb7aea35697a1ceb8d7b6d541ea3b893c Mon Sep 17 00:00:00 2001 From: penguintamer <159223587+penguintamer@users.noreply.github.com> Date: Tue, 2 Apr 2024 23:43:34 -0800 Subject: [PATCH 2/7] Add ignoreslaveaddress option to _extract_payload() --- minimalmodbus.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/minimalmodbus.py b/minimalmodbus.py index 8d22676..84e633a 100644 --- a/minimalmodbus.py +++ b/minimalmodbus.py @@ -1787,7 +1787,8 @@ def _embed_payload( def _extract_payload( - response: bytes, slaveaddress: int, mode: str, functioncode: int + response: bytes, slaveaddress: int, mode: str, functioncode: int, + ignoreslaveaddress: bool = False, ) -> bytes: """Extract the payload data part from the slave's response. @@ -1797,6 +1798,7 @@ def _extract_payload( * slaveaddress: The adress of the slave. Used here for error checking only. * mode: The modbus protocol mode (MODE_RTU or MODE_ASCII) * functioncode: Used here for error checking only. + * ignoreslaveaddress: Bypass slave address check. Returns: The payload part of the *response*. Conversion from Modbus ASCII @@ -1903,16 +1905,17 @@ def _extract_payload( ) raise InvalidResponseError(text) - # Check slave address - responseaddress = response[_BYTEPOSITION_FOR_SLAVEADDRESS] + if not ignoreslaveaddress: + # Check slave address + responseaddress = response[_BYTEPOSITION_FOR_SLAVEADDRESS] - if responseaddress != slaveaddress: - raise InvalidResponseError( - "Wrong return slave " - + "address: {} instead of {}. The response is: {!r}".format( - responseaddress, slaveaddress, response + if responseaddress != slaveaddress: + raise InvalidResponseError( + "Wrong return slave " + + "address: {} instead of {}. The response is: {!r}".format( + responseaddress, slaveaddress, response + ) ) - ) # Check if slave indicates error _check_response_slaveerrorcode(response) From d2eae1457294e62a47a4f4caf06a7a9b746a95d5 Mon Sep 17 00:00:00 2001 From: penguintamer <159223587+penguintamer@users.noreply.github.com> Date: Tue, 2 Apr 2024 23:46:02 -0800 Subject: [PATCH 3/7] Expose ignoreslaveaddress option in _perform_command() --- minimalmodbus.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/minimalmodbus.py b/minimalmodbus.py index 84e633a..6757117 100644 --- a/minimalmodbus.py +++ b/minimalmodbus.py @@ -1297,7 +1297,10 @@ def _generic_command( # Communication implementation details # # #################################### # - def _perform_command(self, functioncode: int, payload_to_slave: bytes) -> bytes: + def _perform_command( + self, functioncode: int, payload_to_slave: bytes, + ignoreslaveaddress: bool = False + ) -> bytes: """Perform the command having the *functioncode*. Args: @@ -1305,6 +1308,7 @@ def _perform_command(self, functioncode: int, payload_to_slave: bytes) -> bytes: Can for example be 'Write register' = 16. * payload_to_slave: Data to be transmitted to the slave (will be embedded in slaveaddress, CRC etc) + * ignoreslaveaddress: Bypass the slave address check Returns: The extracted data payload from the slave. It has been @@ -1357,7 +1361,8 @@ def _perform_command(self, functioncode: int, payload_to_slave: bytes) -> bytes: # Extract payload payload_from_slave = _extract_payload( - response_bytes, self.address, self.mode, functioncode + response_bytes, self.address, self.mode, functioncode, + ignoreslaveaddress ) return payload_from_slave From d2d0e57e943c6a4302c026188b30a1ab83d8bdef Mon Sep 17 00:00:00 2001 From: penguintamer <159223587+penguintamer@users.noreply.github.com> Date: Tue, 2 Apr 2024 23:49:15 -0800 Subject: [PATCH 4/7] Expose ignoreslaveaddress in _generic_command() --- minimalmodbus.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/minimalmodbus.py b/minimalmodbus.py index 6757117..abc3d0b 100644 --- a/minimalmodbus.py +++ b/minimalmodbus.py @@ -996,6 +996,7 @@ def _generic_command( signed: bool = False, byteorder: int = BYTEORDER_BIG, payloadformat: _Payloadformat = _Payloadformat.REGISTER, + ignoreslaveaddress: bool = False, ) -> Any: """Perform generic command for reading and writing registers and bits. @@ -1013,6 +1014,7 @@ def _generic_command( Only for a single register or for payloadformat='long'. * byteorder: How multi-register data should be interpreted. * payloadformat: An _Payloadformat enum + * ignoreslaveaddress: Bypass the slave address check If a value of 77.0 is stored internally in the slave register as 770, then use ``number_of_decimals=1`` which will divide the received data @@ -1273,7 +1275,8 @@ def _generic_command( ) # Communicate with instrument - payload_from_slave = self._perform_command(functioncode, payload_to_slave) + payload_from_slave = self._perform_command( + functioncode, payload_to_slave, ignoreslaveaddress) # There is no response for broadcasts if self.address == _SLAVEADDRESS_BROADCAST: From 43aaa6784f406afb2d642e93f02db77eb9a7bdfa Mon Sep 17 00:00:00 2001 From: penguintamer <159223587+penguintamer@users.noreply.github.com> Date: Tue, 2 Apr 2024 23:52:30 -0800 Subject: [PATCH 5/7] Expose ignoreslaveaddress in high-level methods --- minimalmodbus.py | 64 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 8 deletions(-) diff --git a/minimalmodbus.py b/minimalmodbus.py index abc3d0b..06c45c4 100644 --- a/minimalmodbus.py +++ b/minimalmodbus.py @@ -297,7 +297,10 @@ def _print_debug(self, text: str) -> None: # Methods for talking to the slave # # ################################# # - def read_bit(self, registeraddress: int, functioncode: int = 2) -> int: + def read_bit( + self, registeraddress: int, functioncode: int = 2, + ignoreslaveaddress: bool = False, + ) -> int: """Read one bit from the slave (instrument). This is for a bit that has its individual address in the instrument. @@ -305,6 +308,7 @@ def read_bit(self, registeraddress: int, functioncode: int = 2) -> int: Args: * registeraddress: The slave register address. * functioncode Modbus function code. Can be 1 or 2. + * ignoreslaveaddress: Bypass the slave address check. Returns: The bit value 0 or 1. @@ -320,11 +324,13 @@ def read_bit(self, registeraddress: int, functioncode: int = 2) -> int: registeraddress, number_of_bits=1, payloadformat=_Payloadformat.BIT, + ignoreslaveaddress=ignoreslaveaddress, ) ) def write_bit( - self, registeraddress: int, value: int, functioncode: int = 5 + self, registeraddress: int, value: int, functioncode: int = 5, + ignoreslaveaddress: bool = False, ) -> None: """Write one bit to the slave (instrument). @@ -334,6 +340,7 @@ def write_bit( * registeraddress: The slave register address. * value: 0 or 1, or True or False * functioncode: Modbus function code. Can be 5 or 15. + * ignoreslaveaddress: Bypass the slave address check. Raises: TypeError, ValueError, ModbusException, @@ -347,10 +354,12 @@ def write_bit( value, number_of_bits=1, payloadformat=_Payloadformat.BIT, + ignoreslaveaddress=ignoreslaveaddress, ) def read_bits( - self, registeraddress: int, number_of_bits: int, functioncode: int = 2 + self, registeraddress: int, number_of_bits: int, functioncode: int = 2, + ignoreslaveaddress: bool = False, ) -> List[int]: """Read multiple bits from the slave (instrument). @@ -360,6 +369,7 @@ def read_bits( * registeraddress: The slave register start address. * number_of_bits: Number of bits to read * functioncode: Modbus function code. Can be 1 or 2. + * ignoreslaveaddress: Bypass the slave address check. Returns: A list of bit values 0 or 1. The first value in the list is for @@ -381,12 +391,16 @@ def read_bits( registeraddress, number_of_bits=number_of_bits, payloadformat=_Payloadformat.BITS, + ignoreslaveaddress=ignoreslaveaddress, ) # Make sure that we really return a list of integers assert isinstance(returnvalue, list) return [int(x) for x in returnvalue] - def write_bits(self, registeraddress: int, values: List[int]) -> None: + def write_bits( + self, registeraddress: int, values: List[int], + ignoreslaveaddress: bool = False, + ) -> None: """Write multiple bits to the slave (instrument). This is for bits that have individual addresses in the instrument. @@ -397,6 +411,7 @@ def write_bits(self, registeraddress: int, values: List[int]) -> None: * registeraddress: The slave register start address. * values: List of 0 or 1, or True or False. The first value in the list is for the bit at the given address. + * ignoreslaveaddress: Bypass the slave address check. Raises: TypeError, ValueError, ModbusException, @@ -420,6 +435,7 @@ def write_bits(self, registeraddress: int, values: List[int]) -> None: values, number_of_bits=len(values), payloadformat=_Payloadformat.BITS, + ignoreslaveaddress=ignoreslaveaddress, ) def read_register( @@ -428,6 +444,7 @@ def read_register( number_of_decimals: int = 0, functioncode: int = 3, signed: bool = False, + ignoreslaveaddress: bool = False, ) -> Union[int, float]: """Read an integer from one 16-bit register in the slave, possibly scaling it. @@ -439,6 +456,7 @@ def read_register( * number_of_decimals: The number of decimals for content conversion. * functioncode: Modbus function code. Can be 3 or 4. * signed: Whether the data should be interpreted as unsigned or signed. + * ignoreslaveaddress: Bypass the slave address check. .. note:: The parameter number_of_decimals was named numberOfDecimals before MinimalModbus 1.0 @@ -488,6 +506,7 @@ def read_register( number_of_registers=1, signed=signed, payloadformat=_Payloadformat.REGISTER, + ignoreslaveaddress=ignoreslaveaddress, ) if int(returnvalue) == returnvalue: return int(returnvalue) @@ -500,6 +519,7 @@ def write_register( number_of_decimals: int = 0, functioncode: int = 16, signed: bool = False, + ignoreslaveaddress: bool = False, ) -> None: """Write an integer to one 16-bit register in the slave, possibly scaling it. @@ -513,6 +533,7 @@ def write_register( * number_of_decimals: The number of decimals for content conversion. * functioncode: Modbus function code. Can be 6 or 16. * signed: Whether the data should be interpreted as unsigned or signed. + * ignoreslaveaddress: Bypass the slave address check. .. note:: The parameter number_of_decimals was named numberOfDecimals before MinimalModbus 1.0 @@ -557,6 +578,7 @@ def write_register( number_of_registers=1, signed=signed, payloadformat=_Payloadformat.REGISTER, + ignoreslaveaddress=ignoreslaveaddress, ) def read_long( @@ -566,6 +588,7 @@ def read_long( signed: bool = False, byteorder: int = BYTEORDER_BIG, number_of_registers: int = 2, + ignoreslaveaddress: bool = False, ) -> int: """Read a long integer (32 or 64 bits) from the slave. @@ -581,6 +604,7 @@ def read_long( :data:`minimalmodbus.BYTEORDER_BIG`. * number_of_registers: The number of registers allocated for the long. Can be 2 or 4. (New in version 2.1) + * ignoreslaveaddress: Bypass the slave address check. ======================= ============== =============== ===================== @@ -615,6 +639,7 @@ def read_long( signed=signed, byteorder=byteorder, payloadformat=_Payloadformat.LONG, + ignoreslaveaddress=ignoreslaveaddress, ) ) @@ -625,6 +650,7 @@ def write_long( signed: bool = False, byteorder: int = BYTEORDER_BIG, number_of_registers: int = 2, + ignoreslaveaddress: bool = False, ) -> None: """Write a long integer (32 or 64 bits) to the slave. @@ -645,6 +671,7 @@ def write_long( :data:`minimalmodbus.BYTEORDER_BIG`. * number_of_registers: The number of registers allocated for the long. Can be 2 or 4. (New in version 2.1) + * ignoreslaveaddress: Bypass the slave address check. Raises: TypeError, ValueError, ModbusException, @@ -684,6 +711,7 @@ def write_long( signed=signed, byteorder=byteorder, payloadformat=_Payloadformat.LONG, + ignoreslaveaddress=ignoreslaveaddress, ) def read_float( @@ -692,6 +720,7 @@ def read_float( functioncode: int = 3, number_of_registers: int = 2, byteorder: int = BYTEORDER_BIG, + ignoreslaveaddress: bool = False, ) -> float: r"""Read a floating point number from the slave. @@ -713,6 +742,7 @@ def read_float( * byteorder: How multi-register data should be interpreted. Use the BYTEORDER_xxx constants. Defaults to :data:`minimalmodbus.BYTEORDER_BIG`. + * ignoreslaveaddress: Bypass the slave address check. .. note:: The parameter number_of_registers was named numberOfRegisters before MinimalModbus 1.0 @@ -745,6 +775,7 @@ def read_float( number_of_registers=number_of_registers, byteorder=byteorder, payloadformat=_Payloadformat.FLOAT, + ignoreslaveaddress=ignoreslaveaddress, ) ) @@ -754,6 +785,7 @@ def write_float( value: Union[int, float], number_of_registers: int = 2, byteorder: int = BYTEORDER_BIG, + ignoreslaveaddress: bool = False, ) -> None: """Write a floating point number to the slave. @@ -772,6 +804,7 @@ def write_float( * byteorder: How multi-register data should be interpreted. Use the BYTEORDER_xxx constants. Defaults to :data:`minimalmodbus.BYTEORDER_BIG`. + * ignoreslaveaddress: Bypass the slave address check. .. note:: The parameter number_of_registers was named numberOfRegisters before MinimalModbus 1.0 @@ -794,10 +827,12 @@ def write_float( number_of_registers=number_of_registers, byteorder=byteorder, payloadformat=_Payloadformat.FLOAT, + ignoreslaveaddress=ignoreslaveaddress, ) def read_string( - self, registeraddress: int, number_of_registers: int = 16, functioncode: int = 3 + self, registeraddress: int, number_of_registers: int = 16, + functioncode: int = 3, ignoreslaveaddress: bool = False, ) -> str: """Read an ASCII string from the slave. @@ -811,6 +846,7 @@ def read_string( * registeraddress: The slave register start address. * number_of_registers: The number of registers allocated for the string. * functioncode: Modbus function code. Can be 3 or 4. + * ignoreslaveaddress: Bypass the slave address check. .. note:: The parameter number_of_registers was named numberOfRegisters before MinimalModbus 1.0 @@ -835,11 +871,13 @@ def read_string( registeraddress, number_of_registers=number_of_registers, payloadformat=_Payloadformat.STRING, + ignoreslaveaddress=ignoreslaveaddress, ) ) def write_string( - self, registeraddress: int, textstring: str, number_of_registers: int = 16 + self, registeraddress: int, textstring: str, + number_of_registers: int = 16, ignoreslaveaddress: bool = False, ) -> None: """Write an ASCII string to the slave. @@ -855,6 +893,7 @@ def write_string( * registeraddress: The slave register start address. * textstring: The string to store in the slave, must be ASCII. * number_of_registers: The number of registers allocated for the string. + * ignoreslaveaddress: Bypass the slave address check. .. note:: The parameter number_of_registers was named numberOfRegisters before MinimalModbus 1.0 @@ -888,10 +927,12 @@ def write_string( textstring, number_of_registers=number_of_registers, payloadformat=_Payloadformat.STRING, + ignoreslaveaddress=ignoreslaveaddress, ) def read_registers( - self, registeraddress: int, number_of_registers: int, functioncode: int = 3 + self, registeraddress: int, number_of_registers: int, + functioncode: int = 3, ignoreslaveaddress: bool = False ) -> List[int]: """Read integers from 16-bit registers in the slave. @@ -902,6 +943,7 @@ def read_registers( * registeraddress: The slave register start address. * number_of_registers: The number of registers to read, max 125 registers. * functioncode: Modbus function code. Can be 3 or 4. + * ignoreslaveaddress: Bypass the slave address check. .. note:: The parameter number_of_registers was named numberOfRegisters before MinimalModbus 1.0 @@ -929,12 +971,16 @@ def read_registers( registeraddress, number_of_registers=number_of_registers, payloadformat=_Payloadformat.REGISTERS, + ignoreslaveaddress=ignoreslaveaddress, ) # Make sure that we really return a list of integers assert isinstance(returnvalue, list) return [int(x) for x in returnvalue] - def write_registers(self, registeraddress: int, values: List[int]) -> None: + def write_registers( + self, registeraddress: int, values: List[int], + ignoreslaveaddress: bool = False, + ) -> None: """Write integers to 16-bit registers in the slave. The slave register can hold integer values in the range 0 to @@ -950,6 +996,7 @@ def write_registers(self, registeraddress: int, values: List[int]) -> None: * values: The values to store in the slave registers, max 123 values. The first value in the list is for the register at the given address. + * ignoreslaveaddress: Bypass the slave address check. .. note:: The parameter number_of_registers was named numberOfRegisters before MinimalModbus 1.0 @@ -979,6 +1026,7 @@ def write_registers(self, registeraddress: int, values: List[int]) -> None: values, number_of_registers=len(values), payloadformat=_Payloadformat.REGISTERS, + ignoreslaveaddress=ignoreslaveaddress, ) # ############### # From 1ea2caa95bbb48a6dcf0d30bdac3e0b552c435c2 Mon Sep 17 00:00:00 2001 From: penguintamer <159223587+penguintamer@users.noreply.github.com> Date: Wed, 3 Apr 2024 00:02:26 -0800 Subject: [PATCH 6/7] black --- minimalmodbus.py | 60 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/minimalmodbus.py b/minimalmodbus.py index 06c45c4..59fbada 100644 --- a/minimalmodbus.py +++ b/minimalmodbus.py @@ -298,7 +298,9 @@ def _print_debug(self, text: str) -> None: # ################################# # def read_bit( - self, registeraddress: int, functioncode: int = 2, + self, + registeraddress: int, + functioncode: int = 2, ignoreslaveaddress: bool = False, ) -> int: """Read one bit from the slave (instrument). @@ -329,7 +331,10 @@ def read_bit( ) def write_bit( - self, registeraddress: int, value: int, functioncode: int = 5, + self, + registeraddress: int, + value: int, + functioncode: int = 5, ignoreslaveaddress: bool = False, ) -> None: """Write one bit to the slave (instrument). @@ -358,7 +363,10 @@ def write_bit( ) def read_bits( - self, registeraddress: int, number_of_bits: int, functioncode: int = 2, + self, + registeraddress: int, + number_of_bits: int, + functioncode: int = 2, ignoreslaveaddress: bool = False, ) -> List[int]: """Read multiple bits from the slave (instrument). @@ -398,7 +406,9 @@ def read_bits( return [int(x) for x in returnvalue] def write_bits( - self, registeraddress: int, values: List[int], + self, + registeraddress: int, + values: List[int], ignoreslaveaddress: bool = False, ) -> None: """Write multiple bits to the slave (instrument). @@ -831,8 +841,11 @@ def write_float( ) def read_string( - self, registeraddress: int, number_of_registers: int = 16, - functioncode: int = 3, ignoreslaveaddress: bool = False, + self, + registeraddress: int, + number_of_registers: int = 16, + functioncode: int = 3, + ignoreslaveaddress: bool = False, ) -> str: """Read an ASCII string from the slave. @@ -876,8 +889,11 @@ def read_string( ) def write_string( - self, registeraddress: int, textstring: str, - number_of_registers: int = 16, ignoreslaveaddress: bool = False, + self, + registeraddress: int, + textstring: str, + number_of_registers: int = 16, + ignoreslaveaddress: bool = False, ) -> None: """Write an ASCII string to the slave. @@ -931,8 +947,11 @@ def write_string( ) def read_registers( - self, registeraddress: int, number_of_registers: int, - functioncode: int = 3, ignoreslaveaddress: bool = False + self, + registeraddress: int, + number_of_registers: int, + functioncode: int = 3, + ignoreslaveaddress: bool = False, ) -> List[int]: """Read integers from 16-bit registers in the slave. @@ -978,7 +997,9 @@ def read_registers( return [int(x) for x in returnvalue] def write_registers( - self, registeraddress: int, values: List[int], + self, + registeraddress: int, + values: List[int], ignoreslaveaddress: bool = False, ) -> None: """Write integers to 16-bit registers in the slave. @@ -1324,7 +1345,8 @@ def _generic_command( # Communicate with instrument payload_from_slave = self._perform_command( - functioncode, payload_to_slave, ignoreslaveaddress) + functioncode, payload_to_slave, ignoreslaveaddress + ) # There is no response for broadcasts if self.address == _SLAVEADDRESS_BROADCAST: @@ -1349,8 +1371,10 @@ def _generic_command( # #################################### # def _perform_command( - self, functioncode: int, payload_to_slave: bytes, - ignoreslaveaddress: bool = False + self, + functioncode: int, + payload_to_slave: bytes, + ignoreslaveaddress: bool = False, ) -> bytes: """Perform the command having the *functioncode*. @@ -1412,8 +1436,7 @@ def _perform_command( # Extract payload payload_from_slave = _extract_payload( - response_bytes, self.address, self.mode, functioncode, - ignoreslaveaddress + response_bytes, self.address, self.mode, functioncode, ignoreslaveaddress ) return payload_from_slave @@ -1843,7 +1866,10 @@ def _embed_payload( def _extract_payload( - response: bytes, slaveaddress: int, mode: str, functioncode: int, + response: bytes, + slaveaddress: int, + mode: str, + functioncode: int, ignoreslaveaddress: bool = False, ) -> bytes: """Extract the payload data part from the slave's response. From 8d3c88baccf24c23075f0d09ea52c6206b98cf49 Mon Sep 17 00:00:00 2001 From: penguintamer <159223587+penguintamer@users.noreply.github.com> Date: Wed, 3 Apr 2024 19:38:06 -0800 Subject: [PATCH 7/7] docs: document ignoreslaveaddress feature --- docs/advancedusage.rst | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/advancedusage.rst b/docs/advancedusage.rst index c0c6b53..32a719c 100644 --- a/docs/advancedusage.rst +++ b/docs/advancedusage.rst @@ -226,6 +226,22 @@ Add this to :func:`._extract_payload` function, after the argument validity test pass +Handling instrument address mismatch +-------------------------------------------------------------------------- +Some commands or instrument access patterns may result in responses whose reported slave +address differs from the address used to send the command. Examples include sending a +command to change the device's address or using a "universal address" to communicate +with a single connected device. Note that you should never use a "universal address" when +more than one device is connected to the bus. + +To ignore the slave address returned by a command, set the "ignoreslaveaddress" parameter +to True: + + instr = minimalmodbus.Instrument('/dev/ttyUSB0', 1) + # change device's address to 23 using register 0x17 + instr.write_register(0x17, 23, ignoreslaveaddress=True) + + Install or uninstalling a distribution --------------------------------------------------------------------------