Internal documentation for MinimalModbus

MinimalModbus: A Python driver for Modbus RTU/ASCII via serial port.

minimalmodbus.MODE_RTU = 'rtu'

Use Modbus RTU communication.

minimalmodbus.MODE_ASCII = 'ascii'

Use Modbus ASCII communication.

minimalmodbus.BYTEORDER_BIG = 0

Use big endian byteorder.

minimalmodbus.BYTEORDER_LITTLE = 1

Use little endian byteorder.

minimalmodbus.BYTEORDER_BIG_SWAP = 2

Use big endian byteorder, with swap.

minimalmodbus.BYTEORDER_LITTLE_SWAP = 3

Use litte endian byteorder, with swap.

class minimalmodbus._Payloadformat(*args, **kwds)[source]
BIT = 1
BITS = 2
FLOAT = 3
LONG = 4
REGISTER = 5
REGISTERS = 6
STRING = 7
__module__ = 'minimalmodbus'
class minimalmodbus.Instrument(port: Union[str, serial.serialposix.Serial], slaveaddress: int, mode: str = 'rtu', close_port_after_each_call: bool = False, debug: bool = False)[source]

Instrument class for talking to instruments (slaves).

Uses the Modbus RTU or ASCII protocols (via RS485 or RS232).

Args:
  • port: The serial port name, for example /dev/ttyUSB0 (Linux), /dev/tty.usbserial (OS X) or COM4 (Windows). It is also possible to pass in an already opened serial.Serial object (new in version 2.1).
  • slaveaddress: Slave address in the range 0 to 247. Address 0 is for broadcast, and 248-255 are reserved.
  • mode: Mode selection. Can be minimalmodbus.MODE_RTU or minimalmodbus.MODE_ASCII.
  • close_port_after_each_call: If the serial port should be closed after each call to the instrument.
  • debug: Set this to True to print the communication details
__init__(port: Union[str, serial.serialposix.Serial], slaveaddress: int, mode: str = 'rtu', close_port_after_each_call: bool = False, debug: bool = False) → None[source]

Initialize instrument and open corresponding serial port.

address = None

Slave address (int). Most often set by the constructor (see the class documentation).

Slave address 0 is for broadcasting to all slaves (no responses are sent). It is only possible to write infomation (not read) via broadcast. A long delay is added after each transmission to allow the slowest slaves to digest the information.

New in version 2.0: Support for broadcast

mode = None

Slave mode (str), can be minimalmodbus.MODE_RTU or minimalmodbus.MODE_ASCII. Most often set by the constructor (see the class documentation). Defaults to RTU.

Changing this will not affect how other instruments use the same serial port.

New in version 0.6.

precalculate_read_size = None

If this is False, the serial port reads until timeout instead of just reading a specific number of bytes. Defaults to True.

Changing this will not affect how other instruments use the same serial port.

New in version 0.5.

debug = None

Set this to True to print the communication details. Defaults to False.

Most often set by the constructor (see the class documentation).

Changing this will not affect how other instruments use the same serial port.

clear_buffers_before_each_transaction = None

If this is True, the serial port read and write buffers are cleared before each request to the instrument, to avoid cumulative byte sync errors across multiple messages. Defaults to True.

Changing this will not affect how other instruments use the same serial port.

New in version 1.0.

close_port_after_each_call = None

If this is True, the serial port will be closed after each call. Defaults to False.

Changing this will not affect how other instruments use the same serial port.

Most often set by the constructor (see the class documentation).

handle_local_echo = None

Set to to True if your RS-485 adaptor has local echo enabled. Then the transmitted message will immeadiately appear at the receive line of the RS-485 adaptor. MinimalModbus will then read and discard this data, before reading the data from the slave. Defaults to False.

Changing this will not affect how other instruments use the same serial port.

New in version 0.7.

serial = None

The serial port object as defined by the pySerial module. Created by the constructor.

Attributes that could be changed after initialisation:

  • port (str): Serial port name.
    • Most often set by the constructor (see the class documentation).
  • baudrate (int): Baudrate in Baud.
    • Defaults to 19200.
  • parity (use PARITY_xxx constants): Parity. See the pySerial module.
    • Defaults to serial.PARITY_NONE.
  • bytesize (int): Bytesize in bits.
    • Defaults to 8.
  • stopbits (use STOPBITS_xxx constants): Number of stopbits. See pySerial.
    • Defaults to serial.STOPBITS_ONE.
  • timeout (float): Read timeout value in seconds.
    • Defaults to 0.05 s.
  • write_timeout (float): Write timeout value in seconds.
    • Defaults to 2.0 s.
__repr__() → str[source]

Give string representation of the Instrument object.

roundtrip_time

Latest measured round-trip time, in seconds. Read only.

Note that the value is None if no data is available.

The round-trip time is the time from minimalmodbus sends request data, to the time it receives response data from the instrument. It is basically the time spent waiting on external communication.

Note that mimimalmodbus also sleeps (not included in the round trip time), for example to fulfill the inter-message time interval or to give slaves time to process broadcasted information.

New in version 2.0

_print_debug(text: str) → None[source]
read_bit(registeraddress: int, functioncode: int = 2) → int[source]

Read one bit from the slave (instrument).

This is for a bit that has its individual address in the instrument.

Args:
  • registeraddress: The slave register address.
  • functioncode Modbus function code. Can be 1 or 2.
Returns:
The bit value 0 or 1.
Raises:
TypeError, ValueError, ModbusException, serial.SerialException (inherited from IOError)
write_bit(registeraddress: int, value: int, functioncode: int = 5) → None[source]

Write one bit to the slave (instrument).

This is for a bit that has its individual address in the instrument.

Args:
  • registeraddress: The slave register address.
  • value: 0 or 1, or True or False
  • functioncode: Modbus function code. Can be 5 or 15.
Raises:
TypeError, ValueError, ModbusException, serial.SerialException (inherited from IOError)
read_bits(registeraddress: int, number_of_bits: int, functioncode: int = 2) → List[int][source]

Read multiple bits from the slave (instrument).

This is for bits that have individual addresses in the instrument.

Args:
  • registeraddress: The slave register start address.
  • number_of_bits: Number of bits to read
  • functioncode: Modbus function code. Can be 1 or 2.
Returns:
A list of bit values 0 or 1. The first value in the list is for the bit at the given address.
Raises:
TypeError, ValueError, ModbusException, serial.SerialException (inherited from IOError)
write_bits(registeraddress: int, values: List[int]) → None[source]

Write multiple bits to the slave (instrument).

This is for bits that have individual addresses in the instrument.

Uses Modbus functioncode 15.

Args:
  • 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.
Raises:
TypeError, ValueError, ModbusException, serial.SerialException (inherited from IOError)
read_register(registeraddress: int, number_of_decimals: int = 0, functioncode: int = 3, signed: bool = False) → Union[int, float][source]

Read an integer from one 16-bit register in the slave, possibly scaling it.

The slave register can hold integer values in the range 0 to 65535 (“Unsigned INT16”).

Args:
  • registeraddress: The slave register address.
  • 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.

Note

The parameter number_of_decimals was named numberOfDecimals before MinimalModbus 1.0

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 by 10 before returning the value.

Similarly number_of_decimals=2 will divide the received data by 100 before returning the value.

Some manufacturers allow negative values for some registers. Instead of an allowed integer range 0 to 65535, a range -32768 to 32767 is allowed. This is implemented as any received value in the upper range (32768 to 65535) is interpreted as negative value (in the range -32768 to -1).

Use the parameter signed=True if reading from a register that can hold negative values. Then upper range data will be automatically converted into negative return values (two’s complement).

signed Data type in slave Alternative name Range
False Unsigned INT16 Unsigned short 0 to 65535
True INT16 Short -32768 to 32767
Returns:
The register data in numerical value (int or float).
Raises:
TypeError, ValueError, ModbusException, serial.SerialException (inherited from IOError)
write_register(registeraddress: int, value: Union[int, float], number_of_decimals: int = 0, functioncode: int = 16, signed: bool = False) → None[source]

Write an integer to one 16-bit register in the slave, possibly scaling it.

The slave register can hold integer values in the range 0 to 65535 (“Unsigned INT16”).

Args:
  • registeraddress: The slave register address.
  • value (int or float): The value to store in the slave register (might be scaled before sending).
  • 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.

Note

The parameter number_of_decimals was named numberOfDecimals before MinimalModbus 1.0

To store for example value=77.0, use number_of_decimals=1 if the slave register will hold it as 770 internally. This will multiply value by 10 before sending it to the slave register.

Similarly number_of_decimals=2 will multiply value by 100 before sending it to the slave register.

As the largest number that can be written to a register is 0xFFFF = 65535, the value and number_of_decimals should max be 65535 when combined. So when using number_of_decimals=3 the maximum value is 65.535.

For discussion on negative values, the range and on alternative names, see read_register().

Use the parameter signed=True if writing to a register that can hold negative values. Then negative input will be automatically converted into upper range data (two’s complement).

Raises:
TypeError, ValueError, ModbusException, serial.SerialException (inherited from IOError)
read_long(registeraddress: int, functioncode: int = 3, signed: bool = False, byteorder: int = 0, number_of_registers: int = 2) → int[source]

Read a long integer (32 or 64 bits) from the slave.

Long integers (32 bits = 4 bytes or 64 bits = 8 bytes) are stored in two or four consecutive 16-bit registers in the slave respectively.

Args:
  • registeraddress: The slave register start address.
  • functioncode: Modbus function code. Can be 3 or 4.
  • signed: Whether the data should be interpreted as unsigned or signed.
  • byteorder: How multi-register data should be interpreted. Use the BYTEORDER_xxx constants. Defaults to minimalmodbus.BYTEORDER_BIG.
  • number_of_registers: The number of registers allocated for the long. Can be 2 or 4. (New in version 2.1)
number_of_registers signed Slave data type Range
2 False Unsigned INT32 0 to 4294967295
2 True INT32 -2147483648 to 2147483647
4 False Unsigned INT64 0 to approx 1.8E19
4 True INT64 Approx -9.2E18 to 9.2E18
Returns:
The numerical value.
Raises:
TypeError, ValueError, ModbusException, serial.SerialException (inherited from IOError)
write_long(registeraddress: int, value: int, signed: bool = False, byteorder: int = 0, number_of_registers: int = 2) → None[source]

Write a long integer (32 or 64 bits) to the slave.

Long integers (32 bits = 4 bytes or 64 bits = 8 bytes) are stored in two or four consecutive 16-bit registers in the slave respectively.

Uses Modbus function code 16.

For discussion on number of bits, number of registers and the range, see read_long().

Args:
  • registeraddress: The slave register start address.
  • value: The value to store in the slave.
  • signed: Whether the data should be interpreted as unsigned or signed.
  • byteorder: How multi-register data should be interpreted. Use the BYTEORDER_xxx constants. Defaults to minimalmodbus.BYTEORDER_BIG.
  • number_of_registers: The number of registers allocated for the long. Can be 2 or 4. (New in version 2.1)
Raises:
TypeError, ValueError, ModbusException, serial.SerialException (inherited from IOError)
read_float(registeraddress: int, functioncode: int = 3, number_of_registers: int = 2, byteorder: int = 0) → float[source]

Read a floating point number from the slave.

Floats are stored in two or more consecutive 16-bit registers in the slave. The encoding is according to the standard IEEE 754.

There are differences in the byte order used by different manufacturers. A floating point value of 1.0 is encoded (in single precision) as 3f800000 (hex). In this implementation the data will be sent as '\x3f\x80' and '\x00\x00' to two consecutetive registers by default. Make sure to test that it makes sense for your instrument. If not, change the byteorder argument.

Args:
  • registeraddress : The slave register start address.
  • functioncode: Modbus function code. Can be 3 or 4.
  • number_of_registers: The number of registers allocated for the float. Can be 2 or 4.
  • byteorder: How multi-register data should be interpreted. Use the BYTEORDER_xxx constants. Defaults to minimalmodbus.BYTEORDER_BIG.

Note

The parameter number_of_registers was named numberOfRegisters before MinimalModbus 1.0

Type of floating point in slave Size Registers Range
Single precision (binary32) 32 bits (4 bytes) 2 registers 1.4E-45 to 3.4E38
Double precision (binary64) 64 bits (8 bytes) 4 registers 5E-324 to 1.8E308
Returns:
The numerical value.
Raises:
TypeError, ValueError, ModbusException, serial.SerialException (inherited from IOError)
write_float(registeraddress: int, value: Union[int, float], number_of_registers: int = 2, byteorder: int = 0) → None[source]

Write a floating point number to the slave.

Floats are stored in two or more consecutive 16-bit registers in the slave.

Uses Modbus function code 16.

For discussion on precision, number of registers and on byte order, see read_float().

Args:
  • registeraddress: The slave register start address.
  • value (float or int): The value to store in the slave
  • number_of_registers: The number of registers allocated for the float. Can be 2 or 4.
  • byteorder: How multi-register data should be interpreted. Use the BYTEORDER_xxx constants. Defaults to minimalmodbus.BYTEORDER_BIG.

Note

The parameter number_of_registers was named numberOfRegisters before MinimalModbus 1.0

Raises:
TypeError, ValueError, ModbusException, serial.SerialException (inherited from IOError)
read_string(registeraddress: int, number_of_registers: int = 16, functioncode: int = 3) → str[source]

Read an ASCII string from the slave.

Each 16-bit register in the slave are interpreted as two characters (each 1 byte = 8 bits). For example 16 consecutive registers can hold 32 characters (32 bytes).

International characters (Unicode/UTF-8) are not supported.

Args:
  • 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.

Note

The parameter number_of_registers was named numberOfRegisters before MinimalModbus 1.0

Returns:
The string.
Raises:
TypeError, ValueError, ModbusException, serial.SerialException (inherited from IOError)
write_string(registeraddress: int, textstring: str, number_of_registers: int = 16) → None[source]

Write an ASCII string to the slave.

Each 16-bit register in the slave are interpreted as two characters (each 1 byte = 8 bits). For example 16 consecutive registers can hold 32 characters (32 bytes).

Uses Modbus function code 16.

International characters (Unicode/UTF-8) are not supported.

Args:
  • 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.

Note

The parameter number_of_registers was named numberOfRegisters before MinimalModbus 1.0

If the textstring is longer than the 2*number_of_registers, an error is raised. Shorter strings are padded with spaces.

Returns:
None
Raises:
TypeError, ValueError, ModbusException, serial.SerialException (inherited from IOError)
read_registers(registeraddress: int, number_of_registers: int, functioncode: int = 3) → List[int][source]

Read integers from 16-bit registers in the slave.

The slave registers can hold integer values in the range 0 to 65535 (“Unsigned INT16”).

Args:
  • 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.

Note

The parameter number_of_registers was named numberOfRegisters before MinimalModbus 1.0

Any scaling of the register data, or converting it to negative number (two’s complement) must be done manually.

Returns:
The register data. The first value in the list is for the register at the given address.
Raises:
TypeError, ValueError, ModbusException, serial.SerialException (inherited from IOError)
write_registers(registeraddress: int, values: List[int]) → None[source]

Write integers to 16-bit registers in the slave.

The slave register can hold integer values in the range 0 to 65535 (“Unsigned INT16”).

Uses Modbus function code 16.

The number of registers that will be written is defined by the length of the values list.

Args:
  • registeraddress: The slave register start address.
  • 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.

Note

The parameter number_of_registers was named numberOfRegisters before MinimalModbus 1.0

Any scaling of the register data, or converting it to negative number (two’s complement) must be done manually.

Raises:
TypeError, ValueError, ModbusException, serial.SerialException (inherited from IOError)
_generic_command(functioncode: int, registeraddress: int, value: Union[None, str, int, float, List[int]] = None, number_of_decimals: int = 0, number_of_registers: int = 0, number_of_bits: int = 0, signed: bool = False, byteorder: int = 0, payloadformat: minimalmodbus._Payloadformat = <_Payloadformat.REGISTER: 5>) → Any[source]

Perform generic command for reading and writing registers and bits.

Args:
  • functioncode: Modbus function code.
  • registeraddress: The register address.
  • value (numerical or string or None or list of int): The value to store in the register. Depends on payloadformat.
  • number_of_decimals: The number of decimals for content conversion. Only for a single register.
  • number_of_registers: The number of registers to read/write. Only certain values allowed, depends on payloadformat.
  • number_of_bits: The number of bits to read/write.
  • signed: Whether the data should be interpreted as unsigned or signed. Only for a single register or for payloadformat=’long’.
  • byteorder: How multi-register data should be interpreted.
  • payloadformat: An _Payloadformat enum

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 from the slave by 10 before returning the value. Similarly number_of_decimals=2 will divide the received data by 100 before returning the value. Same functionality is also used when writing data to the slave.

Returns:

The register data in numerical value (int or float), or the bit value 0 or 1 (int), or a list of int, or None.

Returns None for all write function codes.

Raises:
TypeError, ValueError, ModbusException, serial.SerialException (inherited from IOError)
_perform_command(functioncode: int, payload_to_slave: bytes) → bytes[source]

Perform the command having the functioncode.

Args:
  • functioncode: The function code for the command to be performed. Can for example be ‘Write register’ = 16.
  • payload_to_slave: Data to be transmitted to the slave (will be embedded in slaveaddress, CRC etc)
Returns:
The extracted data payload from the slave. It has been stripped of CRC etc.
Raises:
TypeError, ValueError, ModbusException, serial.SerialException (inherited from IOError)

Makes use of the _communicate() method. The request is generated with the _embed_payload() function, and the parsing of the response is done with the _extract_payload() function.

_communicate(request: bytes, number_of_bytes_to_read: int) → bytes[source]

Talk to the slave via a serial port.

Args:
  • request: The raw request that is to be sent to the slave.
  • number_of_bytes_to_read: Number of bytes to read
Returns:
The raw data returned from the slave.
Raises:
TypeError, ValueError, ModbusException, serial.SerialException (inherited from IOError)

Sleeps if the previous message arrived less than the “silent period” ago.

Will block until reaching number_of_bytes_to_read or timeout.

Additional delay will be used after broadcast transmissions (slave address 0).

If the attribute Instrument.debug is True, the communication details are printed.

If the attribute Instrument.close_port_after_each_call is True the serial port is closed after each call.

Timing:

                Request from master (Master is writing)
                |
                |                             Response from slave
                |                             (Master is reading)
                |                             |
--------R-------W-----------------------------R-------W--------------------
         |     |                               |
         |     |<------- Roundtrip time ------>|
         |     |
      -->|-----|<----- Silent period

The resolution for Python’s time.time() is lower on Windows than on Linux. It is about 16 ms on Windows according to stackoverflow.com/questions/157359/accurate-timestamping-in-python-logging

__dict__ = mappingproxy({'__module__': 'minimalmodbus', '__doc__': 'Instrument class for talking to instruments (slaves).\n\n Uses the Modbus RTU or ASCII protocols (via RS485 or RS232).\n\n Args:\n * port: The serial port name, for example ``/dev/ttyUSB0`` (Linux),\n ``/dev/tty.usbserial`` (OS X) or ``COM4`` (Windows).\n It is also possible to pass in an already opened ``serial.Serial``\n object (new in version 2.1).\n * slaveaddress: Slave address in the range 0 to 247.\n Address 0 is for broadcast, and 248-255 are reserved.\n * mode: Mode selection. Can be :data:`minimalmodbus.MODE_RTU` or\n :data:`minimalmodbus.MODE_ASCII`.\n * close_port_after_each_call: If the serial port should be closed after\n each call to the instrument.\n * debug: Set this to :const:`True` to print the communication details\n ', '__init__': <function Instrument.__init__>, '__repr__': <function Instrument.__repr__>, 'roundtrip_time': <property object>, '_print_debug': <function Instrument._print_debug>, 'read_bit': <function Instrument.read_bit>, 'write_bit': <function Instrument.write_bit>, 'read_bits': <function Instrument.read_bits>, 'write_bits': <function Instrument.write_bits>, 'read_register': <function Instrument.read_register>, 'write_register': <function Instrument.write_register>, 'read_long': <function Instrument.read_long>, 'write_long': <function Instrument.write_long>, 'read_float': <function Instrument.read_float>, 'write_float': <function Instrument.write_float>, 'read_string': <function Instrument.read_string>, 'write_string': <function Instrument.write_string>, 'read_registers': <function Instrument.read_registers>, 'write_registers': <function Instrument.write_registers>, '_generic_command': <function Instrument._generic_command>, '_perform_command': <function Instrument._perform_command>, '_communicate': <function Instrument._communicate>, '__dict__': <attribute '__dict__' of 'Instrument' objects>, '__weakref__': <attribute '__weakref__' of 'Instrument' objects>})
__module__ = 'minimalmodbus'
__weakref__

list of weak references to the object (if defined)

exception minimalmodbus.ModbusException[source]

Base class for Modbus communication exceptions.

Inherits from IOError, which is an alias for OSError in Python3.

__module__ = 'minimalmodbus'
__weakref__

list of weak references to the object (if defined)

exception minimalmodbus.SlaveReportedException[source]

Base class for exceptions that the slave (instrument) reports.

__module__ = 'minimalmodbus'
exception minimalmodbus.SlaveDeviceBusyError[source]

The slave is busy processing some command.

__module__ = 'minimalmodbus'
exception minimalmodbus.NegativeAcknowledgeError[source]

The slave can not fulfil the programming request.

This typically happens when using function code 13 or 14 decimal.

__module__ = 'minimalmodbus'
exception minimalmodbus.IllegalRequestError[source]

The slave has received an illegal request.

__module__ = 'minimalmodbus'
exception minimalmodbus.MasterReportedException[source]

Base class for exceptions that the master (computer) detects.

__module__ = 'minimalmodbus'
exception minimalmodbus.NoResponseError[source]

No response from the slave.

__module__ = 'minimalmodbus'
exception minimalmodbus.LocalEchoError[source]

There is some problem with the local echo.

__module__ = 'minimalmodbus'
exception minimalmodbus.InvalidResponseError[source]

The response does not fulfill the Modbus standad, for example wrong checksum.

__module__ = 'minimalmodbus'
minimalmodbus._create_payload(functioncode: int, registeraddress: int, value: Union[None, str, int, float, List[int]], number_of_decimals: int, number_of_registers: int, number_of_bits: int, signed: bool, byteorder: int, payloadformat: minimalmodbus._Payloadformat) → bytes[source]

Create the payload.

Error checking should have been done before calling this function.

For argument descriptions, see the _generic_command() method.

minimalmodbus._parse_payload(payload: bytes, functioncode: int, registeraddress: int, value: Any, number_of_decimals: int, number_of_registers: int, number_of_bits: int, signed: bool, byteorder: int, payloadformat: minimalmodbus._Payloadformat) → Union[None, str, int, float, List[int], List[float]][source]

Extract the payload data from a response.

Args:
  • payload: Payload to be parsed
  • functioncode: Function code
  • registeraddress: Register address for error checking
  • value: Value in request, for error checking
  • number_of_decimals: Number of decimals
  • number_of_registers: Number of registers
  • number_of_bits: Number of bits
  • signed: Signed
  • byteorder: Byte order
  • payloadformat: Payload format
Returns:
The parsed payload.
minimalmodbus._embed_payload(slaveaddress: int, mode: str, functioncode: int, payloaddata: bytes) → bytes[source]

Build a request from the slaveaddress, the function code and the payload data.

Args:
  • slaveaddress: The address of the slave.
  • mode: The modbus protcol mode (MODE_RTU or MODE_ASCII)
  • functioncode: The function code for the command to be performed. Can for example be 16 (Write register).
  • payloaddata: The bytes to be sent to the slave.
Returns:
The built (raw) request for sending to the slave (including CRC etc).
Raises:
ValueError, TypeError.
The resulting request has the format:
  • RTU Mode: slaveaddress byte + functioncode byte + payloaddata + CRC (two bytes).
  • ASCII Mode: header (:) + slaveaddress (2 characters) + functioncode (2 characters) + payloaddata + LRC (which is two characters) + footer (CR+LF)

The LRC or CRC is calculated from the bytes made up of slaveaddress + functioncode + payloaddata. The header, LRC/CRC, and footer are excluded from the calculation.

minimalmodbus._extract_payload(response: bytes, slaveaddress: int, mode: str, functioncode: int) → bytes[source]

Extract the payload data part from the slave’s response.

Args:
  • response: The raw response bytes from the slave. This is different for RTU and ASCII.
  • 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.
Returns:
The payload part of the response. Conversion from Modbus ASCII has been done if applicable.
Raises:
ValueError, TypeError, ModbusException (or subclasses).

Raises an exception if there is any problem with the received address, the functioncode or the CRC.

The received response should have the format:

  • RTU Mode: slaveaddress byte + functioncode byte + payloaddata + CRC (two bytes)
  • ASCII Mode: header (:) + slaveaddress byte + functioncode byte + payloaddata + LRC (which is two characters) + footer (CR+LF)

For development purposes, this function can also be used to extract the payload from the request sent to the slave.

minimalmodbus._predict_response_size(mode: str, functioncode: int, payload_to_slave: bytes) → int[source]

Calculate the number of bytes that should be received from the slave.

Args:
  • mode: The modbus protcol mode (MODE_RTU or MODE_ASCII)
  • functioncode: Modbus function code.
  • payload_to_slave: The raw request that is to be sent to the slave (not hex encoded)
Returns:
The predicted number of bytes in the response.
Raises:
ValueError, TypeError.
minimalmodbus._calculate_minimum_silent_period(baudrate: Union[int, float]) → float[source]

Calculate the silent period length between messages.

It should correspond to the time to send 3.5 characters.

Args:
baudrate: The baudrate for the serial port
Returns:
The number of seconds that should pass between each message on the bus.
Raises:
ValueError, TypeError.
minimalmodbus._num_to_one_byte(inputvalue: int) → bytes[source]

Convert a numerical value to one byte.

Args:
inputvalue: The value to be converted. Should be >=0 and <=255.
Returns:
One byte representing the inputvalue.
Raises:
TypeError, ValueError
minimalmodbus._num_to_two_bytes(value: Union[int, float], number_of_decimals: int = 0, lsb_first: bool = False, signed: bool = False) → bytes[source]

Convert a numerical value to two bytes, possibly scaling it.

Args:
  • value: The numerical value to be converted.
  • number_of_decimals: Number of decimals, 0 or more, for scaling.
  • lsb_first: Whether the least significant byte should be first in the resulting string.
  • signed: Whether negative values should be accepted.
Returns:
Two bytes representing the inputvalue.
Raises:
TypeError, ValueError.

Use number_of_decimals=1 to multiply value by 10 before sending it to the slave register. Similarly number_of_decimals=2 will multiply value by 100 before sending it to the slave register.

Use the parameter signed=True if making a bytes object that can hold negative values. Then negative input will be automatically converted into upper range data (two’s complement).

The byte order is controlled by the lsb_first parameter, as seen here:

lsb_first parameter Endianness Description
False (default) Big-endian Most significant byte is sent first
True Little-endian Least significant byte is sent first
For example:
To store for example value=77.0, use number_of_decimals = 1 if the register will hold it as 770 internally. The value 770 (dec) is 0302 (hex), where the most significant byte is 03 (hex) and the least significant byte is 02 (hex). With lsb_first = False, the most significant byte is given first why the resulting bytes are \x03\x02, which has the length 2.
minimalmodbus._two_bytes_to_num(inputbytes: bytes, number_of_decimals: int = 0, signed: bool = False) → Union[int, float][source]

Convert two bytes to a numerical value, possibly scaling it.

Args:
  • inputbytes: Bytes of length 2.
  • number_of_decimals: The number of decimals. Defaults to 0.
  • signed: Whether large positive values should be interpreted as negative values.
Returns:
The numerical value (int or float) calculated from the inputbytes.
Raises:
TypeError, ValueError

Use the parameter signed=True if converting bytes that can hold negative values. Then upper range data will be automatically converted into negative return values (two’s complement).

Use number_of_decimals=1 to divide the received data by 10 before returning the value. Similarly number_of_decimals=2 will divide the received data by 100 before returning the value.

The byte order is big-endian, meaning that the most significant byte is sent first.

For example:
The bytes \x03\x02 (which has the length 2) corresponds to 0302 (hex) = 770 (dec). If number_of_decimals = 1, then this is converted to 77.0 (float).
minimalmodbus._long_to_bytes(value: int, signed: bool = False, number_of_registers: int = 2, byteorder: int = 0) → bytes[source]

Convert a long integer to bytes.

Long integers (32 bits = 4 bytes or 64 bite = 8 bytes) are stored in two or four consecutive 16-bit registers in the slave respectively.

Args:
  • value: The numerical value to be converted.
  • signed: Whether large positive values should be interpreted as negative values.
  • number_of_registers: Should be 2 or 4.
  • byteorder: How multi-register data should be interpreted.
Returns:
Four or eight bytes.
Raises:
TypeError, ValueError
minimalmodbus._bytes_to_long(inputbytes: bytes, signed: bool = False, number_of_registers: int = 2, byteorder: int = 0) → int[source]

Convert bytes to a long integer.

Long integers (32 bits = 4 bytes or 64 bite = 8 bytes) are stored in two or four consecutive 16-bit registers in the slave respectively.

Args:
  • inputbytes: Length 4 or 8 bytes.
  • signed: Whether large positive values should be interpreted as negative values.
  • number_of_registers: Should be 2 or 4.
  • byteorder: How multi-register data should be interpreted.
Returns:
The numerical value.
Raises:
ValueError, TypeError
minimalmodbus._float_to_bytes(value: Union[int, float], number_of_registers: int = 2, byteorder: int = 0) → bytes[source]

Convert a numerical value to bytes.

Floats are stored in two or more consecutive 16-bit registers in the slave. The encoding is according to the standard IEEE 754.

Type of floating point in slave Size Registers Range
Single precision (binary32) 32 bits (4 bytes) 2 registers 1.4E-45 to 3.4E38
Double precision (binary64) 64 bits (8 bytes) 4 registers 5E-324 to 1.8E308

A floating point value of 1.0 is encoded (in single precision) as 3f800000 (hex). This will give the bytes '\x3f\x80\x00\x00' (big endian).

Args:
  • value (float or int): The numerical value to be converted.
  • number_of_registers: Can be 2 or 4.
  • byteorder: How multi-register data should be interpreted.
Returns:
4 or 8 bytes.
Raises:
TypeError, ValueError
minimalmodbus._bytes_to_float(inputbytes: bytes, number_of_registers: int = 2, byteorder: int = 0) → float[source]

Convert four bytes to a float.

Floats are stored in two or more consecutive 16-bit registers in the slave.

For discussion on precision, number of bits, number of registers, the range, byte order and on alternative names, see minimalmodbus._float_to_bytes().

Args:
  • inputbytes: Four or eight bytes
  • number_of_registers: Can be 2 or 4.
  • byteorder: How multi-register data should be interpreted.
Returns:
A float.
Raises:
TypeError, ValueError
minimalmodbus._textstring_to_bytes(inputstring: str, number_of_registers: int = 16) → bytes[source]

Convert a text string to bytes.

Each 16-bit register in the slave are interpreted as two characters (1 byte = 8 bits). For example 16 consecutive registers can hold 32 characters (32 bytes).

Not much of conversion is done, mostly error checking and string padding. If the inputstring is shorter that the allocated space, it is padded with spaces in the end.

Args:
  • inputstring: The string to be stored in the slave. Max 2 * number_of_registers characters.
  • number_of_registers: The number of registers allocated for the string.
Returns:
Bytes.
Raises:
TypeError, ValueError
minimalmodbus._bytes_to_textstring(inputbytes: bytes, number_of_registers: int = 16) → str[source]

Convert bytes to a text string.

Each 16-bit register in the slave are interpreted as two characters (1 byte = 8 bits). For example 16 consecutive registers can hold 32 characters (32 bytes).

Not much of conversion is done, mostly error checking.

Args:
  • inputbytes: The bytes from the slave. Length = 2 * number_of_registers
  • number_of_registers (int): The number of registers allocated for the string. Should be >0.
Returns:
A the text string.
Raises:
TypeError, ValueError
minimalmodbus._valuelist_to_bytes(valuelist: List[int], number_of_registers: int) → bytes[source]

Convert a list of numerical values to bytes.

Each element is ‘unsigned INT16’.

Args:
  • valuelist: The input list. The elements should be in the range 0 to 65535.
  • number_of_registers: The number of registers. For error checking. Should equal the number of elements in valuelist.
Returns:
Bytes Length = 2 * number_of_registers
Raises:
TypeError, ValueError
minimalmodbus._bytes_to_valuelist(inputbytes: bytes, number_of_registers: int) → List[int][source]

Convert bytes to a list of numerical values.

The bytes are interpreted as ‘unsigned INT16’.

Args:
  • inputbytes: The bytes from the slave. Length = 2 * number_of_registers
  • number_of_registers: The number of registers. For error checking.
Returns:
A list of integers.
Raises:
TypeError, ValueError
minimalmodbus._pack_bytes(formatstring: str, value: Any) → bytes[source]

Pack a value into bytes.

Uses the built-in struct Python module, and adds relevant error messages.

Args:
  • formatstring: String for the packing. See the struct module for details.
  • value (depends on formatstring): The value to be packed
Returns:
The packed bytes
Raises:
ValueError
minimalmodbus._unpack_bytes(formatstring: str, packed_bytes: bytes) → Any[source]

Unpack bytes into a value.

Uses the built-in struct Python module, and adds relevant error messages.

Args:
  • formatstring: String for the packing. See the struct module for details.
  • packed_bytes: The bytes to be unpacked.
Returns:
A value. The type depends on the formatstring.
Raises:
ValueError
minimalmodbus._swap(inputbytes: bytes) → bytes[source]

Swap bytes pairwise.

This corresponds to a “byte swap”.

Args:
  • inputbytes: input. The length should be an even number.

Return the bytes swapped.

minimalmodbus._hexencode(inputbytes: bytes, insert_spaces: bool = False) → bytes[source]

Convert bytes to a hex encoded bytes.

For example b'J' will return b'4A', and b'\x04' will return b'04'.

Args:
  • inputbytes: Can be for example b'A\x01B\x45'.
  • insert_spaces: Insert space characters between pair of characters to increase readability.
Returns:
Bytes of twice the length, with characters in the range ‘0’ to ‘9’ and ‘A’ to ‘F’. It will be longer if spaces are inserted.
Raises:
TypeError, ValueError
minimalmodbus._hexdecode(hexbytes: bytes) → bytes[source]

Convert hex encoded bytes to bytes.

For example b'4A' will return b'J', and b'04' will return b'\x04' (which has length 1).

Args:
  • hexbytes: Can be for example b'A3' or b'A3B4'. Must be of even length. Allowed bytes are b'0' to b'9', b'a' to b'f' and b'A' to b'F' (not space).
Returns:
Bytes of half the length, with bytes corresponding to all 0-255 values.
Raises:
TypeError, ValueError
minimalmodbus._describe_bytes(inputbytes: bytes) → str[source]

Describe bytes in a human friendly way.

Args:
  • inputbytes: Bytes to describe

Returns a space separated descriptive string. For example b'\x01\x02\x03' gives: 01 02 03 (3 bytes)

minimalmodbus._calculate_number_of_bytes_for_bits(number_of_bits: int) → int[source]

Calculate number of full bytes required to house a number of bits.

Args:
  • number_of_bits: Number of bits

Error checking should have been done before.

For example 9 bits requires 2 bytes.

Algorithm from MODBUS APPLICATION PROTOCOL SPECIFICATION V1.1b

minimalmodbus._bit_to_bytes(value: int) → bytes[source]

Create the bit pattern that is used for writing single bits.

Used for functioncode 5. The same value is sent back in the response from the slave.

This is basically a storage of numerical constants.

Args:
  • value: Can be 0 or 1
Returns:
The bit pattern.
Raises:
TypeError, ValueError
minimalmodbus._bits_to_bytes(valuelist: List[int]) → bytes[source]

Build bytes from a list of bits.

This is used for functioncode 15.

Args:
  • valuelist: List of int (0 or 1)

Returns bytes.

minimalmodbus._bytes_to_bits(inputbytes: bytes, number_of_bits: int) → List[int][source]

Parse bits from bytes.

This is used for parsing the bits in response messages for functioncode 1 and 2.

The first byte in the inputbytes contains info on the addressed bit (in LSB in that byte). Second bit from right contains info on the bit on the next address.

Next byte in the inputbytes contains data on next 8 bits. Might be padded with zeros toward MSB.

Args:
  • inputbytes: Input bytes
  • number_of_bits: Number of bits to extract

Returns a list of values (0 or 1). The length of the list is equal to number_of_bits.

minimalmodbus._twos_complement(x: int, bits: int = 16) → int[source]

Calculate the two’s complement of an integer.

Then also negative values can be represented by an upper range of positive values. See https://en.wikipedia.org/wiki/Two%27s_complement

Args:
  • x: Input integer.
  • bits: Number of bits, must be > 0.
Returns:
The two’s complement of the input.

Example for bits = 8:

x returns
0 0
1 1
127 127
-128 128
-127 129
-1 255
minimalmodbus._from_twos_complement(x: int, bits: int = 16) → int[source]

Calculate the inverse(?) of a two’s complement of an integer.

Args:
  • x: Input integer.
  • bits: Number of bits, must be > 0.
Returns:
The inverse(?) of two’s complement of the input.

Example for bits = 8:

x returns
0 0
1 1
127 127
128 -128
129 -127
255 -1
minimalmodbus._set_bit_on(x: int, bit_num: int) → int[source]

Set bit bit_num to True.

Args:
  • x: The value before.
  • bit_num: The bit number that should be set to True.
Returns:
The value after setting the bit.
For example:
For x = 4 (dec) = 0100 (bin), setting bit number 0 results in 0101 (bin) = 5 (dec).
minimalmodbus._check_bit(x: int, bit_num: int) → bool[source]

Check if bit bit_num is set the input integer.

Args:
  • x: The input value.
  • bit_num: The bit number to be checked
Returns:
True or False
For example:
For x = 4 (dec) = 0100 (bin), checking bit number 2 results in True, and checking bit number 3 results in False.
minimalmodbus._CRC16TABLE = (0, 49345, 49537, 320, 49921, 960, 640, 49729, 50689, 1728, 1920, 51009, 1280, 50625, 50305, 1088, 52225, 3264, 3456, 52545, 3840, 53185, 52865, 3648, 2560, 51905, 52097, 2880, 51457, 2496, 2176, 51265, 55297, 6336, 6528, 55617, 6912, 56257, 55937, 6720, 7680, 57025, 57217, 8000, 56577, 7616, 7296, 56385, 5120, 54465, 54657, 5440, 55041, 6080, 5760, 54849, 53761, 4800, 4992, 54081, 4352, 53697, 53377, 4160, 61441, 12480, 12672, 61761, 13056, 62401, 62081, 12864, 13824, 63169, 63361, 14144, 62721, 13760, 13440, 62529, 15360, 64705, 64897, 15680, 65281, 16320, 16000, 65089, 64001, 15040, 15232, 64321, 14592, 63937, 63617, 14400, 10240, 59585, 59777, 10560, 60161, 11200, 10880, 59969, 60929, 11968, 12160, 61249, 11520, 60865, 60545, 11328, 58369, 9408, 9600, 58689, 9984, 59329, 59009, 9792, 8704, 58049, 58241, 9024, 57601, 8640, 8320, 57409, 40961, 24768, 24960, 41281, 25344, 41921, 41601, 25152, 26112, 42689, 42881, 26432, 42241, 26048, 25728, 42049, 27648, 44225, 44417, 27968, 44801, 28608, 28288, 44609, 43521, 27328, 27520, 43841, 26880, 43457, 43137, 26688, 30720, 47297, 47489, 31040, 47873, 31680, 31360, 47681, 48641, 32448, 32640, 48961, 32000, 48577, 48257, 31808, 46081, 29888, 30080, 46401, 30464, 47041, 46721, 30272, 29184, 45761, 45953, 29504, 45313, 29120, 28800, 45121, 20480, 37057, 37249, 20800, 37633, 21440, 21120, 37441, 38401, 22208, 22400, 38721, 21760, 38337, 38017, 21568, 39937, 23744, 23936, 40257, 24320, 40897, 40577, 24128, 23040, 39617, 39809, 23360, 39169, 22976, 22656, 38977, 34817, 18624, 18816, 35137, 19200, 35777, 35457, 19008, 19968, 36545, 36737, 20288, 36097, 19904, 19584, 35905, 17408, 33985, 34177, 17728, 34561, 18368, 18048, 34369, 33281, 17088, 17280, 33601, 16640, 33217, 32897, 16448)

CRC-16 lookup table with 256 elements.

Built with this code:

poly=0xA001
table = []
for index in range(256):
    data = index << 1
    crc = 0
    for _ in range(8, 0, -1):
        data >>= 1
        if (data ^ crc) & 0x0001:
            crc = (crc >> 1) ^ poly
        else:
            crc >>= 1
    table.append(crc)
output = ''
for i, m in enumerate(table):
    if not i%11:
        output += "\n"
    output += "{:5.0f}, ".format(m)
print output
minimalmodbus._is_serial_object(obj: Any) → bool[source]

Check if an object is serialport-like.

minimalmodbus._calculate_crc(inputbytes: bytes) → bytes[source]

Calculate CRC-16 for Modbus RTU.

Args:
inputbytes: An arbitrary-length message (without the CRC).
Returns:
A two-byte CRC, where the least significant byte is first.
minimalmodbus._calculate_lrc(inputbytes: bytes) → bytes[source]

Calculate LRC for Modbus ASCII.

Args:
inputbytes: An arbitrary-length message (without the beginning colon and terminating CRLF). It should already be decoded from hex-string.
Returns:
A one-byte LRC (not encoded to hex-string)

Algorithm from the document ‘MODBUS over serial line specification and implementation guide V1.02’.

The LRC is calculated as 8 bits (one byte).

For example a resulting LRC 0110 0001 (bin) = 61 (hex) = 97 (dec) = b'a'. This function will then return b'a'.

In Modbus ASCII mode, this should be transmitted using two characters. This example should be transmitted as b'61', which is a bytes object of length two. This function does not handle that conversion for transmission.

minimalmodbus._check_mode(mode: str) → None[source]

Check that the Modbus mode is valid.

Args:
mode: The Modbus mode (MODE_RTU or MODE_ASCII)
Raises:
TypeError, ValueError
minimalmodbus._check_functioncode(functioncode: int, list_of_allowed_values: Optional[List[int], None] = None) → None[source]

Check that the given functioncode is in the list_of_allowed_values.

Also verifies that 1 <= function code <= 127.

Args:
  • functioncode: The function code
  • list_of_allowed_values: Allowed values. Use None to bypass this part of the checking.
Raises:
TypeError, ValueError
minimalmodbus._check_slaveaddress(slaveaddress: int) → None[source]

Check that the given slaveaddress is valid.

Args:
slaveaddress: The slave address
Raises:
TypeError, ValueError
minimalmodbus._check_registeraddress(registeraddress: int) → None[source]

Check that the given registeraddress is valid.

Args:
registeraddress: The register address
Raises:
TypeError, ValueError
minimalmodbus._check_response_payload(payload: bytes, functioncode: int, registeraddress: int, value: Any, number_of_decimals: int, number_of_registers: int, number_of_bits: int, signed: bool, byteorder: int, payloadformat: minimalmodbus._Payloadformat) → None[source]

Check the response payload.

Args:
  • payload: Payload to be checked
  • functioncode: Function code
  • registeraddress: Register address
  • value: Value in request
  • number_of_decimals: Number of decimals
  • number_of_registers: Number of registers
  • number_of_bits: Number of bits
  • signed: Signed
  • byteorder: Byte order
  • payloadformat: Payload format
Raises:
ValueError, TypeError
minimalmodbus._check_response_slaveerrorcode(response: bytes) → None[source]

Check if the slave indicates an error.

Args:
  • response: Response from the slave

The response is in RTU format, but the checksum might be one or two bytes depending on whether it was sent in RTU or ASCII mode.

Checking of type and length of the response should be done before calling this functions.

Raises:
SlaveReportedException or subclass
minimalmodbus._check_response_bytecount(payload: bytes) → None[source]

Check that the number of bytes as given in the response is correct.

The first byte in the payload indicates the length of the payload (first byte not counted).

Args:
payload: The payload
Raises:
TypeError, ValueError, InvalidResponseError
minimalmodbus._check_response_registeraddress(payload: bytes, registeraddress: int) → None[source]

Check that the start adress as given in the response is correct.

The first two bytes in the payload holds the address value.

Args:
  • payload: The payload
  • registeraddress: What the register address actually shoud be.
Raises:
TypeError, ValueError, InvalidResponseError
minimalmodbus._check_response_number_of_registers(payload: bytes, number_of_registers: int) → None[source]

Check that the number of written registers as given in the response is correct.

The bytes 2 and 3 (zero based counting) in the payload holds the value.

Args:
  • payload: The payload
  • number_of_registers: Number of registers that have been written
Raises:
TypeError, ValueError, InvalidResponseError
minimalmodbus._check_response_writedata(payload: bytes, writedata: bytes) → None[source]

Check that the write data as given in the response is correct.

The bytes 2 and 3 (zero based counting) in the payload holds the write data.

Args:
  • payload: The payload
  • writedata: The data that should have been written. Length should be 2 bytes.
Raises:
TypeError, ValueError, InvalidResponseError
minimalmodbus._check_bytes(inputbytes: bytes, description: str, minlength: int = 0, maxlength: Optional[int, None] = None, exception_type: Type[Exception] = <class 'ValueError'>) → None[source]

Check that the bytes are valid.

Args:
  • inputbytes: The bytes to be checked
  • description: Used in error messages for the checked inputbytes
  • minlength: Minimum length of the inputbytes
  • maxlength: Maximum length of the inputbytes
  • exception_type: The type of exception to raise for length errors
minimalmodbus._check_string(inputstring: str, description: str, minlength: int = 0, maxlength: Optional[int, None] = None, force_ascii: bool = False, exception_type: Type[Exception] = <class 'ValueError'>) → None[source]

Check that the given string is valid.

Args:
  • inputstring: The string to be checked
  • description: Used in error messages for the checked inputstring
  • minlength: Minimum length of the string
  • maxlength: Maximum length of the string
  • force_ascii: Enforce that the string is ASCII
  • exception_type: The type of exception to raise for length errors
Raises:
TypeError, ValueError or the one given by exception_type

Uses the function _check_int() internally.

minimalmodbus._check_int(inputvalue: int, minvalue: Optional[int, None] = None, maxvalue: Optional[int, None] = None, description: str = 'inputvalue') → None[source]

Check that the given integer is valid.

Args:
  • inputvalue: The integer to be checked
  • minvalue: Minimum value of the integer
  • maxvalue: Maximum value of the integer
  • description: Used in error messages for the checked inputvalue
Raises:
TypeError, ValueError

Note: Can not use the function _check_string(), as that function uses this function internally.

minimalmodbus._check_numerical(inputvalue: Union[int, float], minvalue: Union[None, int, float] = None, maxvalue: Union[None, int, float] = None, description: str = 'inputvalue') → None[source]

Check that the given numerical value is valid.

Args:
  • inputvalue: The value to be checked.
  • minvalue: Minimum value. Use None to skip this part of the test.
  • maxvalue: Maximum value. Use None to skip this part of the test.
  • description: Used in error messages for the checked inputvalue
Raises:
TypeError, ValueError

Note: Can not use the function _check_string(), as it uses this function internally.

minimalmodbus._check_bool(inputvalue: bool, description: str = 'inputvalue') → None[source]

Check that the given inputvalue is a boolean.

Args:
  • inputvalue: The value to be checked.
  • description: Used in error messages for the checked inputvalue.
Raises:
TypeError, ValueError
minimalmodbus._get_diagnostic_string() → str[source]

Generate a diagnostic string, showing the module version, the platform etc.

Returns:
A descriptive string.
minimalmodbus._getDiagnosticString() → str

Generate a diagnostic string, showing the module version, the platform etc.

Returns:
A descriptive string.