Modbus is a messaging protocol that defines the packet structure for transferring data between devices in a master/slave architecture. The protocol is independent of the transmission medium and is usually transmitted over TCP (MODBUS TCP) or serial communication (MODBUS RTU). Modbus is intended as a request/reply protocol and delivers services specified by function codes. The function code in the request tells the addressed slave what kind of action to perform. The function codes most commonly supported by devices are listed below.

Function Name

Function Code

Read Coils

0x01

Read Discrete Inputs

0x02

Read Holding Registers

0x03

Read Input Registers

0x04

Write Single Coil

0x05

Write Single Register

0x06

Write Multiple Coils

0x0F

Write Multiple Registers

0x10

For more information on the MODBUS RTU see the following PDF File. Information on the MODBUS TCP can be found here.

Pycom Modbus Library

Python libraries and sample code that support Modbus TCP and Modbus RTU are available at the following GitHub Repository. To use this library, connect to the target Pycom device via ftp and upload the uModbus folder to /flash. A description of the supported function codes is found below.

Read Coils

This function code requests the status (ON/OFF) of discrete coils on a remote device. The slave device address, the address of the first coil and the number of coils must be specified in the request. The address of the first coil is 0 and a maximum of 2000 contiguous coils can be read. Python sample code is shown below.

slave_addr=0x0A
starting_address=0x00
coil_quantity=100
coil_status = modbus_obj.read_coils(slave_addr, starting_address, coil_quantity)
print('Coil status: ' + ' '.join('{:d}'.format(x) for x in coil_status))

Read Discrete Inputs

This command is used to read the status (ON/OFF) of discrete inputs on a remote device. The slave address, the address of the first input, and the quantity of inputs to be read must be specified. The address of the first input is 0 and a maximum of 2000 continuous inputs can be read. The Python sample code is shown below.

slave_addr=0x0A
starting_address=0x0
input_quantity=100
input_status = modbus_obj.read_discrete_inputs(slave_addr, starting_address, input_quantity)
print('Input status: ' + ' '.join('{:d}'.format(x) for x in input_status))

Read Holding Registers

This function code is used to read the contents of analogue output holding registers. The slave address, the starting register address, the number of registers to read and the sign of the data must be specified. Register addresses start at 0 and a maximum of 125 continuous registers can be read.

slave_addr=0x0A
starting_address=0x00
register_quantity=100
signed=True
register_value = modbus_obj.read_holding_registers(slave_addr, starting_address, register_quantity, signed)
print('Holding register value: ' + ' '.join('{:d}'.format(x) for x in register_value))

Read Input Registers

This command is used to read up to 125 continuous input registers on a remote device. The slave address, the starting register address, the number of input registers and the sign of the data must be specified. The address of the first input registers is 0.

slave_addr=0x0A
starting_address=0x00
register_quantity=100
signed=True
register_value = modbus_obj.read_input_registers(slave_addr, starting_address, register_quantity, signed)
print('Input register value: ' + ' '.join('{:d}'.format(x) for x in register_value))

Write Single Coil

This function code is used to write the state of a discrete coil on a remote device. A value of 0xFF00 means the coil should be set to ON, while a value of 0x0000 means the coil should be set to OFF. The Python sample code to set the coil at address 0x00, to an ON state is shown below.

slave_addr=0x0A
output_address=0x00
output_value=0xFF00
return_flag = modbus_obj.write_single_coil(slave_addr, output_address, output_value)
output_flag = 'Success' if return_flag else 'Failure'
print('Writing single coil status: ' + output_flag)

Write Single Register

This command is used to write the contents of an analog output holding register on a remote device. The slave address, the register address, the register value, and the signature of the data must be specified. As for all the other commands, the register addresses start from 0.

slave_addr=0x0A
register_address=0x01
register_value=-32768
signed=True
return_flag = modbus_obj.write_single_register(slave_addr, register_address, register_value, signed)
output_flag = 'Success' if return_flag else 'Failure'
print('Writing single coil status: ' + output_flag)

Write Multiple Coils

This function code is used to set a continuous sequence of coils, in a remote device, to either ON or OFF. The slave address, the starting address of the coils and an array with the coil states must be specified.

slave_addr=0x0A
starting_address=0x00
output_values=[1,1,1,0,0,1,1,1,0,0,1,1,1]
return_flag = modbus_obj.write_multiple_coils(slave_addr, starting_address, output_values)
output_flag = 'Success' if return_flag else 'Failure'
print('Writing multiple coil status: ' + output_flag)

Write Multiple Registers

This command is used to write the contents of a continuous sequence of analogue registers on a remote device. The slave address, the starting register address, the register values, and the signature of the data must be specified. The address of the first register is 0 and a maximum of 125 register values can be written. The Python sample code is shown below.

slave_addr=0x0A
register_address=0x01
register_values=[2, -4, 6, -256, 1024]
signed=True
return_flag = modbus_obj.write_multiple_registers(slave_addr, register_address, register_values, signed)
output_flag = 'Success' if return_flag else 'Failure'
print('Writing multiple register status: ' + output_flag)