Writing Registers
Write to Modbus registers and coils with PyModbus. Single writes, batch writes, data type conversion, and read-modify-write patterns.
Writing to Modbus Registers
PyModbus supports writing single registers, multiple registers, and coils. You can also convert floats and strings into register values using BinaryPayloadBuilder.
Write Single Register
from pymodbus.client import ModbusTcpClient
client = ModbusTcpClient('192.168.1.100')
client.connect()
# Write value 1234 to register 100
client.write_register(address=100, value=1234, slave=1)
client.close()Track Modbus writes in production
TofuPilot records test results from your PyModbus scripts, tracks pass/fail rates, and generates compliance reports. Free to start.
Write Multiple Registers
from pymodbus.client import ModbusTcpClient
client = ModbusTcpClient('192.168.1.100')
client.connect()
values = [100, 200, 300, 400, 500]
client.write_registers(address=100, values=values, slave=1)
# Verify by reading back
result = client.read_holding_registers(100, 5, slave=1)
print(f"Written values: {result.registers}")
client.close()Write Coils (Digital Outputs)
# Write single coil
client.write_coil(address=0, value=True, slave=1)
# Write multiple coils
coil_values = [True, False, True, True, False, False, True, False]
client.write_coils(address=0, values=coil_values, slave=1)
# Read back to verify
result = client.read_coils(0, 8, slave=1)
print(f"Coil states: {result.bits[:8]}")Writing Data Types
32-bit Integer
from pymodbus.payload import BinaryPayloadBuilder
from pymodbus.constants import Endian
def write_int32(client, address, value):
builder = BinaryPayloadBuilder(
byteorder=Endian.BIG,
wordorder=Endian.BIG
)
builder.add_32bit_int(value)
client.write_registers(address, builder.to_registers())
write_int32(client, address=100, value=-123456)Float
def write_float(client, address, value):
builder = BinaryPayloadBuilder(
byteorder=Endian.BIG,
wordorder=Endian.BIG
)
builder.add_32bit_float(value)
client.write_registers(address, builder.to_registers())
write_float(client, address=100, value=23.5)String
def write_string(client, address, text, length=16):
builder = BinaryPayloadBuilder(
byteorder=Endian.BIG,
wordorder=Endian.BIG
)
text = text[:length].ljust(length, '\x00')
builder.add_string(text)
client.write_registers(address, builder.to_registers())
write_string(client, address=100, text="PUMP_01", length=16)Read-Modify-Write
Write a value and immediately read it back to confirm it stuck.
import time
from pymodbus.client import ModbusTcpClient
def write_and_verify(client, address, value, slave=1):
write_result = client.write_register(address, value, slave)
if write_result.isError():
print(f"Write failed: {write_result}")
return False
read_result = client.read_holding_registers(address, 1, slave)
if read_result.isError():
print(f"Read verification failed: {read_result}")
return False
actual = read_result.registers[0]
if actual == value:
print(f"Wrote {value} to address {address}")
return True
else:
print(f"Mismatch: expected {value}, got {actual}")
return False
client = ModbusTcpClient('192.168.1.100')
client.connect()
write_and_verify(client, address=100, value=12345)
client.close()Batch Writing
from pymodbus.client import ModbusTcpClient
def batch_write_configs(client, configs):
for address, value in configs.items():
result = client.write_register(address, value)
if result.isError():
print(f"Failed to write address {address}: {result}")
return False
return True
client = ModbusTcpClient('192.168.1.100')
client.connect()
configs = {
1000: 235, # Temperature setpoint: 23.5C
1001: 750, # Pressure setpoint: 75.0 bar
1002: 1500, # Flow setpoint: 1500 L/h
1003: 60, # Time setpoint: 60 seconds
}
batch_write_configs(client, configs)
client.close()Write with Retry
import time
from pymodbus.exceptions import ModbusException
def safe_write(client, address, value, max_retries=3):
for attempt in range(max_retries):
try:
result = client.write_register(address, value)
if not result.isError():
return True
print(f"Attempt {attempt + 1} failed: {result}")
if hasattr(result, 'exception_code'):
if result.exception_code == 2: # Illegal address
print(f"Address {address} does not exist")
return False
elif result.exception_code == 3: # Illegal value
print(f"Value {value} out of range")
return False
except ModbusException as e:
print(f"Modbus exception: {e}")
if attempt < max_retries - 1:
time.sleep(0.5)
return FalseWrite Protection
Some devices require a password before writes are allowed.
import time
def unlock_and_write(client, password_register, password, address, value):
client.write_register(password_register, password)
time.sleep(0.1) # Wait for unlock
result = client.write_register(address, value)
client.write_register(password_register, 0) # Lock again
return not result.isError()
unlock_and_write(client, 9999, 1234, 100, 500)Always validate values before writing to production equipment. Wrong values can damage hardware or cause safety issues.
Common Issues
Value Out of Range
# Registers are 16-bit unsigned (0-65535)
# This wraps or fails
client.write_register(100, 70000) # Too big
# Clamp to valid range
value = min(65535, max(0, your_value))
client.write_register(100, value)Wrong Data Type
# Device expects scaled integer, not float
client.write_register(100, 23.5) # Truncates to 23
# Scale first
scaled = int(23.5 * 10) # 235
client.write_register(100, scaled)Byte Order Issues
from pymodbus.payload import BinaryPayloadBuilder
from pymodbus.constants import Endian
# If device shows wrong values, try different byte order
builder = BinaryPayloadBuilder(
byteorder=Endian.LITTLE, # Try BIG if wrong
wordorder=Endian.LITTLE # Try BIG if wrong
)