我有一个关于pymodbus模块及其功能的问题。我的服务器工作得很好,我想实现的数据存储也很好。
下面是我的服务器和数据存储的代码:
import asyncio
from pymodbus.datastore import (ModbusSequentialDataBlock,ModbusServerContext,ModbusSlaveContext,)
from pymodbus.server import StartTcpServer
from pymodbus.device import ModbusDeviceIdentification
from pymodbus.version import version
def run_full_sync_server():
print("Creating sequential Datastore.")
# Creating continuing Datablock without gaps.
datablock = ModbusSequentialDataBlock(0, [0]*20) # Initializing starting address and registers with value 0 each
print("Creating slave Context.")
# Creating one slave context. Allows the server to respond to slave context with its unit id.
slave_context = ModbusSlaveContext(
di=datablock, # 'di' - Discrete Input Initializer
co=datablock, # 'co' - Coils Initializer
hr=datablock, # 'hr' - Holding Register Initializer
ir=datablock, # 'ir' - Input Registers Initializer
unit=1, # SlaveID
zero_mode=False
)
print("Creating Server Identity.")
# Creates Server Information.
identity = ModbusDeviceIdentification(
info_name={
"VendorName": "XXX",
"ProductCode": "ModbusKassow",
"VendorUrl": "XXX",
"ProductName": "Synchronous Py",
"ModelName": "Pymodbus Server",
"MajorMinorRevision": version.short(),
}
)
print("Starting Server.")
server_context = ModbusServerContext(slaves=slave_context, single=True)
server = StartTcpServer(context=server_context, identity=identity, address=("0.0.0.0", 502))
#return server
if name == "main":
asyncio.create_task(run_full_sync_server())我正在使用spyder,因此我需要一个独立的异步实例来运行服务器。
至于编写线圈/寄存器,有一些来自模块的函数,但是每当我使用函数write_coil时,确切的值就会出现在我的离散输入数据存储中(运行脚本两次)。
from pymodbus.client import ModbusTcpClient
client = ModbusTcpClient('127.0.0.1', port=502)
discrete_inputs = client.read_discrete_inputs(0, 14) # start reading from address 0
discrete_inputs.setBit(3, 1) # set address 3 to value 1
discrete_inputs.setBit(1,1)
print(discrete_inputs.getBit(0))
print(discrete_inputs.getBit(1))
print(discrete_inputs.bits[:])
print()
client.write_coil(10, True)
client.write_coil(12, True)
client.write_coil(15, True)
reading_coil = client.read_coils(0, 14) # start reading from address 1
print(reading_coil.bits[:])我认为离散输入和离散线圈是分离的数据存储,因为它们是单独初始化的?
另外,为什么discrete_inputs.bits[:]只返回16个bool值的列表,因为在服务器脚本中,我用20个值的列表初始化了数据存储?
每当我运行该脚本两次时,我的线圈值将出现在离散输入数据存储中:
[False, True, False, True, False, False, False, False, False, False, True, False, True, False, False, False]我知道每个寄存器/线圈只能存储16位,这对应于我从读取函数得到的16个值的列表。
我尝试了上面的代码,并期望数据存储是分开的。我还假设我可能只在一个寄存器中写东西,因为我得到了16位的返回。如果是这样的话,我不知道如何访问其他线圈地址。
编辑:代码格式
发布于 2022-11-15 19:53:22
我认为离散输入和离散线圈是独立的数据存储,因为它们是单独初始化的?
是的;但是您正在创建一个存储,然后将相同的存储分配给每个元素。尝试这样的方法(展示两种实现此功能的方法):
datablock = ModbusSequentialDataBlock(0, [0]*20)
datablock2 = ModbusSequentialDataBlock(0, [0]*20)
slave_context = ModbusSlaveContext(
di=datablock, # 'di' - Discrete Input Initializer
co=ModbusSequentialDataBlock(0, [0]*20), # 'co' - Coils Initializer
hr=datablock2, # 'hr' - Holding Register Initializer
ir=ModbusSequentialDataBlock(0, [0]*20), # 'ir' - Input Registers Initializer
unit=1, # SlaveID
zero_mode=False
)我知道每个寄存器/线圈只能存储16位,这对应于我从读取函数得到的16个值的列表。
我认为您可能混淆了Modbus协议和PyModbus实现。Modbus线圈是一位( PyModbus数据存储可能最终将这一位存储在一个16位变量中,但这是一个实现细节)。
根据医生们
响应消息中的线圈被打包为数据字段的每比特一个线圈。 状态表示为1= ON和0= OFF。第一个数据字节的LSB包含查询中寻址的输出。其他的线圈跟随到这个字节的高阶端,然后在后续的字节中从低阶到高阶。 如果返回的输出量是,而不是8个的倍数,则最终数据字节中的剩余位将被填充零(指向字节的高阶端)。bytes字段指定了完整字节的数据数量。
您正在请求14个寄存器(client.read_discrete_inputs(0, 14)),因此输出将被舍入2字节(16位)。
https://stackoverflow.com/questions/74444413
复制相似问题