I have been tasked with implementing a pymodbus-based Modbus server. The server will run on a Linux machine like a Raspberry Pi or Up2 controller. It is expected to interface with a Modbus client which I have no control over. That external Modbus client is expecting to be able to read INPUT REGISTERS as well as holding registers served by my Modbus server.
I can set the values of the HOLDING registers that will be read by the external client. I have been unable to set the values of the INPUT registers that the external client will read. How does one do that?
I saw this post which asked a similar question but the question doesn't seem to ever have been answered:
How to write to PLC input registers using pymodbus
Thanks in advance for any help!
As I said, I am not familiar with python or pymodbus, but take a look at this example which is something like what I expected would exist: https://pymodbus.readthedocs.io/en/latest/source/example/updating_server.html
Four 100 "register" arrays are created as the data store. I assume di=digital inputs, co=coils, hr=holding registers, ir=input registers
store = ModbusSlaveContext(
di=ModbusSequentialDataBlock(0, [17]*100),
co=ModbusSequentialDataBlock(0, [17]*100),
hr=ModbusSequentialDataBlock(0, [17]*100),
ir=ModbusSequentialDataBlock(0, [17]*100))
context = ModbusServerContext(slaves=store, single=True)
These values are then updated in "updating_writer(a)" which is called by the background thread. It looks to me like it just adds 1 to each value every time it is called. In a real world PLC, this function would probably read things like sensors, settings, and other operational/state/configuration data.
Thanks to Marker and to all the examples online. I finally got this working as I wanted. Hope this helps someone else.
There were several gotchas I ran into:
Sooo...
First I had to do this: from threading import Thread
Then I kicked the following off in a Process as I'd done before, but RIGHT BEFORE calling StartTcpServer I kicked off the updating_writer Thread (all start_addr, init_val and num_addrs variables are set earlier).
discrete_inputs_obj = ModbusSequentialDataBlock(di_start_addr, [di_init_val]*di_num_addrs)
coils_obj = ModbusSequentialDataBlock(co_start_addr, [co_init_val]*co_num_addrs)
holding_regs_obj = ModbusSequentialDataBlock(hr_start_addr, [hr_init_val]*hr_num_addrs)
input_regs_obj = ModbusSequentialDataBlock(ir_start_addr, [ir_init_val]*ir_num_addrs)
mb_store = ModbusSlaveContext(di=discrete_inputs_obj, co=coils_obj, hr=holding_regs_obj, ir=input_regs_obj, zero_mode=True)
mb_context = ModbusServerContext(slaves=mb_store, single=True)
mb_store = ModbusSlaveContext(
di=ModbusSequentialDataBlock(di_start_addr, [di_init_val]*di_num_addrs),
co=ModbusSequentialDataBlock(co_start_addr, [co_init_val]*co_num_addrs),
hr=ModbusSequentialDataBlock(hr_start_addr, [hr_init_val]*hr_num_addrs),
ir=ModbusSequentialDataBlock(ir_start_addr, [ir_init_val]*ir_num_addrs))
mb_context = ModbusServerContext(slaves=mb_store, single=True)
updating_writer_cfg = {}
updating_writer_cfg["mb_context"] = mb_context
updating_writer_cfg["managed_obj"] = managed_obj #For being able to send messages to this Thread
updating_writer_thread = Thread(target = updating_writer, args = [updating_writer_cfg]) # We need this to be a thread in this process so that they can share the same datastore
updating_writer_thread.start()
StartTcpServer(mb_context, address=("", port))
In the While loop of updating_writer I have code that polls the managed_obj to receive messages. In adding the key bits of code in that loop are:
mb_context[0].setValues(4, addr_to_write, regs_to_write)
...where 4 is the write function, addr_to_write is the register address at which to start writing and regs_to_write is a list of register values...AND...
regs_to_read = mb_context[0].getValues(3, addr_to_read, num_regs_to_read)
...where 3 is the read function, addr_to_read is the register address at which to start reading. regs_to_read will be a list of length num_regs_to_read.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.