Minimalmodbus Readthedocs Io en Master
Minimalmodbus Readthedocs Io en Master
Minimalmodbus Readthedocs Io en Master
Release 2.0.1
Jonas Berg
1 MinimalModbus 3
1.1 Web resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2 Installation 5
2.1 Dependencies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2 Alternate installation on Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.3 If everything else fails . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3 Usage 7
3.1 General on Modbus protocol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.2 Typical hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.3 Typical usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.4 Default values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.5 Confusing Modbus register addresses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.6 Using multiple instruments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.7 Closing serial port after each call . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.8 Handling communication errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.9 Byte order for floating point values and long integers . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.10 Subclassing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.11 Extending . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
5 Modbus details 23
5.1 Modbus data types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
5.2 Some extensions not covered by the official standard . . . . . . . . . . . . . . . . . . . . . . . . . . 24
5.3 Implemented functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
5.4 Byte order for data stored in serveral registers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
5.5 Modbus implementation details . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
5.6 Reading individual bits from a 16-bit register . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
5.7 Known deviations from the standard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
5.8 MODBUS ASCII format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
5.9 Manual testing of Modbus equipment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
6 Serial communication 31
6.1 Timing of the serial communications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
i
6.2 RS-485 introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
6.3 Controlling the RS485 transmitter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
6.4 Controlling the RS-485 transceiver from userspace . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
7 Debug mode 35
7.1 Debug mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
8 Trouble shooting 39
8.1 No communication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
8.2 Local echo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
8.3 Empty bytes added in the beginning or the end on the received message . . . . . . . . . . . . . . . . 40
8.4 Serial adaptors not recognized . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
8.5 Known issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
8.6 Issues when running under Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
8.7 Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
10 Developer documentation 51
10.1 Design considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
10.2 General driver structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
10.3 Number conversion to and from bytestrings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
10.4 Unit testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
10.5 Making sure that error messages are informative for the user . . . . . . . . . . . . . . . . . . . . . . 53
10.6 Recording communication data for unittesting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
10.7 Using the dummy serial port . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
10.8 Data encoding in Python2 and Python3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
10.9 Extending MinimalModbus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
10.10 Other useful internal functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
10.11 Generate documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
10.12 Webpage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
10.13 Codecov.io . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
10.14 Notes on distribution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
10.15 Preparation for release . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
10.16 Useful development tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
10.17 Git usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
10.18 Sphinx usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
10.19 TODO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
12 Credits 71
12.1 Development Lead . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
12.2 Contributors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
ii
13 Related software 73
14 History 75
14.1 Release 2.0.1 (2021-08-11) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
14.2 Release 2.0.0 (2021-08-10) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
14.3 Release 1.0.2 (2019-08-11) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
14.4 Release 1.0.1 (2019-08-10) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
14.5 Release 1.0.0 (2019-08-10) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
14.6 Release 0.7 (2015-07-30) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
14.7 Release 0.6 (2014-06-22) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
14.8 Release 0.5 (2014-03-23) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
14.9 Release 0.4 (2012-09-08) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
14.10 Release 0.3.2 (2012-01-25) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
14.11 Release 0.3.1 (2012-01-24) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
14.12 Release 0.3 (2012-01-23) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
14.13 Release 0.2 (2011-08-19) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
14.14 Release 0.1 (2011-06-16) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
15 Internal documentation 79
15.1 Documentation for dummy_serial (which is a serial port mock) . . . . . . . . . . . . . . . . . . . . 79
15.2 Internal documentation for MinimalModbus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
15.3 Internal documentation for unit testing of MinimalModbus . . . . . . . . . . . . . . . . . . . . . . . 102
15.4 Internal documentation for hardware testing of MinimalModbus using DTB4824 . . . . . . . . . . . 117
Index 125
iii
iv
MinimalModbus Documentation, Release 2.0.1
Documentation built using Sphinx Aug 11, 2021 for MinimalModbus version 2.0.1.
Contents:
Contents 1
MinimalModbus Documentation, Release 2.0.1
2 Contents
CHAPTER 1
MinimalModbus
• Documentation: https://minimalmodbus.readthedocs.io
• Source code on GitHub: https://github.com/pyhys/minimalmodbus
• Python package index (PyPI) with download: https://pypi.org/project/minimalmodbus/
Other web pages:
• Readthedocs project page: https://readthedocs.org/projects/minimalmodbus/
• codecov.io project page: https://codecov.io/github/pyhys/minimalmodbus
Obsolete web pages:
• Old Travis CI build status page: https://travis-ci.org/pyhys/minimalmodbus
• Old Sourceforge documentation page: http://minimalmodbus.sourceforge.net/
• Old Sourceforge project page: https://sourceforge.net/projects/minimalmodbus
• Old Sourceforge repository: https://sourceforge.net/p/minimalmodbus/code/HEAD/tree/
3
MinimalModbus Documentation, Release 2.0.1
1.2 Features
MinimalModbus is an easy-to-use Python module for talking to instruments (slaves) from a computer (master) using
the Modbus protocol, and is intended to be running on the master. The only dependence is the pySerial module (also
pure Python).
There are convenience functions to handle floats, strings and long integers (in different byte orders).
This software supports the ‘Modbus RTU’ and ‘Modbus ASCII’ serial communication versions of the protocol, and is
intended for use on Linux, OS X and Windows platforms. It is open source, and has the Apache License, Version 2.0.
For Python 3.6 and later. Tested with Python 3.6, 3.7, 3.8, 3.9 and 3.10.
This package uses semantic versioning.
4 Chapter 1. MinimalModbus
CHAPTER 2
Installation
or possibly:
2.1 Dependencies
Python versions 3.6 and higher are supported. This module is pure Python.
This module relies on pySerial (also pure Python) to do the heavy lifting, and it is the only dependency. It is BSD-3-
Clause licensed. You can find it at the Python package index: https://pypi.org/project/pyserial The version of pyserial
should be 3.0 or later.
Note: Since MinimalModbus 1.0 you need to use pySerial version at least 3.0
You can also manually download the compressed source files from https://pypi.org/project/minimalmodbus/. In that
case you first need to manually install pySerial from https://pypi.org/project/pyserial.
There are compressed source files for Unix/Linux (.tar.gz) and Windows (.zip). To install a manually downloaded file
use the pip tool:
5
MinimalModbus Documentation, Release 2.0.1
You can download the raw minimalmodbus.py file from GitHub, and put it in the same directory as your other code.
Note that you must have pySerial installed.
6 Chapter 2. Installation
CHAPTER 3
Usage
The application for which I wrote this software is to read and write data from Eurotherm process controllers. These
come with different types of communication protocols, but the controllers I prefer use the Modbus RTU protocol.
MinimalModbus is intended for general communication using the Modbus RTU protocol (using a serial link), so there
should be lots of applications.
There can be several instruments (slaves, nodes) on a single bus, and the slaves have addresses in the range 1 to 247.
In the Modbus RTU protocol, only the master can initiate communication. The physical layer is most often the serial
bus RS485, which is described at https://en.wikipedia.org/wiki/RS-485.
7
MinimalModbus Documentation, Release 2.0.1
To connect your computer to the RS485 bus, a serial port is required. There are direct USB-to-RS485 converters, but I
use a USB-to-RS232 converter together with an industrial RS232-to-RS485 converter (Westermo MDW-45). This has
the advantage that the latter is galvanically isolated using opto-couplers, and has transient supression.
The instrument is typically connected via a serial port, and a USB-to-serial adaptor should be used on most modern
computers. How to configure such a serial port is described on the pySerial page: https://pyserial.readthedocs.io
For example, consider an instrument (slave) with Modbus RTU mode and address number 1 to which we are to
communicate via a serial port with the name /dev/ttyUSB1. The instrument stores the measured temperature in
register 289. For this instrument a temperature of 77.2 C is stored as (the integer) 772, why we use 1 decimal. To read
this data from the instrument:
#!/usr/bin/env python3
import minimalmodbus
Most of the serial port parameters have the default values defined in the Modbus standard (19200 8N1):
8 Chapter 3. Usage
MinimalModbus Documentation, Release 2.0.1
instrument.serial.timeout = 0.2
print(instrument)
import serial
instrument.serial.parity = serial.PARITY_EVEN
instrument.serial.parity = minimalmodbus.serial.PARITY_EVEN
Warning: The module level constants minimalmodbus.BAUDRATE etc were removed in version 1.0
instrument.serial.close()
Sometimes “entity numbers” are used in documentation for Modbus instruments. These numbers are typically five
or six digits long, and contains info about both the register type and the register address. The first digit describes
the register type, for example 4 is a holding register. The rest of the digits describes the address plus one (yes, very
confusing).
According to the example on https://en.wikipedia.org/wiki/Modbus, an entity number of 40100 describes a holding
register with address 99.
More details on different types of Modbus registers are found in Modbus details.
Use a single script for talking to all your instruments (if connected via the same serial port). Create several instrument
objects like:
instrumentA = minimalmodbus.Instrument('/dev/ttyUSB1', 1)
instrumentA.serial.baudrate = 9600
instrumentA.serial.timeout = 0.2
instrumentA.mode = minimalmodbus.MODE_RTU
instrumentB = minimalmodbus.Instrument('/dev/ttyUSB1', 2)
instrumentB.mode = minimalmodbus.MODE_ASCII
instrumentC = minimalmodbus.Instrument('/dev/ttyUSB2', 1)
The instruments sharing the same serial port share the same serial Python object, so instrumentB will have the
same baudrate and timeout as instrumentA.
You can use instruments on different serial ports in the same script, but running several scripts using the same port will
give problems.
In some cases (mostly on Windows) the serial port must be closed after each call.
Enable that behavior with:
instrument.close_port_after_each_call = True
Your top-level code should be able to handle communication errors. Glitches in the serial communication might
happen now and then.
Instead of running:
print(instrument.read_register(4143))
Use:
try:
print(instrument.read_register(4143))
except IOError:
print("Failed to read from instrument")
3.9 Byte order for floating point values and long integers
The byte order used by manufacturers differ. See See Byte order for data stored in serveral registers.
3.10 Subclassing
It is better to put the details on registers etc in a driver for the specific instrument. See Making drivers for specific
instruments.
10 Chapter 3. Usage
MinimalModbus Documentation, Release 2.0.1
3.11 Extending
It is pretty easy to extend this module to support other functioncodes or special cases. See Extending MinimalModbus.
3.11. Extending 11
MinimalModbus Documentation, Release 2.0.1
12 Chapter 3. Usage
CHAPTER 4
MinimalModbus: A Python driver for Modbus RTU/ASCII via serial port (via USB, RS485 or RS232).
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.Instrument(port: str, slaveaddress: int, mode: str = ’rtu’,
close_port_after_each_call: bool = False, debug: bool =
False)
Bases: object
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).
• slaveaddress: Slave address in the range 0 to 247 (use decimal numbers, not hex). Address 0 is for
broadcast, and 248-255 are reserved.
• mode: Mode selection. Can be minimalmodbus.MODE_RTU or minimalmodbus.
MODE_ASCII.
13
MinimalModbus Documentation, Release 2.0.1
• 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
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 infoma-
tion (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 immea-
diately 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.
15
MinimalModbus Documentation, Release 2.0.1
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).
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) → int
Read a long integer (32 bits) from the slave.
Long integers (32 bits = 4 bytes) are stored in two consecutive 16-bit registers in the slave.
Args:
• registeraddress: The slave register start address (use decimal numbers, not hex).
• 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.
17
MinimalModbus Documentation, Release 2.0.1
write_long(registeraddress: int, value: int, signed: bool = False, byteorder: int = 0) → None
Write a long integer (32 bits) to the slave.
Long integers (32 bits = 4 bytes) are stored in two consecutive 16-bit registers in the slave.
Uses Modbus function code 16.
For discussion on number of bits, number of registers, the range and on alternative names, see
read_long().
Args:
• registeraddress: The slave register start address (use decimal numbers, not hex).
• 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.
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
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 (use decimal numbers, not hex).
• 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
Note: The parameter number_of_registers was named numberOfRegisters before MinimalModbus 1.0
Note: The parameter number_of_registers was named numberOfRegisters before MinimalModbus 1.0
19
MinimalModbus Documentation, Release 2.0.1
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]
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 (use decimal numbers, not hex).
• 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
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 (use decimal numbers, not hex).
• 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)
exception minimalmodbus.ModbusException
Bases: OSError
Base class for Modbus communication exceptions.
Inherits from IOError, which is an alias for OSError in Python3.
exception minimalmodbus.SlaveReportedException
Bases: minimalmodbus.ModbusException
Base class for exceptions that the slave (instrument) reports.
exception minimalmodbus.SlaveDeviceBusyError
Bases: minimalmodbus.SlaveReportedException
The slave is busy processing some command.
exception minimalmodbus.NegativeAcknowledgeError
Bases: minimalmodbus.SlaveReportedException
The slave can not fulfil the programming request.
This typically happens when using function code 13 or 14 decimal.
exception minimalmodbus.IllegalRequestError
Bases: minimalmodbus.SlaveReportedException
The slave has received an illegal request.
exception minimalmodbus.MasterReportedException
Bases: minimalmodbus.ModbusException
Base class for exceptions that the master (computer) detects.
exception minimalmodbus.NoResponseError
Bases: minimalmodbus.MasterReportedException
No response from the slave.
exception minimalmodbus.LocalEchoError
Bases: minimalmodbus.MasterReportedException
There is some problem with the local echo.
exception minimalmodbus.InvalidResponseError
Bases: minimalmodbus.MasterReportedException
The response does not fulfill the Modbus standad, for example wrong checksum.
21
MinimalModbus Documentation, Release 2.0.1
Modbus details
Function codes are used to describe the read or write operations (shown in decimal in the table below)
Note that function code 23 not is implemented by this software (it is for reading and writing in same request).
Function codes 128 and larger are used by slaves to indicate errors.
23
MinimalModbus Documentation, Release 2.0.1
Scaling of register values Some manufacturers store a temperature value of 77.0 C as 770 in the register, to allow
room for one decimal.
Negative numbers (INT16 = short) Some manufacturers allow negative values for some registers. Instead of an
allowed integer range 0-65535, a range -32768 to 32767 is allowed. This is implemented as any received
value in the upper range (32768-65535) is interpreted as negative value (in the range -32768 to -1). This is
two’s complement and is described at https://en.wikipedia.org/wiki/Two%27s_complement. Help functions to
calculate the two’s complement value (and back) are provided in MinimalModbus.
Long integers (‘Unsigned INT32’ or ‘INT32’) These require 32 bits, and are implemented as two consecutive 16-
bit registers. The range is 0 to 4294967295, which is called ‘unsigned INT32’. Alternatively negative values
can be stored if the instrument is defined that way, and is then called ‘INT32’ which has the range -2147483648
to 2147483647. Unfortunately the byte order might differ between manufacturers of Modbus instruments.
Floats (single or double precision) Single precision floating point values (binary32) are defined by 32 bits (4 bytes),
and are implemented as two consecutive 16-bit registers. Correspondingly, double precision floating point values
(binary64) use 64 bits (8 bytes) and are implemented as four consecutive 16-bit registers. How to convert from
the bit values to the floating point value is described in the standard IEEE 754, as seen in https://en.wikipedia.org/
wiki/Floating_point. Unfortunately the byte order might differ between manufacturers of Modbus instruments.
Strings Each register (16 bits) is interpreted as two ASCII characters (each 1 byte = 8 bits). Often 16 consecutive
registers are used, allowing 32 characters in the string. Unicode/UTF-8 is typically not supported.
8-bit registers For example Danfoss use 8-bit registers for storage of some settings internally in the instruments. The
data is nevertherless transmitted as 16 bit over the serial link, so you can read and write like normal (but with
values limited to the range 0-255).
32-bit registers “Enron Modbus” allows larger registers where you can store 32 bits in a single register (instead of
two consecutive 16 bit registers). Not supported by this software.
Bit fields in integers Some manufacturers store multiple bits in a 16-bit register, instead of as individually adressable
bits. This is also known as flag registers. See below for how to use them with this software.
JBUS adressing From Eurotherm Modbus/ProfibusCommunications Handbook: “The JBUS protocol is identical in
all respects but one to the Modbus protocol. The one difference concerns the parameter or register address. Both
use a numeric index but the JBUS index starts at 0 while the Modbus index starts at 1.”
Slave addresses larger than 255 Sometimes the slave address is encoded in two bytes to allow values larger than
255. Not supported by this software.
These are the functions to use for reading and writing registers and bits of your instrument. Study the documentation
of your instrument to find which Modbus function code to use. The function codes (F code) are given in decimal in
this table.
read_registers()3 [or 4] 16
write_registers()
Registers
Integers
Floats and long integers does not fit in a single 16-bit register, so typically consecutive registers are used. However
different manufacturers store the bytes in different order.
The functions handling floats and long integers have a parameter for changing which byte order that is used.
The example column show how the bytes are ordered on the wire (assuming byte A is the most significant byte).
Read more on Modbus byte ordering in these articles:
• https://store.chipkin.com/articles/how-real-floating-point-and-32-bit-data-is-encoded-in-modbus-rtu-messages
• https://www.modbustools.com/poll_display_formats.html
• https://www.simplymodbus.ca/FAQ.htm#Ext
In Modbus RTU, the request message is sent from the master in this format:
• Slave address [1 Byte]
• Function code [1 Byte]. Allowed range is 1 to 127 (in decimal).
• Payload data [0 to 252 Bytes]
• CRC [2 Bytes]. It is a Cyclic Redundancy Check code, for error checking of the message
The response from the client is similar, but with other payload data.
23 ? ?
Read and write multiple registers
For function code 5, the only valid values are 0000 (hex) or FF00 (hex), representing OFF and ON respectively.
It is seen in the table above that the request and response messages are similar for function code 1 to 4. The same can
be said about function code 5 and 6, and also about 15 and 16.
For finding how the k Bytes for the value relates to the number of registers etc (n), see the Modbus documents referred
to above.
Some manufacturers use 16-bit registers to store individual boolean values (bits), so with a single read from a single
address, 16 booleans could be retrieved. This is sometimes called a flag register.
You need to read the register as an integer, and then extract the bit you are interested in. For example to extract the
third bit from right:
registervalue = instrument.read_register(4143)
is_my_bit_set = (registervalue & 0b0000000000000100) > 0
More information on bit manipulation in Python, see the “Single bits” section of https://wiki.python.org/moin/
BitManipulation
Some instruments:
• sets more than one bit in the response when one bit is requested.
• add an extra 0xFE byte after some messages.
• LRC [2 characters]. The LRC is a Longitudinal Redundancy Check code, for error checking of the message.
• Stop [2 characters]. The stop characters are carriage return ('\r' = '\x0D') and line feed ('\n' = '\x0A').
import serial
ser = serial.Serial('/dev/ttyUSB0', 19200, timeout=1)
print(ser)
ser.write(':010310010001EA\r\n')
print(repr(ser.read(1000))) # Read 1000 bytes, or wait for timeout
:0103020136C3
Correspondingly for Modbus ASCII, change the write command to for example:
TODO: Verify
ser.write(':010310010001EA\r\n')
:0103020136C3
It is also easy to test Modbus ASCII equipment from Linux command line. First must the appropriate serial port be
set up properly:
• Print port settings: stty -F /dev/ttyUSB0
• Print all settings for a port: stty -F /dev/ttyUSB0 -a
• Reset port to default values: stty -F /dev/ttyUSB0 sane
• Change port to raw behavior: stty -F /dev/ttyUSB0 raw
• and: stty -F /dev/ttyUSB0 -echo -echoe -echok
• Change port baudrate: stty -F /dev/ttyUSB0 19200
To send out a Modbus ASCII request (read register 0x1001 on slave 1), and print out the response:
:0103020136C3
Serial communication
The Modbus RTU standard prescribes a silent period corresponding to 3.5 characters between each message, to be
able fo figure out where one message ends and the next one starts.
The silent period after the message to the slave is the responsibility of the slave.
The silent period after the message from the slave was previously implemented in MinimalModbus by setting a gen-
erous timeout value, and let the serial read() function wait for timeout.
The character time corresponds to 11 bit times, according to https://www.automation.com/en-us/articles/2012-1/
introduction-to-modbus
According to the Modbus RTU standard, the minimum silent period should be 1.75 ms regardless of the baud rate.
Baud rate Bit rate Bit time Character time 3.5 character times
2400 2400 bits/s 417 us 4.6 ms 16 ms
4800 4800 bits/s 208 us 2.3 ms 8.0 ms
9600 9600 bits/s 104 us 1.2 ms 4.0 ms
19200 19200 bits/s 52 us 573 us 2.0 ms
38400 38400 bits/s 26 us 286 us 1.75 ms (1.0 ms)
115200 115200 bit/s 8.7 us 95 us 1.75 ms (0.33 ms)
Several nodes (instruments) can be connected to one RS485 bus. The bus consists of two lines, A and B, carrying
differential voltages. In both ends of the bus, a 120 Ohm termination resistor is connected between line A and B. Most
often a common ground line is connected between the nodes as well.
At idle, both line A and B rest at the same voltage (or almost the same voltage). When a logic 1 is transmitted, line A
is pulled towards lower voltage and line B is pulled towards higher voltage. Note that the A/B naming is sometimes
31
MinimalModbus Documentation, Release 2.0.1
Controlling the TXENABLE pin on the transceiver chip is the tricky part when it comes to RS485 communication.
There are some options:
Using a USB-to-serial conversion chip that is capable of setting the TXENABLE pin properly See for example
the FTDI chip FT232RL, which has a separate output for this purpose (TXDEN in their terminology). The
Sparkfun breakout board BOB-09822 combines this FTDI chip with a RS485 transceiver chip. The TXDEN
output from the FTDI chip is high (+5 V) when the transmitter is to be activated. The FTDI chip calculates
when the transmitter should be activated, so you do not have to do anything in your application software.
Using a RS232-to-RS485 converter capable of figuring out this by it self This typically requires a microcontroller
in the converter, and that you configure the baud rate, stop bits etc. This is a straight-forward and easy-to-use
alternative, as you can use it together with a standard USB-to-RS232 cable and nothing needs to be done in your
application software. One example of this type of converter is Westermo MDW-45, which I have been using
with great success.
Using a converter where the TXENABLE pin is controlled by the TX pin, sometimes via some timer circuit I
am not conviced that it is a good idea to control the TXENABLE pin by the TX pin, as only one of the logic
levels are actively driving the bus voltage. If using a timer circuit, the hardware needs to be adjusted to the
baudrate.
Have the transmitter constantly enabled Some users have been reporting on success for this strategy. The problem
is that the master and slaves have their transmitters enabled simultaneously. I guess for certain situations (and
being lucky with the transceiver chip) it might work. Note that you will receive your own transmitted message
(local echo). See minimalmodbus.Instrument for echo detais.
Controlling a separate GPIO pin from kernelspace software on embedded Linux machines See for example
https://blog.savoirfairelinux.com/en-ca/2013/rs-485-for-beaglebone-a-quick-peek-at-the-omap-uart/ This is a
very elegant solution, as the TXENABLE pin is controlled by the kernel driver and you don’t have to worry
about it in your application program. Unfortunately this is not available for all boards, for example the standard
distribution for Beaglebone (September 2014).
Controlling a separate GPIO pin from userspace software on embedded Linux machines This will give large
time delays, but might be acceptable for low speeds. It will probaby take 1-3 ms to turn off the transciver.
For this to fit in the 3.5 character time before the slave starts transmitting, max speed can be 9600 bps.
Controlling the RTS pin in the RS232 interface (from userspace), and connecting it to the TXENABLE pin of the transceiver
This will give large time delays, but might be acceptable for low speeds.
As described above, this should be avoided. Nevertheless, for low speeds (maybe up to 9600 bits/s) it might be useful.
This can be done from userspace, but will then lead to large time delays. I have tested this with a 3.3V FTDI USB-
to-serial cable using pySerial on a Linux laptop. The cable has a RTS output, but no TXDEN output. Note that the
RTS output is +3.3 V at idle, and 0 V when RTS is set to True. The delay time is around 1 ms, as measured with
an oscilloscope. This corresponds to approx 100 bit times when running at 115200 bps, but this value also includes
delays caused by the Python intepreter.
If you would like to use this for low speed, it can be implemented as in the contributed pull request: https://github.
com/pyhys/minimalmodbus/pull/70 Then you should provide a callback that enables and disables the transmitter.
Debug mode
To switch on the debug mode, where the communication details are printed:
#!/usr/bin/env python3
import minimalmodbus
With this you can easily see what is sent to and from your instrument, and immediately see what is wrong. This is
very useful also if developing your own Modbus compatible electronic instruments.
Similar in interactive mode:
>>> instrument.read_register(4097,1)
MinimalModbus debug mode. Writing to instrument: '\n\x03\x10\x01\x00\x01\xd0q'
MinimalModbus debug mode. Response from instrument: '\n\x03\x02\x07\xd0\x1e)'
200.0
The data is stored internally in this driver as byte strings (representing byte values). For example a byte with value 18
(dec) = 12 (hex) = 00010010 (bin) is stored in a string of length one. This can be created using the function chr(18),
or by simply typing the string '\x12' (which is a string of length 1). See https://docs.python.org/3/reference/lexical_
analysis.html#string-and-bytes-literals for details on escape sequences.
For more information about hexadecimal numbers, see https://en.wikipedia.org/wiki/Hexadecimal.
Note that the letter A has the hexadecimal ASCII code 41, why the string '\x41' prints 'A'. The Latin-1 encoding
is used (on most installations?), and the conversion table is found on https://en.wikipedia.org/wiki/Latin_1.
The byte strings can look pretty strange when printed, as values 0 to 31 (dec) are ASCII control signs (not correspond-
ing to any letter). For example ‘vertical tab’ and ‘line feed’ are among those. To make the output easier to understand,
print the representation, repr(). Use:
35
MinimalModbus Documentation, Release 2.0.1
print(repr(bytestringname))
Registers are 16 bit wide (2 bytes), and the data is sent with the most significant byte (MSB) before the least significant
byte (LSB). This is called big-endian byte order. To find the register data value, multiply the MSB by 256 (dec) and
add the LSB.
Error checking is done using CRC (cyclic redundancy check), and the result is two bytes.
7.1.1 Example
We use this example in debug mode. It reads one register (number 5) and interpret the data as having 1 decimal. The
slave has address 1 (as set when creating the instrument instance), and we are using MODBUS function code 3
(the default value for read_register()):
>>> instrument.read_register(5,1)
In the section ‘Modbus implementation details’ above, the request message structure is described. See the table entry
for function code 3.
Interpret the request message (8 bytes) as:
Some ASCII control characters have representations like \n, and their meanings are described in this table:
It is also possible to write for example ASCII Bell (BEL, hex = 07, dec = 7) as \a, but its repr() will still print
\x07.
More about ASCII control characters is found on https://en.wikipedia.org/wiki/ASCII.
Trouble shooting
8.1 No communication
If there is no communication, make sure that the settings on your instrument are OK:
• Wiring is correct
• Communication module is set for digital communication
• Correct protocol (Modbus, and the RTU or ASCII version)
• Baud rate
• Parity
• Delay (most often not necessary)
• Address
The corresponding settings should also be used in MinimalModbus. Check also your:
• Port name
For troubleshooting, it is recommended to use interactive mode with debug enabled. See Interactive usage.
If there is no response from your instrument, you can try using a lower baud rate, or to adjust the timeout setting.
See also the pySerial pages: https://pyserial.readthedocs.io
To make sure you are sending something valid, start with the examples in the users manual of your instrument. Use
MinimalModbus in debug mode and make sure that each sent byte is correct.
The terminiation resistors of the RS-485 bus must be set correctly. Use a multimeter to verify that there is termination
in the appropriate nodes of your RS-485 bus.
To troubleshoot the communication in more detail, an oscilloscope can be very useful to verify transmitted data.
39
MinimalModbus Documentation, Release 2.0.1
Local echo of the USB-to-RS485 adaptor can also be the cause of some problems, and give rise to strange error
messages (like “CRC error” or “wrong number of bytes error” etc). Switch on the debug mode to see the request and
response messages. If the full request message can be found as the first part of the response, then local echo is likely
the cause.
Make a test to remove the adaptor from the instrument (but still connected to the computer), and see if you still have a
response.
Most adaptors have switches to select echo ON/OFF. Turning off the local echo can be done in a number of ways:
• A DIP-switch inside the plastic cover.
• A jumper inside the plastic cover.
• Shorting two of the pins in the 9-pole D-SUB connector turns off the echo for some models.
• If based on a FTDI chip, some special program can be used to change a chip setting for disabling echo.
To handle local echo, see minimalmodbus.Instrument.
8.3 Empty bytes added in the beginning or the end on the received
message
This is due to interference. Use biasing of modbus lines, by connecting resistors to GND and Vcc from the the two
lines. This is sometimes named “failsafe”.
There have been reports on problems with serial adaptors on some platforms, for example Raspberry Pi. It seems to
lack kernel drives for some chips, like PL2303. Serial adaptors based on FTDI FT232RL are known to work.
Make sure to run the dmesg command before and after plugging in your serial adaptor, to verify that the proper kernel
driver is loaded.
Since MinimalModbus version 0.5, the handling of several instruments on the same serial port has been improved for
Windows.
8.7 Support
Ask a question on https://stackoverflow.com/. Use the tags “modbus”, “python” and “minimalmodbus”.
Describe the problem in detail, and include any error messsages.
Note that it can be very helpful to switch on the debug mode, where the communication details are printed. See Debug
mode.
Please also include the output after running:
Describe which instrument model you are using, and possibly a link to online PDF documentation for it.
8.7. Support 41
MinimalModbus Documentation, Release 2.0.1
To use interactive mode, start the Python interpreter and import minimalmodbus:
>>> import minimalmodbus
>>> instr = minimalmodbus.Instrument('/dev/ttyUSB0', 1)
>>> instr
minimalmodbus.Instrument<id=0xb7437b2c, address=1, close_port_after_each_call=False,
˓→debug=False, serial=Serial<id=0xb7437b6c, open=True>(port='/dev/ttyUSB0',
˓→rtscts=False, dsrdtr=False)>
>>> instr.read_register(24, 1)
5.0
>>> instr.write_register(24, 450, 1)
>>> instr.read_register(24, 1)
450.0
Note that when you call a function, in interactive mode the representation of the return value is printed. The repre-
sentation is kind of a debug information, like seen here for the returned string (example from Omega CN7500 driver,
which previously was included in this package):
>>> instrument.get_all_pattern_variables(0)
'SP0: 10.0 Time0: 10\nSP1: 20.0 Time1: 20\nSP2: 30.0 Time2: 30\nSP3: 333.3 Time3:
˓→45\nSP4: 50.0 Time4: 50\nSP5: 60.0 Time5: 60\nSP6: 70.0 Time6: 70\nSP7: 80.0
˓→Time7: 80\nActual step: 7\nAdditional cycles: 4\nLinked pattern: 1\n'
43
MinimalModbus Documentation, Release 2.0.1
It is possible to show the representation also when printing, if you use the function repr():
>>> print(repr(instrument.get_all_pattern_variables(0)))
'SP0: 10.0 Time0: 10\nSP1: 20.0 Time1: 20\nSP2: 30.0 Time2: 30\nSP3: 333.3 Time3:
˓→45\nSP4: 50.0 Time4: 50\nSP5: 60.0 Time5: 60\nSP6: 70.0 Time6: 70\nSP7: 80.0
˓→Time7: 80\nActual step: 7\nAdditional cycles: 4\nLinked pattern: 1\n'
In case of problems using MinimalModbus, it is useful to switch on the debug mode to see the communication details:
With proper instrument drivers you can use commands like getTemperatureCenter() in your code instead of
read_register(289, 1). So the driver is a basically a collection of numerical constants to make your code
more readable.
This segment is part of the example driver eurotherm3500 which previously was included in this distribution:
import minimalmodbus
Args:
* portname (str): port name
* slaveaddress (int): slave address in the range 1 to 247
"""
def get_pv_loop1(self):
"""Return the process value (PV) for loop1."""
return self.read_register(289, 1)
def is_manual_loop1(self):
"""Return True if loop1 is in manual mode."""
(continues on next page)
def get_sptarget_loop1(self):
"""Return the setpoint (SP) target for loop1."""
return self.read_register(2, 1)
def get_sp_loop1(self):
"""Return the (working) setpoint (SP) for loop1."""
return self.read_register(5, 1)
Args:
value (float): Setpoint (most often in degrees)
"""
self.write_register(24, value, 1)
def disable_sprate_loop1(self):
"""Disable the setpoint (SP) change rate for loop1. """
VALUE = 1
self.write_register(78, VALUE, 0)
#!/usr/bin/env python3
import eurotherm3500
Note that I have one additional driver layer on top of eurotherm3500 (which is one layer on top of minimalmodbus).
I use this process controller to run a heater, so I have a driver heater.py in which all my settings are done.
The idea is that minimalmodbus should be useful to most Modbus users, and eurotherm3500 should be useful to
most users of that controller type. So my heater.py driver has functions like getTemperatureCenter() and
getTemperatureEdge(), and there I also define resistance values etc.
Here is a part of heater.py:
"""Driver for the heater in the CVD system. Talks to the heater controller and the
˓→heater policeman.
"""
class heater():
"""Class for the heater in the CVD system. Talks to the heater controller and the
˓→heater policeman.
"""
ADDRESS_HEATERCONTROLLER = 1
"""Modbus address for the heater controller."""
ADDRESS_POLICEMAN = 2
"""Modbus address for the heater over-temperature protection unit."""
SUPPLY_VOLTAGE = 230
"""Supply voltage (V)."""
def getTemperatureCenter(self):
"""Return the temperature (in deg C)."""
return self.heatercontroller.get_pv_loop1()
def getTemperatureEdge(self):
"""Return the temperature (in deg C) for the edge heater zone."""
return self.heatercontroller.get_pv_loop2()
def getTemperaturePolice(self):
"""Return the temperature (in deg C) for the overtemperature protection
˓→sensor."""
return self.policeman.get_pv()
def getOutputCenter(self):
"""Return the output (in %) for the heater center zone."""
return self.heatercontroller.get_op_loop1()
It is very useful to make a graphical user interface (GUI) for your control/measurement program.
One library for making GUIs is wxPython, found on https://www.wxpython.org/. One good tutorial (it starts from the
basics) is: https://zetcode.com/wxpython/
I strongly suggest that your measurement program should be possible to run without any GUI, as it then is
much easier to actually get the GUI version of it to work. Your program should have some function like
setTemperature(255).
The role of the GUI is this: If you have a temperature text box where a user has entered 255 (possibly degrees C), and
a button ‘Run!’ or ‘Go!’ or something similar, then the GUI program should read 255 from the box when the user
presses the button, and call the function setTemperature(255).
This way it is easy to test the measurement program and the GUI separately.
Some users have reported errors due to instruments not fulfilling the Modbus standard. For example can some addi-
tional byte be pasted at the end of the response from the instrument. Here is an example how this can be handled by
tweaking the minimalmodbus.py file.
Add this to _extract_payload() function, after the argument validity testing section:
# Fix for broken T3-PT10 which outputs extra 0xFE byte after some messages
# Patch by Edwin van den Oetelaar
# check length of message when functioncode in 3,4
# if received buffer length longer than expected, truncate it,
# this makes sure CRC bytes are taken from right place, not the end of the buffer, it
˓→ignores the extra bytes in the buffer
except IndexError:
pass
9.5.1 Uninstall
Use:
pip3 freeze
import minimalmodbus
print(minimalmodbus._get_diagnostic_string())
/usr/local/lib/python2.6/dist-packages
/Library/Python/2.6/site-packages/minimalmodbus.py
Note that .pyc is a byte compiled version. Make the changes in the .py file, and delete the .pyc file (When
available, .pyc files are used instead of .py files). You might need root privileges to edit the file in this location.
Otherwise it is better to uninstall it, put it instead in your home folder and add it to sys.path
On Windows machines, for example:
C:\python27\Lib\site-packages
The Windows installer also creates a .pyo file (and also the .pyc file).
/usr/lib/python2.7/
/usr/lib/python2.7/dist-packages
To find locations:
~$ which python
/usr/bin/python
~$ which python3
/usr/bin/python3
~$ which python2.7
/usr/bin/python2.7
~$ which python3.2
/usr/bin/python3.2
python3 --version
echo $PYTHONPATH
export PYTHONPATH='/home/jonas/pythonprogrammering/minimalmodbus/trunk'
or:
export PYTHONPATH=$PYTHONPATH:/home/jonas/pythonprogrammering/minimalmodbus/trunk
It is easy to include MinimalModbus in a Yocto build, which is using Bitbake. Yocto is a collaboration with the Open
Embedded initiative.
SUMMARY = "Easy-to-use Modbus RTU and Modbus ASCII implementation for Python"
SECTION = "devel/python"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://LICENCE.txt;md5=27da4ba4e954f7f4ba8d1e08a2c756c4"
DEPENDS = "python"
RDEPENDS_${PN} = "python-pyserial"
PR = "r0"
SRC_URI = "${SOURCEFORGE_MIRROR}/project/minimalmodbus/${PV}/MinimalModbus-${PV}.tar.
˓→gz"
SRC_URI[md5sum] = "1b2ec44e9537e14dcb8a238ea3eda451"
SRC_URI[sha256sum] = "d9acf6457bc26d3c784caa5d7589303afe95e980ceff860ec2a4051038bc261e
˓→"
S = "${WORKDIR}/MinimalModbus-${PV}"
inherit distutils
When using the recipe for another version of MinimalModbus, change the version number in the filename. Bitbake
will complain that the md5sum and sha256sum not are correct, but Bitbake will print out the correct values so you can
change the recipe accordingly.
Developer documentation
The details printed in debug mode (requests and responses) are very useful for using the included dummy_serial port
for unit testing purposes. For examples, see the file test/test_minimalmodbus.py.
My take on the design is that is should be as simple as possible, hence the name MinimalModbus, but it should
implement the smallest number of functions needed for it to be useful. The target audience for this driver simply
wants to talk to Modbus clients using a serial interface using some simple driver.
Only a few functions are implemented. It is very easy to implement lots of (seldom used) functions, resulting in
buggy code with large fractions of it almost never used. It is instead much better to implement the features when
needed/requested. There are many Modbus function codes, but I guess that most are not used.
There should be unittests for all functions, and mock communication data.
Errors should be caught as early as possible, and the error messages should be informative. For this reason there is
type checking for for the parameters in most functions. This is rather un-pythonic, but is intended to give more clear
error messages (for easier remote support).
Note that the term ‘address’ is ambiguous, why it is better to use the terms ‘register address’ or ‘slave address’.
Use only external links in the README.rst, otherwise they will not work on Python Package Index (PyPI). No
Sphinx-specific constructs are allowed in that file.
Design priorities:
• Easy to use
• Catch errors early
• Informative error messages
• Good unittest coverage
51
MinimalModbus Documentation, Release 2.0.1
Function Description
read_register() One of the facades for _generic_command().
_generic_command() Generates payload, then calls _perform_command().
_perform_command() Embeds payload into error-checking codes etc, then calls _communicate().
_communicate() Handles raw bytes for communication via pySerial.
Most of the logic is located in separate (easy to test) functions on module level. For a description of them, see Internal
documentation for MinimalModbus.
For compability with Python 2, the data is stored internally as strings. As this module has dropped support for Python
2, it will be converted gradually to use bytes in all internal data storage instead.
The Python module struct is used for conversion. See https://docs.python.org/3/library/struct.html
Several wrapper functions are defined for easy use of the conversion. These functions also do argument validity
checking.
Note that the struct module produces byte buffers for Python3, but bytestrings for Python2. This is compensated
for automatically by using the wrapper functions _pack() and _unpack().
For a description of them, see Internal documentation for MinimalModbus.
make test
The unittests uses previosly recorded communication data for the testing.
A dummy/mock/stub for the serial port, dummy_serial, is provided for test purposes. See Documentation for
dummy_serial (which is a serial port mock).
The test coverage analysis is found at https://codecov.io/github/pyhys/minimalmodbus?branch=master.
Hardware tests are performed using a Delta DTB4824 process controller together with a USB-to-RS485 converter.
See Internal documentation for hardware testing of MinimalModbus using DTB4824 for more information.
Run it with:
python3 tests/test_deltaDTB4824.py
The baudrate, portname and mode can optionally be set from command line:
python3 tests/test_deltaDTB4824.py -b19200 -D/dev/ttyUSB0 -ascii
For more details on testing with this hardware, see Internal documentation for hardware testing of MinimalModbus
using DTB4824.
10.5 Making sure that error messages are informative for the user
To have a look on the error messages raised during unit testing of minimalmodbus, monkey-patch
test_minimalmodbus.SHOW_ERROR_MESSAGES_FOR_ASSERTRAISES as seen here:
>>> import unittest
>>> import test_minimalmodbus
>>> test_minimalmodbus.SHOW_ERROR_MESSAGES_FOR_ASSERTRAISES = True
>>> suite = unittest.TestLoader().loadTestsFromModule(test_minimalmodbus)
>>> unittest.TextTestRunner(verbosity=2).run(suite)
10.5. Making sure that error messages are informative for the user 53
MinimalModbus Documentation, Release 2.0.1
suite = unittest.TestLoader().loadTestsFromTestCase(test_minimalmodbus.TestSetBitOn)
If necessary:
reload(test_minimalmodbus.minimalmodbus)
With the known data output from an instrument, we can finetune the inner details of the driver (code refactoring)
without worrying that we change the output from the code. This data will be the ‘golden standard’ to which we test
the code. Use as many as possible of the commands, and paste all the output in a text document. From this it is pretty
easy to reshuffle it into unittest code.
Here is an example how to record communication data, which then is pasted into the test code (for use with a
mock/dummy serial port). See for example Internal documentation for unit testing of MinimalModbus (click ‘[source]’
on right side, see RESPONSES at end of the page). Do like this:
This is also very useful for debugging drivers built on top of MinimalModbus.
A dummy serial port is included for testing purposes, see dummy_serial. Use it like this:
>>> import dummy_serial
>>> import test_minimalmodbus
>>> dummy_serial.RESPONSES = test_minimalmodbus.RESPONSES # Load previously recorded
˓→responses
>>> instrument.read_register(4097, 1)
823.6
In the example above there is recorded data available for read_register(4097, 1). If no recorded data is
available, an error message is displayed:
>>> instrument.read_register(4098, 1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/jonas/pythonprogrammering/minimalmodbus/trunk/minimalmodbus.py", line
˓→174, in read_register
response = self._communicate(message)
File "/home/jonas/pythonprogrammering/minimalmodbus/trunk/minimalmodbus.py", line
˓→395, in _communicate
The dummy serial port can be used also with instrument drivers built on top of MinimalModbus:
>>> import dummy_serial
>>> import test_omegacn7500
>>> dummy_serial.RESPONSES = test_omegacn7500.RESPONSES # Load previously recorded
˓→responses
>>> instrument.get_pv()
24.6
To see the generated request data (without bothering about the response):
>>> import dummy_serial
>>> import minimalmodbus
>>> minimalmodbus.serial.Serial = dummy_serial.Serial # Monkey-patch a dummy serial
˓→port
The string type has changed in Python3 compared to Python2. In Python3 the type bytes is used when communicating
via pySerial.
Dependent on the Python version number, the data sent from MinimalModbus to pySerial has different types.
This is a bytes constant in Python3, but a string constant in Python2 (allowed for 2.6 and higher):
by = b'abc\x69\xe6\x03'
Ideally, we would like to use the same source code for Python2 and Python3. In Python 2.6 and higher there is the
bytes() function for forward compatibility, but it is merely a synonym for str().
To convert from ‘bytes’(string) to string:
str(by) # not possible to give encoding
by.decode('latin1') # Gives unicode
It is thus not possible to use exactly the same code for both Python2 and Python3. Where it is unavoidable, use:
if sys.version_info[0] > 2:
whatever
It is straight-forward to extend MinimalModbus to handle more Modbus function codes. Use the method
_perform_command() to send data to the slave, and to receive the response. Note that the API might change,
as this is outside the official API.
This is easily tested in interactive mode. For example the method read_register() generates payload, which
internally is sent to the instrument using _perform_command():
It is possible to use _perform_command() directly. You can use any Modbus function code (1-127), but you need
to generate the payload yourself. Note that the same data is sent:
Use this if you are to implement other Modbus function codes, as it takes care of CRC generation etc.
There are several useful (module level) helper functions available in the minimalmodbus module. The module
level helper functions can be used without any hardware connected. See Internal documentation for MinimalModbus.
These can be handy when developing your own Modbus instrument hardware.
For example:
>>> minimalmodbus._calculate_crc_string('\x01\x03\x00\x05\x00\x01')
'\x94\x0b'
And to embed the payload '\x10\x11\x12' to slave address 1, with functioncode 16:
>>> minimalmodbus._calculate_minimum_silent_period(19200)
0.0020052083333333332
Note that the API might change, as this is outside the official API.
make docs
Do linkchecking:
make linkcheck
10.12 Webpage
10.13 Codecov.io
make install
To uninstall it:
make uninstall
10.14.2 How to generate a source distribution from the present development code
This will create a subfolder dist with the source in wheel format and in .tar.gz format:
make dist
make black
make lint
Check typing:
make mypy
10.15.3 Unittesting
make test
make coverage
Also make tests using Delta DTB4824 hardware. See Internal documentation for hardware testing of MinimalModbus
using DTB4824.
Test the source distribution generation (look in the PKG-INFO file):
make dist
Also make sure that these are functional (see sections below):
• Documentation generation
• Test coverage report generation
10.15.4 Git
Merge to the master branch locally. Make a tag in the git repository. Push the master branch (including tags) to Github.
If you push to another branch, a pull request will be generated.
See below for details.
10.15.5 GitHub
Test links on the PyPI page. If adjustments are required on the PyPI page, log in and manually adjust the text. This
might be for example parsing problems with the ReST text (allows no Sphinx-specific constructs).
Log in to https://readthedocs.org (using Github credentials) and force rebuild on the master branch.
Enable the “master” and “stable” documentation versions. In the advanced settings select Python3, and enter the name
of the dependency file (a requirements.txt file must be available in the repo).
Make sure that the installer works, and the dependencies are handled correctly. Try at least Linux and Windows.
On windows you might need to use:
py -m pip install minimalmodbus
Test the package on hardware from Linux and Windows. Download the file test_deltaDTB4824.py.
To run the hardware test on Windows:
C:\Python27>python.exe C:\Users\jonas\Documents\Pythonprogram\testmodbus\test_
˓→deltaDTB4824.py -DCOM7 -b2400 -ascii
Check in a new version on GitHub master branch. If the previous release was X.Y.Z, then use X.Y.(Z+1)a1.
10.15.12 Backup
Show details:
git remote -v
git status
git branch
Stage changes:
Commit locally:
List branches:
git branch
Change branch:
git tag
sphinx-build --version
Note that only the functions and methods that are listed in the index will show as links.
Headings
• Top level heading underlining symbol: = (equals)
• Next lower level: - (minus)
• A third level if necessary (avoid this): ` (backquote)
Internal links
• Add an internal marker .. _my-reference-label: before a heading.
make docs
10.19 TODO
10.19. TODO 65
MinimalModbus Documentation, Release 2.0.1
Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given.
Note that MinimalModbus is released very infrequently, but your issues are not forgotten. Do not use GitHub issues
for problems getting the Modbus communication to your instrument to work. For that Stack Overflow is much better,
see Support.
You can contribute in many ways:
It is greatly appreciated if you can help other users to get their Modbus equipment up and running. Please subscribe
(“watch”) the tags “modbus” and “minimalmodbus” on Stack Overflow.
Here are the newest minimalmodbus questions on Stack Overflow: https://stackoverflow.com/questions/tagged/
minimalmodbus?tab=Newest
67
MinimalModbus Documentation, Release 2.0.1
Look through the GitHub issues for bugs. Anything tagged with “bug” is open to whoever wants to implement it.
Look through the GitHub issues for features. Anything tagged with “enhancement” is open to whoever wants to
implement it.
MinimalModbus could always use more documentation, whether as part of the official MinimalModbus docs, in
docstrings, or even on the web in blog posts, articles, and such.
3. Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed, this is how you set up
your fork for local development:
$ mkvirtualenv minimalmodbus
$ cd minimalmodbus/
$ python setup.py develop
$ git add .
$ git commit -m "Your detailed description of your changes."
$ git push origin name-of-your-bugfix-or-feature
Before you submit a pull request, check that it meets these guidelines:
1. The pull request should include tests.
2. If the pull request adds functionality, the docs should be updated.
3. The pull request should work for currently supported Pyhton versions. Check Github Actions to make sure that
the tests pass for all supported Python versions.
Credits
12.2 Contributors
71
MinimalModbus Documentation, Release 2.0.1
• Matthias Bolte
• Michael Penza
• Peter
• Russ Garrett
• Yurij Z (Github user: zyura)
Related software
The MinimalModbus package is intended for easy-to-use communication with instruments using the Modbus (RTU
and ASCII) protocol. There are a few other Python packages for Modbus protocol implementation. For more advanced
use, you should consider using one of these:
pyModbus From https://github.com/riptideio/pymodbus: ‘Pymodbus is a full Modbus protocol implementation using
twisted for its asynchronous communications core.’
modbus-tk From https://github.com/ljean/modbus-tk: ‘Make possible to write modbus TCP and RTU master and
slave mainly for testing purpose. It is shipped with slave simulator and a master with a web-based hmi. It is a
full-stack implementation and as a consequence could also be used on real-world project.’
umodbus From https://github.com/AdvancedClimateSystems/umodbus/: ‘uModbus or (𝜇Modbus) is a pure Python
implementation of the Modbus protocol as described in the MODBUS Application Protocol Specification
V1.1b3. uModbus implements both a Modbus client (both TCP and RTU) and a Modbus server (both TCP
and RTU).’
EasyModbusTCP/UDP/RTU Python From https://sourceforge.net/projects/easymodbustcp-udp-rtu-python/:
‘EasyModbusTCP library is available for .NET / Java / and Python. Same Handling for different implementa-
tions and different plattforms.’
pyModbusTCP From https://github.com/sourceperl/pyModbusTCP: ‘A simple Modbus/TCP library for Python’
pylibmodbus From https://github.com/stephane/pylibmodbus: ‘Python Interface for libmodbus written with CFFI
(Python 2 and Python 3) ‘
73
MinimalModbus Documentation, Release 2.0.1
History
• Improved documentation
• Finetuned Github Actions workflow
New features:
• Type hints available
• Support for broadcast (slave address 0), by Jan Breuer.
• Measurement of round-trip time
Breaking changes:
• Dropping support for Python 2
Other fixes:
• Starting to convert internal data representation as bytes (it had to be strings when supporting Python 2)
• Converted from setup.py to setup.cfg
• Use Github Actions instead of Travis CI
75
MinimalModbus Documentation, Release 2.0.1
New features:
• Implements reading and writing multiple bits simultaneously.
• Support more byteorders (endianness) for floats and long integers.
Breaking changes:
• Renamed method arguments ‘numberOfDecimals’, ‘numberOfRegisters’ to ‘number_of_decimals’, ‘num-
ber_of_registers’
• Removed example drivers for Eurotherm 3500 and Omegacn 7500, as I no longer have access to these instru-
ments for testing. It would great if someone would pick up support for these instruments in a separate project.
• Requires pyserial 3.0 or later.
• Removed module level constants for default values, as they were confusingly named.
Other fixes:
• Allow slave addresses also in the reserved range (up to 255). Reported by GitHub user gnbl.
• Serial port read and write buffers are cleared before each request to the instrument. Pull request from GitHub
user mrrs6.
• Check whether the serial port is open before trying to open it. Reported by Matthias Bolte.
• Custom exceptions for Modbus errors, by Russ Garrett.
• Silent period between messages is at least 1.75 ms to fulfill Modbus standard. Reported by GitHub user draput.
• Use time.monotonic if available. Suggested by Matthias Bolte.
• Implemented write timeout, to avoid hanging when writing. Instead it will raise an exception. Reported by
Austin Stover.
• Better checking of number of registers when reading and writing.
• Rename internal methods and variables to be PEP8 compliant.
• Improved documentation.
Internal documentation
79
MinimalModbus Documentation, Release 2.0.1
MinimalModbus: A Python driver for Modbus RTU/ASCII via serial port (via USB, RS485 or RS232).
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
An enumeration.
BIT = 1
BITS = 2
FLOAT = 3
LONG = 4
REGISTER = 5
REGISTERS = 6
STRING = 7
__module__ = 'minimalmodbus'
class minimalmodbus.Instrument(port: str, slaveaddress: int, mode: str = ’rtu’,
close_port_after_each_call: bool = False, debug: bool =
False)
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).
• slaveaddress: Slave address in the range 0 to 247 (use decimal numbers, not hex). 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: str, slaveaddress: int, mode: str = ’rtu’, close_port_after_each_call: bool = False,
debug: bool = False) → None
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 infoma-
tion (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 immea-
diately 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 for documentation.
– Defaults to serial.PARITY_NONE.
• bytesize (int): Bytesize in bits.
– Defaults to 8.
• stopbits (use STOPBITS_xxx constants): The number of stopbits. See pySerial docs.
– Defaults to serial.STOPBITS_ONE.
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
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 (use decimal numbers, not hex).
• 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]
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 (use decimal numbers, not hex).
• 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).
• registeraddress: The slave register address (use decimal numbers, not hex).
• 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) → int
Read a long integer (32 bits) from the slave.
Long integers (32 bits = 4 bytes) are stored in two consecutive 16-bit registers in the slave.
Args:
• registeraddress: The slave register start address (use decimal numbers, not hex).
• 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.
• registeraddress: The slave register start address (use decimal numbers, not hex).
• 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.
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
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 (use decimal numbers, not hex).
• 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
• 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
Note: The parameter number_of_registers was named numberOfRegisters before MinimalModbus 1.0
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]
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 (use decimal numbers, not hex).
• 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
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 (use decimal numbers, not hex).
• 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, payload-
format: minimalmodbus._Payloadformat = <_Payloadformat.REGISTER: 5>)
→ Any
Perform generic command for reading and writing registers and bits.
Args:
• functioncode: Modbus function code.
• registeraddress: The register address (use decimal numbers, not hex).
• 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 func-
tionality 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: str) → str
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
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:
| | |
| |<------- 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 https://stackoverflow.com/questions/157359/accurate-timestamping-in-python-logging
__dict__ = mappingproxy({'__module__': 'minimalmodbus', '__doc__': 'Instrument class
__module__ = 'minimalmodbus'
__weakref__
list of weak references to the object (if defined)
exception minimalmodbus.ModbusException
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
Base class for exceptions that the slave (instrument) reports.
__module__ = 'minimalmodbus'
exception minimalmodbus.SlaveDeviceBusyError
The slave is busy processing some command.
__module__ = 'minimalmodbus'
exception minimalmodbus.NegativeAcknowledgeError
The slave can not fulfil the programming request.
This typically happens when using function code 13 or 14 decimal.
__module__ = 'minimalmodbus'
exception minimalmodbus.IllegalRequestError
The slave has received an illegal request.
__module__ = 'minimalmodbus'
exception minimalmodbus.MasterReportedException
Base class for exceptions that the master (computer) detects.
__module__ = 'minimalmodbus'
exception minimalmodbus.NoResponseError
No response from the slave.
__module__ = 'minimalmodbus'
exception minimalmodbus.LocalEchoError
There is some problem with the local echo.
__module__ = 'minimalmodbus'
exception minimalmodbus.InvalidResponseError
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, payloadfor-
mat: minimalmodbus._Payloadformat) → str
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: str, functioncode: int, registeraddress: int, value:
Any, number_of_decimals: int, number_of_registers: int, num-
ber_of_bits: int, signed: bool, byteorder: int, payloadformat:
minimalmodbus._Payloadformat) → Union[None, str, int, float,
List[int], List[float]]
minimalmodbus._embed_payload(slaveaddress: int, mode: str, functioncode: int, payloaddata: str)
→ str
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 byte string 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 (which is two bytes).
• ASCII Mode: header (:) + slaveaddress (2 characters) + functioncode (2 characters) + payloaddata +
LRC (which is two characters) + footer (CRLF)
The LRC or CRC is calculated from the byte string made up of slaveaddress + functioncode + payloaddata. The
header, LRC/CRC, and footer are excluded from the calculation.
minimalmodbus._extract_payload(response: str, slaveaddress: int, mode: str, functioncode: int)
→ str
Extract the payload data part from the slave’s response.
Args:
• response: The raw response byte string 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 (which is two bytes)
• ASCII Mode: header (:) + slaveaddress byte + functioncode byte + payloaddata + LRC (which is two
characters) + footer (CRLF)
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: str) →
int
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 string)
Returns: The predicted number of bytes in the response.
Raises: ValueError, TypeError.
minimalmodbus._calculate_minimum_silent_period(baudrate: Union[int, float]) → float
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_onebyte_string(inputvalue: int) → str
Convert a numerical value to a one-byte string.
Args: inputvalue: The value to be converted. Should be >=0 and <=255.
Returns: A one-byte string created by chr(inputvalue).
Raises: TypeError, ValueError
minimalmodbus._num_to_twobyte_string(value: Union[int, float], number_of_decimals: int = 0,
lsb_first: bool = False, signed: bool = False) → str
Convert a numerical value to a two-byte string, 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: A two-byte string.
Raises: TypeError, ValueError. Gives DeprecationWarning instead of ValueError for some values in Python
2.6.
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 bytestring 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:
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 string is \x03\x02, which has the length 2.
minimalmodbus._twobyte_string_to_num(bytestring: str, number_of_decimals: int = 0, signed:
bool = False) → Union[int, float]
Convert a two-byte string to a numerical value, possibly scaling it.
Args:
• bytestring: A string 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 bytestring.
Raises: TypeError, ValueError
Use the parameter signed=True if converting a bytestring 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: A string \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_bytestring(value: int, signed: bool = False, number_of_registers: int =
2, byteorder: int = 0) → str
Convert a long integer to a bytestring.
Long integers (32 bits = 4 bytes) are stored in two consecutive 16-bit registers in the slave.
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. For error checking only.
• byteorder: How multi-register data should be interpreted.
Returns: A bytestring (4 bytes).
Raises: TypeError, ValueError
A floating point value of 1.0 is encoded (in single precision) as 3f800000 (hex). This will give a byte string
'\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: A bytestring (4 or 8 bytes).
Raises: TypeError, ValueError
minimalmodbus._bytestring_to_float(bytestring: str, number_of_registers: int = 2, byteorder:
int = 0) → float
Convert a four-byte string 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_bytestring().
Args:
• bytestring: A string of length 4 or 8.
• number_of_registers: Can be 2 or 4.
• byteorder: How multi-register data should be interpreted.
Returns: A float.
Raises: TypeError, ValueError
Args:
• hexstring: Can be for example ‘A3’ or ‘A3B4’. Must be of even length.
• Allowed characters are ‘0’ to ‘9’, ‘a’ to ‘f’ and ‘A’ to ‘F’ (not space).
Returns: A string of half the length, with characters corresponding to all 0-255 values for each byte.
Raises: TypeError, ValueError
minimalmodbus._describe_bytes(inputbytes: bytes) → str
Describe bytes in a human friendly way.
Args:
• inputbytes: Bytes to describe
Returns a space separated descriptive string. For example b’x01x02x03’ gives: 01 02 03 (3 bytes)
minimalmodbus._calculate_number_of_bytes_for_bits(number_of_bits: int) → int
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.
Algorithm from MODBUS APPLICATION PROTOCOL SPECIFICATION V1.1b
minimalmodbus._bit_to_bytestring(value: int) → str
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 (string).
Raises: TypeError, ValueError
minimalmodbus._bits_to_bytestring(valuelist: List[int]) → str
Build a bytestring from a list of bits.
This is used for functioncode 15.
Args:
• valuelist: List of int (0 or 1)
Returns a bytestring.
minimalmodbus._bytestring_to_bits(bytestring: str, number_of_bits: int) → List[int]
Parse bits from a bytestring.
This is used for parsing the bits in response messages for functioncode 1 and 2.
The first byte in the bytestring 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 bytestring contains data on next 8 bits. Might be padded with zeros toward MSB.
Args:
• bytestring: Input string
x returns
0 0
1 1
127 127
-128 128
-127 129
-1 255
x returns
0 0
1 1
127 127
128 -128
129 -127
255 -1
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
Simulated response error Tested using function Tested using Modbus function code
No response read_bit 2
Wrong CRC in response write_register 16
Wrong slave address in response write_register 16
Wrong function code in response write_register 16
Slave indicates an error write_register 16
Wrong byte count in response read_bit 2
Wrong register address in response write_register 16
Wrong number of registers in response write_bit 15
Wrong number of registers in response write_register 16
Wrong write data in response write_bit 5
Wrong write data in response write_register 6
test_minimalmodbus.VERBOSITY = 0
Verbosity level for the unit testing. Use value 0 or 2. Note that it only has an effect for Python 2.7 and above.
test_minimalmodbus.SHOW_ERROR_MESSAGES_FOR_ASSERTRAISES = False
Set this to True for printing the error messages caught by assertRaises().
If set to True, any unintentional error messages raised during the processing of the command in
assertRaises() are also caught (not counted). It will be printed in the short form, and will show no
traceback. It can also be useful to set VERBOSITY = 2.
exception test_minimalmodbus._NonexistantError
class test_minimalmodbus.ExtendedTestCase(methodName=’runTest’)
Overriding the assertRaises() method to be able to print the error message.
Use test_minimalmodbus.SHOW_ERROR_MESSAGES_FOR_ASSERTRAISES = True in order to use
this option. It can also be useful to set test_minimalmodbus.VERBOSITY = 2.
Based on https://stackoverflow.com/questions/8672754/how-to-show-the-error-messages-caught-by-assertraises-in-unittest-in-py
testKnownValues() → None
testWrongValues() → None
class test_minimalmodbus.TestParsePayload(methodName=’runTest’)
testKnownValues() → None
testInvalidPayloads() → None
class test_minimalmodbus.TestEmbedPayload(methodName=’runTest’)
knownValues = [(2, 2, 'rtu', '123', '\x02\x02123XÂ'), (1, 16, 'rtu', 'ABC', '\x01\x10AB
testKnownValues() → None
testWrongInputValue() → None
testWrongInputType() → None
class test_minimalmodbus.TestExtractPayload(methodName=’runTest’)
knownValues = [(2, 2, 'rtu', '123', '\x02\x02123XÂ'), (1, 16, 'rtu', 'ABC', '\x01\x10AB
testKnownValues() → None
testWrongInputValue() → None
testWrongInputType() → None
class test_minimalmodbus.TestSanityEmbedExtractPayload(methodName=’runTest’)
knownValues = [(2, 2, 'rtu', '123', '\x02\x02123XÂ'), (1, 16, 'rtu', 'ABC', '\x01\x10AB
testKnownValues() → None
testRange() → None
class test_minimalmodbus.TestPredictResponseSize(methodName=’runTest’)
knownValues = [(2400, 0.016), (2400.0, 0.016), (4800, 0.008), (9600, 0.004), (19200, 0.
testKnownValues() → None
testWrongInputValue() → None
testWrongInputType() → None
class test_minimalmodbus.TestNumToOneByteString(methodName=’runTest’)
knownValues = [('\x00', 1, [0]), ('\x01', 1, [1]), ('\x02', 2, [0, 1]), ('\x04', 3, [0,
testKnownValues() → None
testWrongValues() → None
class test_minimalmodbus.TestBitsToBytestring(methodName=’runTest’)
knownValues = [('\x00', 1, [0]), ('\x01', 1, [1]), ('\x02', 2, [0, 1]), ('\x04', 3, [0,
testKnownValues() → None
testWrongValues() → None
class test_minimalmodbus.TestBitToBytestring(methodName=’runTest’)
testValueNotInteger() → None
class test_minimalmodbus.TestCalculateNumberOfBytesForBits(methodName=’runTest’)
knownValues = [(0, 0), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1), (8, 1),
testKnownValues() → None
class test_minimalmodbus.TestLongToBytestring(methodName=’runTest’)
knownValues = [('A', 1, 'A '), ('AB', 1, 'AB'), ('ABC', 2, 'ABC '), ('ABCD', 2, 'ABCD')
testKnownValues() → None
testWrongInputValue() → None
testWrongInputType() → None
class test_minimalmodbus.TestBytestringToTextstring(methodName=’runTest’)
knownValues = [('A', 1, 'A '), ('AB', 1, 'AB'), ('ABC', 2, 'ABC '), ('ABCD', 2, 'ABCD')
testKnownValues() → None
testWrongInputValue() → None
testWrongInputType() → None
class test_minimalmodbus.TestSanityTextstring(methodName=’runTest’)
knownValues = [('A', 1, 'A '), ('AB', 1, 'AB'), ('ABC', 2, 'ABC '), ('ABCD', 2, 'ABCD')
testSanity() → None
class test_minimalmodbus.TestPack(methodName=’runTest’)
knownValues = [(-77, '>h', 'ÿ3 '), (-1, '>h', 'ÿÿ'), (-770, '>h', 'üþ'), (-32768, '>h',
testKnownValues() → None
testWrongInputValue() → None
testWrongInputType() → None
class test_minimalmodbus.TestUnpack(methodName=’runTest’)
knownValues = [(-77, '>h', 'ÿ3 '), (-1, '>h', 'ÿÿ'), (-770, '>h', 'üþ'), (-32768, '>h',
testKnownValues() → None
testWrongInputValue() → None
testWrongInputType() → None
class test_minimalmodbus.TestSwap(methodName=’runTest’)
knownValues = [('', ''), ('AB', 'BA'), ('ABCD', 'BADC'), ('ABCDEF', 'BADCFE'), ('ABCDEF
wrongValues = ['A', 'ABC', 'ABCDE', 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
testKnownValues() → None
testWrongValues() → None
class test_minimalmodbus.TestSanityPackUnpack(methodName=’runTest’)
knownValues = [(-77, '>h', 'ÿ3 '), (-1, '>h', 'ÿÿ'), (-770, '>h', 'üþ'), (-32768, '>h',
testSanity() → None
class test_minimalmodbus.TestHexencode(methodName=’runTest’)
knownValues = [('', False, ''), ('7', False, '37'), ('J', False, '4A'), (']', False, '5
testKnownValues() → None
testWrongInputValue() → None
testWrongInputType() → None
class test_minimalmodbus.TestHexdecode(methodName=’runTest’)
knownValues = [('', False, ''), ('7', False, '37'), ('J', False, '4A'), (']', False, '5
testKnownValues() → None
testAllowLowercase() → None
testWrongInputValue() → None
testWrongInputType() → None
class test_minimalmodbus.TestSanityHexencodeHexdecode(methodName=’runTest’)
knownValues = [('', False, ''), ('7', False, '37'), ('J', False, '4A'), (']', False, '5
testKnownValues() → None
testKnownValuesLoop() → None
Loop through all bytestrings of length two.
class test_minimalmodbus.TestDescribeBytes(methodName=’runTest’)
testKnownValues() → None
class test_minimalmodbus.TestTwosComplement(methodName=’runTest’)
knownValues = [(0, 8, 0), (1, 8, 1), (127, 8, 127), (-128, 8, 128), (-127, 8, 129), (-1
testKnownValues() → None
testOutOfRange() → None
testWrongInputType() → None
class test_minimalmodbus.TestFromTwosComplement(methodName=’runTest’)
knownValues = [(0, 8, 0), (1, 8, 1), (127, 8, 127), (-128, 8, 128), (-127, 8, 129), (-1
testKnownValues() → None
testOutOfRange() → None
testWrongInputType() → None
class test_minimalmodbus.TestSanityTwosComplement(methodName=’runTest’)
knownValues = [(0, 0, False), (0, 1, False), (0, 2, False), (0, 3, False), (0, 4, False
testKnownValues() → None
testWrongInputValue() → None
testWrongInputType() → None
class test_minimalmodbus.TestCalculateCrcString(methodName=’runTest’)
testCorrectFunctioncode() → None
testCorrectFunctioncodeNoRange() → None
testWrongFunctioncode() → None
testWrongFunctioncodeNoRange() → None
testWrongFunctioncodeType() → None
testWrongFunctioncodeListValues() → None
testWrongListType() → None
class test_minimalmodbus.TestCheckSlaveaddress(methodName=’runTest’)
testKnownValues() → None
testWrongValues() → None
testNotIntegerInput() → None
class test_minimalmodbus.TestCheckMode(methodName=’runTest’)
testKnownValues() → None
testWrongValues() → None
testNotIntegerInput() → None
class test_minimalmodbus.TestCheckRegisteraddress(methodName=’runTest’)
testKnownValues() → None
testWrongValues() → None
testWrongType() → None
class test_minimalmodbus.TestCheckResponseSlaveErrorCode(methodName=’runTest’)
testResponsesWithoutErrors() → None
testResponsesWithErrors() → None
testTooShortResponses() → None
class test_minimalmodbus.TestCheckResponseNumberOfBytes(methodName=’runTest’)
testCorrectNumberOfBytes() → None
testWrongNumberOfBytes() → None
testNotStringInput() → None
class test_minimalmodbus.TestCheckResponseRegisterAddress(methodName=’runTest’)
testCorrectResponseRegisterAddress() → None
testTooShortString() → None
testNotString() → None
testWrongResponseRegisterAddress() → None
testInvalidAddress() → None
testAddressNotInteger() → None
class test_minimalmodbus.TestCheckResponsenumber_of_registers(methodName=’runTest’)
testCorrectResponsenumber_of_registers() → None
testTooShortString() → None
testNotString() → None
testWrongResponsenumber_of_registers() → None
testInvalidResponsenumber_of_registersRange() → None
testnumber_of_registersNotInteger() → None
class test_minimalmodbus.TestCheckResponseWriteData(methodName=’runTest’)
testCorrectResponseWritedata() → None
testWrongResponseWritedata() → None
testNotString() → None
testTooShortPayload() → None
testInvalidReferenceData() → None
class test_minimalmodbus.TestCheckString(methodName=’runTest’)
testKnownValues() → None
testTooShort() → None
testTooLong() → None
testNotAscii() → None
testInconsistentLengthlimits() → None
testInputNotString() → None
testNotIntegerInput() → None
testDescriptionNotString() → None
testWrongCustomError() → None
testCustomError() → None
class test_minimalmodbus.TestCheckBytes(methodName=’runTest’)
testKnownValues() → None
testTooShort() → None
testTooLong() → None
testInconsistentLengthlimits() → None
testInputNotBytes() → None
testNotIntegerInput() → None
testDescriptionNotString() → None
class test_minimalmodbus.TestCheckInt(methodName=’runTest’)
testKnownValues() → None
testTooLargeValue() → None
testTooSmallValue() → None
testInconsistentLimits() → None
testWrongInputType() → None
class test_minimalmodbus.TestCheckNumerical(methodName=’runTest’)
testKnownValues() → None
testTooLargeValue() → None
testTooSmallValue() → None
testInconsistentLimits() → None
testNotNumericInput() → None
testDescriptionNotString() → None
class test_minimalmodbus.TestCheckBool(methodName=’runTest’)
testKnownValues() → None
testWrongType() → None
class test_minimalmodbus.TestGetDiagnosticString(methodName=’runTest’)
testReturnsString() → None
class test_minimalmodbus.TestPrintOut(methodName=’runTest’)
testKnownValues() → None
testInputNotString() → None
class test_minimalmodbus.TestDummyCommunication(methodName=’runTest’)
setUp() → None
Hook method for setting up the test fixture before exercising it.
testReadBit() → None
testReadBitWrongValue() → None
testReadBitWrongType() → None
testReadBitWithWrongByteCountResponse() → None
testReadBitWithNoResponse() → None
testWriteBit() → None
testWriteBitWrongValue() → None
testWriteBitWrongType() → None
testWriteBitWithWrongRegisternumbersResponse() → None
testWriteBitWithWrongWritedataResponse() → None
testReadBits() → None
testReadBitsWrongValue() → None
testWriteBits() → None
testWriteBitsWrongValue() → None
testReadRegister() → None
testReadRegisterWrongValue() → None
testReadRegisterWrongType() → None
testWriteRegister() → None
testWriteRegisterWithDecimals() → None
testWriteRegisterWrongValue() → None
testWriteRegisterWrongType() → None
testWriteRegisterWithWrongCrcResponse() → None
testWriteRegisterSuppressErrorMessageAtWrongCRC() → None
testWriteRegisterWithWrongSlaveaddressResponse() → None
testWriteRegisterWithWrongFunctioncodeResponse() → None
testWriteRegisterWithWrongRegisteraddressResponse() → None
testWriteRegisterWithWrongRegisternumbersResponse() → None
testWriteRegisterWithWrongWritedataResponse() → None
testReadLong() → None
testReadLongWrongValue() → None
testReadLongWrongType() → None
testWriteLong() → None
testWriteLongWrongValue() → None
testWriteLongWrongType() → None
testReadFloat() → None
testReadFloatWrongValue() → None
testReadFloatWrongType() → None
testWriteFloat() → None
testWriteFloatWrongValue() → None
testWriteFloatWrongType() → None
testReadString() → None
testReadStringWrongValue() → None
testReadStringWrongType() → None
testWriteString() → None
testWriteStringWrongValue() → None
testWriteStringWrongType() → None
testReadRegisters() → None
testReadRegistersWrongValue() → None
testReadRegistersWrongType() → None
testWriteRegisters() → None
testWriteRegistersWrongValue() → None
testWriteRegistersWrongType() → None
testGenericCommand() → None
testGenericCommandWrongValue() → None
testGenericCommandWrongType() → None
testGenericCommandWrongValueCombinations() → None
testPerformcommandKnownResponse() → None
testPerformcommandWrongSlaveResponse() → None
testPerformcommandWrongInputValue() → None
testPerformcommandWrongInputType() → None
testCommunicateKnownResponse() → None
testCommunicateWrongType() → None
testCommunicateNoMessage() → None
testCommunicateNoResponse() → None
testCommunicateLocalEcho() → None
testCommunicateWrongLocalEcho() → None
testPortWillBeOpened() → None
testMeasureRoundtriptime() → None
testRepresentation() → None
testReadPortClosed() → None
testPortAlreadyOpen() → None
testPortAlreadyClosed() → None
tearDown() → None
Hook method for deconstructing the test fixture after testing it.
class test_minimalmodbus.TestDummyCommunicationOmegaSlave1(methodName=’runTest’)
setUp() → None
Hook method for setting up the test fixture before exercising it.
testReadBit() → None
testWriteBit() → None
testReadRegister() → None
testWriteRegister() → None
tearDown() → None
Hook method for deconstructing the test fixture after testing it.
class test_minimalmodbus.TestDummyCommunicationOmegaSlave10(methodName=’runTest’)
setUp() → None
Hook method for setting up the test fixture before exercising it.
testReadBit() → None
testWriteBit() → None
testReadRegister() → None
testWriteRegister() → None
tearDown() → None
Hook method for deconstructing the test fixture after testing it.
class test_minimalmodbus.TestDummyCommunicationDTB4824_RTU(methodName=’runTest’)
setUp() → None
Hook method for setting up the test fixture before exercising it.
testReadBit() → None
testWriteBit() → None
testReadBits() → None
testReadRegister() → None
testReadRegisters() → None
testWriteRegister() → None
tearDown() → None
Hook method for deconstructing the test fixture after testing it.
class test_minimalmodbus.TestDummyCommunicationDTB4824_ASCII(methodName=’runTest’)
setUp() → None
Hook method for setting up the test fixture before exercising it.
testReadBit() → None
testWriteBit() → None
testReadBits() → None
testReadRegister() → None
testReadRegisters() → None
testWriteRegister() → None
tearDown() → None
Hook method for deconstructing the test fixture after testing it.
class test_minimalmodbus.TestDummyCommunicationWithPortClosure(methodName=’runTest’)
setUp() → None
Hook method for setting up the test fixture before exercising it.
testReadRegisterSeveralTimes() → None
testPortAlreadyClosed() → None
tearDown() → None
Hook method for deconstructing the test fixture after testing it.
class test_minimalmodbus.TestVerboseDummyCommunicationWithPortClosure(methodName=’runTest’)
setUp() → None
Hook method for setting up the test fixture before exercising it.
testReadRegister() → None
tearDown() → None
Hook method for deconstructing the test fixture after testing it.
class test_minimalmodbus.TestDummyCommunicationBroadcast(methodName=’runTest’)
setUp() → None
Hook method for setting up the test fixture before exercising it.
testWriteRegister() → None
testReadingNotAllowed() → None
tearDown() → None
Hook method for deconstructing the test fixture after testing it.
class test_minimalmodbus.TestDummyCommunicationThreeInstrumentsPortClosure(methodName=’runTest
setUp() → None
Hook method for setting up the test fixture before exercising it.
testCommunication() → None
tearDown() → None
Hook method for deconstructing the test fixture after testing it.
class test_minimalmodbus.TestDummyCommunicationHandleLocalEcho(methodName=’runTest’)
setUp() → None
Hook method for setting up the test fixture before exercising it.
testReadRegister() → None
testReadRegisterWrongEcho() → None
tearDown() → None
Hook method for deconstructing the test fixture after testing it.
test_minimalmodbus.WRONG_ASCII_RESPONSES = {}
A dictionary of respones from a dummy instrument.
The key is the message (string) sent to the serial port, and the item is the response (string) from the dummy
serial port.
15.4.1 Usage
Arguments:
• -b : baud rate
• -D : port name
NOTE: There should be no space between the option switch and its argument.
Defaults to RTU mode.
Make sure that RUN_VERIFY_EXAMPLES and similar flags are all ‘True’.
• Run the tests under Linux and Windows
• Use 2400 bps and 38400 bps
• Use Modbus ASCII and Modbus RTU
Sequence:
• 38400 bps RTU
• 38400 bps ASCII
• 2400 bps ASCII
• 2400 bps RTU
To change the settings on the temperature controller panel, hold the SET button for more than 3 seconds. Use the ‘loop
arrow’ button for moving to next parameter. Change the value with the up and down arrows, and confirm using the
SET button. Press SET again to exit setting mode.
Use these setting values in the temperature controller:
• SP 1 (Decimal point position)
• CoSH on (ON: communication write-in enabled)
• C-SL rtu (use RTU or ASCII)
• C-no 1 (Slave number)
• BPS (see the DEFAULT_BAUDRATE setting below, or the command line argument)
• LEN 8
15.4. Internal documentation for hardware testing of MinimalModbus using DTB4824 117
MinimalModbus Documentation, Release 2.0.1
• PRTY None
• Stop 1
When running, the setpoint is seen on the rightmost part of the display.
Sometimes after changing the baud rate, there is no communication with the temperature controller. Reset the FTDI
chip by unplugging and replugging the USB-to-RS485 converter.
Use a setting of 19200 bps, RTU mode and slave addess 1 for the DTB4824. Run these commands:
import minimalmodbus
instrument = minimalmodbus.Instrument('/dev/ttyUSB0', 1, debug=True) # Adjust if
˓→necessary.
15.4. Internal documentation for hardware testing of MinimalModbus using DTB4824 119
MinimalModbus Documentation, Release 2.0.1
• genindex
• modindex
• search
121
MinimalModbus Documentation, Release 2.0.1
d
dummy_serial, 79
m
minimalmodbus, 13
t
test_deltaDTB4824, 117
test_minimalmodbus, 102
123
MinimalModbus Documentation, Release 2.0.1
Symbols F
_NonexistantError, 103 flush() (dummy_serial.Serial method), 80
_box() (in module test_deltaDTB4824), 118
H
A handle_local_echo (minimalmodbus.Instrument at-
address (minimalmodbus.Instrument attribute), 14 tribute), 14
assertAlmostEqualRatio()
(test_minimalmodbus.ExtendedTestCase I
method), 103 IllegalRequestError, 21
assertRaises() (test_minimalmodbus.ExtendedTestCase
Instrument (class in minimalmodbus), 13
method), 103 InvalidResponseError, 21
is_open (dummy_serial.Serial attribute), 80
B
BYTEORDER_BIG (in module minimalmodbus), 13 K
BYTEORDER_BIG_SWAP (in module minimalmodbus), knownValues (test_minimalmodbus.TestBitsToBytestring
13 attribute), 105
BYTEORDER_LITTLE (in module minimalmodbus), 13 knownValues (test_minimalmodbus.TestBitToBytestring
BYTEORDER_LITTLE_SWAP (in module minimalmod- attribute), 105
bus), 13 knownValues (test_minimalmodbus.TestBytestringToBits
attribute), 105
C knownValues (test_minimalmodbus.TestBytestringToFloat
clear_buffers_before_each_transaction attribute), 106
(minimalmodbus.Instrument attribute), 14 knownValues (test_minimalmodbus.TestBytestringToLong
close() (dummy_serial.Serial method), 80 attribute), 106
close_port_after_each_call (minimalmod- knownValues (test_minimalmodbus.TestBytestringToTextstring
bus.Instrument attribute), 14 attribute), 107
knownValues (test_minimalmodbus.TestBytestringToValuelist
D attribute), 107
debug (minimalmodbus.Instrument attribute), 14 knownValues (test_minimalmodbus.TestCalculateCrcString
DEFAULT_BAUDRATE (in module dummy_serial), 79 attribute), 109
DEFAULT_RESPONSE (in module dummy_serial), 79 knownValues (test_minimalmodbus.TestCalculateLrcString
DEFAULT_TIMEOUT (in module dummy_serial), 79 attribute), 109
dummy_serial (module), 79 knownValues (test_minimalmodbus.TestCalculateMinimumSilentPeriod
attribute), 104
E knownValues (test_minimalmodbus.TestCalculateNumberOfBytesForBits
environment variable attribute), 106
PYTHONPATH, 63 knownValues (test_minimalmodbus.TestCheckBit at-
ExtendedTestCase (class in test_minimalmodbus), tribute), 109
103
125
MinimalModbus Documentation, Release 2.0.1
knownValues (test_minimalmodbus.TestEmbedPayload L
attribute), 104 LocalEchoError, 21
knownValues (test_minimalmodbus.TestExtractPayload
attribute), 104 M
knownValues (test_minimalmodbus.TestFloatToBytestringmain() (in module test_deltaDTB4824), 119
attribute), 106 MasterReportedException, 21
knownValues (test_minimalmodbus.TestFromTwosComplement
measure_roundtrip_time() (in module
attribute), 109 test_deltaDTB4824), 119
knownValues (test_minimalmodbus.TestHexdecode at- minimalmodbus (module), 13
tribute), 108 ModbusException, 20
knownValues (test_minimalmodbus.TestHexencode at- mode (minimalmodbus.Instrument attribute), 14
tribute), 108 MODE_ASCII (in module minimalmodbus), 13
knownValues (test_minimalmodbus.TestLongToBytestringMODE_RTU (in module minimalmodbus), 13
attribute), 106
N
knownValues (test_minimalmodbus.TestNumToOneByteString
attribute), 105
NegativeAcknowledgeError, 21
knownValues (test_minimalmodbus.TestNumToTwoByteString
NoResponseError, 21
attribute), 105
knownValues (test_minimalmodbus.TestPack at- O
tribute), 107
open() (dummy_serial.Serial method), 80
knownValues (test_minimalmodbus.TestPredictResponseSize
attribute), 104
P
knownValues (test_minimalmodbus.TestSanityEmbedExtractPayload
attribute), 104 parse_commandline() (in module
knownValues (test_minimalmodbus.TestSanityFloat test_deltaDTB4824), 119
attribute), 106 precalculate_read_size (minimalmod-
knownValues (test_minimalmodbus.TestSanityHexencodeHexdecode bus.Instrument attribute), 14
attribute), 108 Python Enhancement Proposals
knownValues (test_minimalmodbus.TestSanityLong PEP 440, 59
attribute), 106 PYTHONPATH, 63
knownValues (test_minimalmodbus.TestSanityPackUnpack
attribute), 108 R
knownValues (test_minimalmodbus.TestSanityTextstring read() (dummy_serial.Serial method), 80
attribute), 107 read_bit() (minimalmodbus.Instrument method), 15
read_bits()
knownValues (test_minimalmodbus.TestSanityTwoByteString (minimalmodbus.Instrument method),
attribute), 105 15
read_float() (minimalmodbus.Instrument method),
knownValues (test_minimalmodbus.TestSanityTwosComplement
attribute), 109 18
knownValues (test_minimalmodbus.TestSanityValuelist read_long() (minimalmodbus.Instrument method),
attribute), 107 17
knownValues (test_minimalmodbus.TestSetBitOn at- read_register() (minimalmodbus.Instrument
tribute), 109 method), 16
knownValues (test_minimalmodbus.TestSwap at- read_registers() (minimalmodbus.Instrument
tribute), 108 method), 20
read_string()
knownValues (test_minimalmodbus.TestTextstringToBytestring (minimalmodbus.Instrument
attribute), 107 method), 19
reset_input_buffer()
knownValues (test_minimalmodbus.TestTwoByteStringToNum (dummy_serial.Serial
attribute), 105 method), 80
knownValues (test_minimalmodbus.TestTwosComplementreset_output_buffer() (dummy_serial.Serial
attribute), 108 method), 80
knownValues (test_minimalmodbus.TestUnpack at- RESPONSES (in module dummy_serial), 79
tribute), 107 roundtrip_time (minimalmodbus.Instrument at-
knownValues (test_minimalmodbus.TestValuelistToBytestring tribute), 15
attribute), 106
126 Index
MinimalModbus Documentation, Release 2.0.1
S tearDown() (test_minimalmodbus.TestDummyCommunicationWithPortC
Serial (class in dummy_serial), 79 method), 116
serial (minimalmodbus.Instrument attribute), 14 tearDown() (test_minimalmodbus.TestVerboseDummyCommunicationWi
setUp() (test_minimalmodbus.TestDummyCommunication method), 116
method), 112 test_deltaDTB4824 (module), 117
test_minimalmodbus
setUp() (test_minimalmodbus.TestDummyCommunicationBroadcast (module), 102
method), 116 testAddressNotInteger()
(test_minimalmodbus.TestCheckResponseRegisterAddress
setUp() (test_minimalmodbus.TestDummyCommunicationDTB4824_ASCII
method), 115 method), 111
testAllowLowercase()
setUp() (test_minimalmodbus.TestDummyCommunicationDTB4824_RTU
method), 115 (test_minimalmodbus.TestHexdecode method),
108
setUp() (test_minimalmodbus.TestDummyCommunicationHandleLocalEcho
method), 116 TestBitsToBytestring (class in
test_minimalmodbus),
setUp() (test_minimalmodbus.TestDummyCommunicationOmegaSlave1 105
method), 114 TestBitToBytestring (class in
test_minimalmodbus),
setUp() (test_minimalmodbus.TestDummyCommunicationOmegaSlave10 105
method), 115 TestBytestringToBits (class in
test_minimalmodbus),
setUp() (test_minimalmodbus.TestDummyCommunicationThreeInstrumentsPortClosure 105
method), 116 TestBytestringToFloat (class in
test_minimalmodbus),
setUp() (test_minimalmodbus.TestDummyCommunicationWithPortClosure 106
method), 115 TestBytestringToLong (class in
test_minimalmodbus),
setUp() (test_minimalmodbus.TestVerboseDummyCommunicationWithPortClosure 106
method), 116 TestBytestringToTextstring (class in
show_current_values() (in module test_minimalmodbus), 107
test_deltaDTB4824), 118 TestBytestringToValuelist (class in
SHOW_ERROR_MESSAGES_FOR_ASSERTRAISES (in test_minimalmodbus), 107
module test_minimalmodbus), 103 TestCalculateCrcString (class in
show_instrument_settings() (in module test_minimalmodbus), 109
test_deltaDTB4824), 118 TestCalculateLrcString (class in
show_test_settings() (in module test_minimalmodbus), 109
test_deltaDTB4824), 118 TestCalculateMinimumSilentPeriod (class in
SlaveDeviceBusyError, 21 test_minimalmodbus), 104
SlaveReportedException, 20 TestCalculateNumberOfBytesForBits (class
SLEEPTIME_READ (in module dummy_serial), 79 in test_minimalmodbus), 106
SLEEPTIME_WRITE (in module dummy_serial), 79 testCalculationTime()
(test_minimalmodbus.TestCalculateCrcString
T method), 109
TestCheckBit (class in test_minimalmodbus), 109
tearDown() (test_minimalmodbus.TestDummyCommunication
TestCheckBool (class in test_minimalmodbus), 112
method), 114
TestCheckBytes (class in test_minimalmodbus), 111
tearDown() (test_minimalmodbus.TestDummyCommunicationBroadcast
TestCheckFunctioncode (class in
method), 116
test_minimalmodbus), 109
tearDown() (test_minimalmodbus.TestDummyCommunicationDTB4824_ASCII
TestCheckInt (class in test_minimalmodbus), 112
method), 115
TestCheckMode (class in test_minimalmodbus), 110
tearDown() (test_minimalmodbus.TestDummyCommunicationDTB4824_RTU
TestCheckNumerical (class in
method), 115
test_minimalmodbus), 112
tearDown() (test_minimalmodbus.TestDummyCommunicationHandleLocalEcho
TestCheckRegisteraddress (class in
method), 116
test_minimalmodbus), 110
tearDown() (test_minimalmodbus.TestDummyCommunicationOmegaSlave1
TestCheckResponsenumber_of_registers
method), 115
(class in test_minimalmodbus), 111
tearDown() (test_minimalmodbus.TestDummyCommunicationOmegaSlave10
TestCheckResponseNumberOfBytes (class in
method), 115
test_minimalmodbus), 110
tearDown() (test_minimalmodbus.TestDummyCommunicationThreeInstrumentsPortClosure
TestCheckResponseRegisterAddress (class in
method), 116
test_minimalmodbus), 110
Index 127
MinimalModbus Documentation, Release 2.0.1
128 Index
MinimalModbus Documentation, Release 2.0.1
testInconsistentLengthlimits() (test_minimalmodbus.TestCalculateCrcString
(test_minimalmodbus.TestCheckString method), 109
method), 111 testKnownValues()
testInconsistentLimits() (test_minimalmodbus.TestCalculateLrcString
(test_minimalmodbus.TestCheckInt method), method), 109
112 testKnownValues()
testInconsistentLimits() (test_minimalmodbus.TestCalculateMinimumSilentPeriod
(test_minimalmodbus.TestCheckNumerical method), 104
method), 112 testKnownValues()
testInputNotBytes() (test_minimalmodbus.TestCalculateNumberOfBytesForBits
(test_minimalmodbus.TestCheckBytes method), method), 106
111 testKnownValues()
testInputNotString() (test_minimalmodbus.TestCheckBit method),
(test_minimalmodbus.TestCheckString 109
method), 111 testKnownValues()
testInputNotString() (test_minimalmodbus.TestCheckBool method),
(test_minimalmodbus.TestPrintOut method), 112
112 testKnownValues()
testInvalidAddress() (test_minimalmodbus.TestCheckBytes method),
(test_minimalmodbus.TestCheckResponseRegisterAddress 111
method), 110 testKnownValues()
testInvalidPayloads() (test_minimalmodbus.TestCheckInt method),
(test_minimalmodbus.TestParsePayload 112
method), 104 testKnownValues()
testInvalidReferenceData() (test_minimalmodbus.TestCheckMode method),
(test_minimalmodbus.TestCheckResponseWriteData 110
method), 111 testKnownValues()
testInvalidResponsenumber_of_registersRange() (test_minimalmodbus.TestCheckNumerical
(test_minimalmodbus.TestCheckResponsenumber_of_registers
method), 112
method), 111 testKnownValues()
testKnownLoop() (test_minimalmodbus.TestNumToOneByteString(test_minimalmodbus.TestCheckRegisteraddress
method), 105 method), 110
testKnownValues() testKnownValues()
(test_minimalmodbus.TestBitsToBytestring (test_minimalmodbus.TestCheckSlaveaddress
method), 105 method), 110
testKnownValues() testKnownValues()
(test_minimalmodbus.TestBitToBytestring (test_minimalmodbus.TestCheckString
method), 105 method), 111
testKnownValues() testKnownValues()
(test_minimalmodbus.TestBytestringToBits (test_minimalmodbus.TestCreatePayload
method), 105 method), 103
testKnownValues() testKnownValues()
(test_minimalmodbus.TestBytestringToFloat (test_minimalmodbus.TestDescribeBytes
method), 106 method), 108
testKnownValues() testKnownValues()
(test_minimalmodbus.TestBytestringToLong (test_minimalmodbus.TestEmbedPayload
method), 106 method), 104
testKnownValues() testKnownValues()
(test_minimalmodbus.TestBytestringToTextstring (test_minimalmodbus.TestExtractPayload
method), 107 method), 104
testKnownValues() testKnownValues()
(test_minimalmodbus.TestBytestringToValuelist (test_minimalmodbus.TestFloatToBytestring
method), 107 method), 106
testKnownValues() testKnownValues()
Index 129
MinimalModbus Documentation, Release 2.0.1
(test_minimalmodbus.TestFromTwosComplement testKnownValuesLoop()
method), 109 (test_minimalmodbus.TestSanityHexencodeHexdecode
testKnownValues() method), 108
(test_minimalmodbus.TestHexdecode method), TestLongToBytestring (class in
108 test_minimalmodbus), 106
testKnownValues() testMeasureRoundtriptime()
(test_minimalmodbus.TestHexencode method), (test_minimalmodbus.TestDummyCommunication
108 method), 114
testKnownValues() testNotAscii() (test_minimalmodbus.TestCheckString
(test_minimalmodbus.TestLongToBytestring method), 111
method), 106 testNotIntegerInput()
testKnownValues() (test_minimalmodbus.TestCheckBytes method),
(test_minimalmodbus.TestNumToOneByteString 111
method), 105 testNotIntegerInput()
testKnownValues() (test_minimalmodbus.TestCheckMode method),
(test_minimalmodbus.TestNumToTwoByteString 110
method), 105 testNotIntegerInput()
testKnownValues() (test_minimalmodbus.TestPack (test_minimalmodbus.TestCheckSlaveaddress
method), 107 method), 110
testKnownValues() testNotIntegerInput()
(test_minimalmodbus.TestParsePayload (test_minimalmodbus.TestCheckString
method), 104 method), 111
testKnownValues() testNotNumericInput()
(test_minimalmodbus.TestPredictResponseSize (test_minimalmodbus.TestCheckNumerical
method), 104 method), 112
testKnownValues() testNotString() (test_minimalmodbus.TestCheckResponsenumber_of_
(test_minimalmodbus.TestPrintOut method), method), 111
112 testNotString() (test_minimalmodbus.TestCheckResponseRegisterAd
testKnownValues() method), 110
(test_minimalmodbus.TestSanityEmbedExtractPayload
testNotString() (test_minimalmodbus.TestCheckResponseWriteData
method), 104 method), 111
testKnownValues() testNotStringInput()
(test_minimalmodbus.TestSanityHexencodeHexdecode (test_minimalmodbus.TestCalculateCrcString
method), 108 method), 109
testKnownValues() testNotStringInput()
(test_minimalmodbus.TestSetBitOn method), (test_minimalmodbus.TestCalculateLrcString
109 method), 109
testKnownValues() (test_minimalmodbus.TestSwap testNotStringInput()
method), 108 (test_minimalmodbus.TestCheckResponseNumberOfBytes
testKnownValues() method), 110
(test_minimalmodbus.TestTextstringToBytestring testnumber_of_registersNotInteger()
method), 107 (test_minimalmodbus.TestCheckResponsenumber_of_registers
testKnownValues() method), 111
(test_minimalmodbus.TestTwoByteStringToNum TestNumToOneByteString (class in
method), 105 test_minimalmodbus), 104
testKnownValues() TestNumToTwoByteString (class in
(test_minimalmodbus.TestTwosComplement test_minimalmodbus), 105
method), 108 testOutOfRange() (test_minimalmodbus.TestFromTwosComplement
testKnownValues() method), 109
(test_minimalmodbus.TestUnpack method), testOutOfRange() (test_minimalmodbus.TestTwosComplement
108 method), 109
testKnownValues() TestPack (class in test_minimalmodbus), 107
(test_minimalmodbus.TestValuelistToBytestring TestParsePayload (class in test_minimalmodbus),
method), 107 104
130 Index
MinimalModbus Documentation, Release 2.0.1
testPerformcommandKnownResponse() testReadBitWrongType()
(test_minimalmodbus.TestDummyCommunication (test_minimalmodbus.TestDummyCommunication
method), 114 method), 112
testPerformcommandWrongInputType() testReadBitWrongValue()
(test_minimalmodbus.TestDummyCommunication (test_minimalmodbus.TestDummyCommunication
method), 114 method), 112
testPerformcommandWrongInputValue() testReadFloat() (test_minimalmodbus.TestDummyCommunication
(test_minimalmodbus.TestDummyCommunication method), 113
method), 114 testReadFloatWrongType()
testPerformcommandWrongSlaveResponse() (test_minimalmodbus.TestDummyCommunication
(test_minimalmodbus.TestDummyCommunication method), 113
method), 114 testReadFloatWrongValue()
testPortAlreadyClosed() (test_minimalmodbus.TestDummyCommunication
(test_minimalmodbus.TestDummyCommunication method), 113
method), 114 testReadingNotAllowed()
testPortAlreadyClosed() (test_minimalmodbus.TestDummyCommunicationBroadcast
(test_minimalmodbus.TestDummyCommunicationWithPortClosure
method), 116
method), 116 testReadLong() (test_minimalmodbus.TestDummyCommunication
testPortAlreadyOpen() method), 113
(test_minimalmodbus.TestDummyCommunication testReadLongWrongType()
method), 114 (test_minimalmodbus.TestDummyCommunication
testPortWillBeOpened() method), 113
(test_minimalmodbus.TestDummyCommunication testReadLongWrongValue()
method), 114 (test_minimalmodbus.TestDummyCommunication
TestPredictResponseSize (class in method), 113
test_minimalmodbus), 104 testReadPortClosed()
TestPrintOut (class in test_minimalmodbus), 112 (test_minimalmodbus.TestDummyCommunication
testRange() (test_minimalmodbus.TestSanityEmbedExtractPayload
method), 114
method), 104 testReadRegister()
testReadBit() (test_minimalmodbus.TestDummyCommunication (test_minimalmodbus.TestDummyCommunication
method), 112 method), 113
testReadBit() (test_minimalmodbus.TestDummyCommunicationDTB4824_ASCII
testReadRegister()
method), 115 (test_minimalmodbus.TestDummyCommunicationDTB4824_ASCI
testReadBit() (test_minimalmodbus.TestDummyCommunicationDTB4824_RTU
method), 115
method), 115 testReadRegister()
testReadBit() (test_minimalmodbus.TestDummyCommunicationOmegaSlave1
(test_minimalmodbus.TestDummyCommunicationDTB4824_RTU
method), 114 method), 115
testReadBit() (test_minimalmodbus.TestDummyCommunicationOmegaSlave10
testReadRegister()
method), 115 (test_minimalmodbus.TestDummyCommunicationHandleLocalEch
testReadBits() (test_minimalmodbus.TestDummyCommunication method), 116
method), 113 testReadRegister()
testReadBits() (test_minimalmodbus.TestDummyCommunicationDTB4824_ASCII
(test_minimalmodbus.TestDummyCommunicationOmegaSlave1
method), 115 method), 114
testReadBits() (test_minimalmodbus.TestDummyCommunicationDTB4824_RTU
testReadRegister()
method), 115 (test_minimalmodbus.TestDummyCommunicationOmegaSlave10
testReadBitsWrongValue() method), 115
(test_minimalmodbus.TestDummyCommunication testReadRegister()
method), 113 (test_minimalmodbus.TestVerboseDummyCommunicationWithPor
testReadBitWithNoResponse() method), 116
(test_minimalmodbus.TestDummyCommunication testReadRegisters()
method), 112 (test_minimalmodbus.TestDummyCommunication
testReadBitWithWrongByteCountResponse() method), 114
(test_minimalmodbus.TestDummyCommunication testReadRegisters()
method), 112 (test_minimalmodbus.TestDummyCommunicationDTB4824_ASCI
Index 131
MinimalModbus Documentation, Release 2.0.1
132 Index
MinimalModbus Documentation, Release 2.0.1
Index 133
MinimalModbus Documentation, Release 2.0.1
(test_minimalmodbus.TestDummyCommunication 109
method), 113 testWrongInputType()
testWriteRegisterWithWrongWritedataResponse() (test_minimalmodbus.TestCheckInt method),
(test_minimalmodbus.TestDummyCommunication 112
method), 113 testWrongInputType()
testWriteRegisterWrongType() (test_minimalmodbus.TestEmbedPayload
(test_minimalmodbus.TestDummyCommunication method), 104
method), 113 testWrongInputType()
testWriteRegisterWrongValue() (test_minimalmodbus.TestExtractPayload
(test_minimalmodbus.TestDummyCommunication method), 104
method), 113 testWrongInputType()
testWriteString() (test_minimalmodbus.TestFloatToBytestring
(test_minimalmodbus.TestDummyCommunication method), 106
method), 113 testWrongInputType()
testWriteStringWrongType() (test_minimalmodbus.TestFromTwosComplement
(test_minimalmodbus.TestDummyCommunication method), 109
method), 114 testWrongInputType()
testWriteStringWrongValue() (test_minimalmodbus.TestHexdecode method),
(test_minimalmodbus.TestDummyCommunication 108
method), 114 testWrongInputType()
testWrongCustomError() (test_minimalmodbus.TestHexencode method),
(test_minimalmodbus.TestCheckString 108
method), 111 testWrongInputType()
testWrongFunctioncode() (test_minimalmodbus.TestLongToBytestring
(test_minimalmodbus.TestCheckFunctioncode method), 106
method), 110 testWrongInputType()
testWrongFunctioncodeListValues() (test_minimalmodbus.TestNumToTwoByteString
(test_minimalmodbus.TestCheckFunctioncode method), 105
method), 110 testWrongInputType()
testWrongFunctioncodeNoRange() (test_minimalmodbus.TestPack method),
(test_minimalmodbus.TestCheckFunctioncode 107
method), 110 testWrongInputType()
testWrongFunctioncodeType() (test_minimalmodbus.TestPredictResponseSize
(test_minimalmodbus.TestCheckFunctioncode method), 104
method), 110 testWrongInputType()
testWrongInput() (test_minimalmodbus.TestNumToOneByteString (test_minimalmodbus.TestSetBitOn method),
method), 105 109
testWrongInputType() testWrongInputType()
(test_minimalmodbus.TestBytestringToFloat (test_minimalmodbus.TestTextstringToBytestring
method), 106 method), 107
testWrongInputType() testWrongInputType()
(test_minimalmodbus.TestBytestringToLong (test_minimalmodbus.TestTwoByteStringToNum
method), 106 method), 105
testWrongInputType() testWrongInputType()
(test_minimalmodbus.TestBytestringToTextstring (test_minimalmodbus.TestTwosComplement
method), 107 method), 109
testWrongInputType() testWrongInputType()
(test_minimalmodbus.TestBytestringToValuelist (test_minimalmodbus.TestUnpack method),
method), 107 108
testWrongInputType() testWrongInputType()
(test_minimalmodbus.TestCalculateMinimumSilentPeriod (test_minimalmodbus.TestValuelistToBytestring
method), 104 method), 107
testWrongInputType() testWrongInputValue()
(test_minimalmodbus.TestCheckBit method), (test_minimalmodbus.TestBytestringToFloat
134 Index
MinimalModbus Documentation, Release 2.0.1
Index 135
MinimalModbus Documentation, Release 2.0.1
W
write() (dummy_serial.Serial method), 80
write_bit() (minimalmodbus.Instrument method),
15
write_bits() (minimalmodbus.Instrument method),
16
write_float() (minimalmodbus.Instrument
method), 18
write_long() (minimalmodbus.Instrument method),
18
write_register() (minimalmodbus.Instrument
method), 17
write_registers() (minimalmodbus.Instrument
method), 20
write_string() (minimalmodbus.Instrument
method), 19
WRONG_ASCII_RESPONSES (in module
test_minimalmodbus), 116
wrongValues (test_minimalmodbus.TestSwap at-
tribute), 108
136 Index