我目前正在尝试从我的Arduino从服务器接收数据到我的计算机。我成功地创建了一个Arduino从属。但是,当我尝试使用Pymodbus库从我的计算机接收数据时,我的代码无法从Arduino接收数据并引发ModbusIOException。对于我的项目的规范,我正在尝试使用Arduino构建一个Modbus RTU,以模拟具有随机数字读数的传感器。Arduino代码使用Andre Sarmento的Modbus-Arduino库。
https://github.com/andresarmento/modbus-arduino
我已经检查了我的Arduino奴隶是否工作正常。我尝试通过Modbus Master仿真器(QModMaster)读取数据,它工作得很好。这可能证明问题本身来自于Master的代码。此外,串行连接似乎工作得很好,因为self.client.connect()返回True。
这些是QModMaster配置的屏幕截图。
Slave configurations Serial Port configurations
主服务器的Python代码:
class ModbusRTU:
def __init__(self, graph_name, port, baudrate=9600,
stopbits=1, bytesize=8, parity='N',
timeout=1):
self.graph_name = graph_name
self.client = ModbusSerialClient(method='rtu',
port=port,
baudrate=baudrate,
parity=parity,
timeout=timeout)
self.connection = self.client.connect()
result = self.client.read_holding_registers(address=0,
count=2,
unit=1)
print(result.registers)
if __name__ == '__main__':
modbus = ModbusRTU(graph_name='/dev/ttyACM0',
port='/dev/ttyACM0', baudrate=9600,
stopbits=1, bytesize=8, parity='N',
timeout=1)
print(modbus.check_connection())
模拟从机和传感器的Arduino代码:
#include <Modbus.h>
#include <ModbusSerial.h>
ModbusSerial mb;
const int READING = 0;
const int DECIMAL = 1;
void setup() {
mb.config(&Serial, 9600, SERIAL_8N1);
mb.setSlaveId(1);
mb.addHreg(READING);
mb.addHreg(DECIMAL);
}
void loop() {
mb.task();
mb.Hreg(READING, random(1, 201));
mb.Hreg(DECIMAL, random(0, 4));
}
在打印results.registers
时,它应该是一个整数列表。但是,它只会引发一个包含以下消息的ModbusIOException:
'ModbusIOException' object has no attribute 'registers'
File "/home/kebaranas/PythonProjects/ThirsyWell/tools/utilities.py", line 21, in __init__
print(result.registers)
File "/home/kebaranas/PythonProjects/ThirsyWell/tools/utilities.py", line 29, in <module>
timeout=1)
它也给出了这个信息。
Modbus Error: [Input/Output] Modbus Error: [Invalid Message] Incomplete message received, expected at least 2 bytes (0 received)
发布于 2019-06-02 20:52:03
感谢几个人的帮助,我已经找到了解决这个问题的办法。QModMaster使用一个名为libmodbus的库。由于Arduino模拟的从机和传感器与QModMaster一起工作,因此更改以前的库并使用libmodbus会更容易。幸运的是,有一个与libmodbus等效的python,它就是pylibmodbus。这是库https://github.com/stephane/pylibmodbus的链接。
from pylibmodbus import ModbusRtu
class ModbusRTU:
def __init__(self, port, baudrate=9600, databit=8, parity='None',
stopbit=1, timeout=1000):
self.parity = {'Odd': 'O', 'Even': 'E', 'None': 'N'}
self.modbus = ModbusRtu(device=port.encode('ascii'),
data_bit=databit, baud=baudrate,
parity=self.parity[parity] \
.encode('ascii'),
stop_bit=stopbit)
self.modbus.set_response_timeout(timeout/1000)
self.modbus.connect()
self.modbus.set_slave(1)
result = self.modbus.read_registers(0, 2)
print(result)
self.modbus.close()
if __name__ == '__main__':
main = ModbusRTU('/dev/ttyACM0', baudrate=9600, databit=8,
parity='None', stopbit=1)
发布于 2019-05-30 20:57:53
在print(result.registers)
之前,请尝试以下代码片段:
if not result.isError():
print(result.registers)
else:
print("error: {}".format(result))
另外,填写其他ModbusSerialClient()
参数。
下面是您的代码片段的更新:
from pymodbus.client.sync import ModbusSerialClient
class ModbusRTU:
def __init__(self, graph_name, port, baudrate=9600,
stopbits=1, bytesize=8, parity='N',
timeout=1):
self.graph_name = graph_name
self.client = ModbusSerialClient(
method='rtu',
port=port,
baudrate=baudrate,
parity=parity,
timeout=timeout,
stopbits=stopbits,
bytesize=bytesize
)
self.connection = self.client.connect()
result = self.client.read_input_registers(address=1,
count=2,
unit=1)
if not result.isError():
print(result.registers)
else:
print("error: {}".format(result))
if __name__ == '__main__':
modbus = ModbusRTU(
graph_name='/dev/ttyACM0',
port='/dev/ttyACM0', baudrate=9600,
stopbits=1, bytesize=8, parity='N',
timeout=1
)
发布于 2019-05-30 22:21:16
你在你的从机中定义了保持寄存器,但是你试图将它们读取为输入寄存器,试着改变这一行:
result = self.client.read_input_registers(address=1, count=2, unit=1)
至:
result = self.client.read_holding_registers(address=1, count=2, unit=1)
请注意,Modbus规范定义了这两种不同类型的寄存器:保持寄存器和输入寄存器,具体取决于它们所在的存储区域。
https://stackoverflow.com/questions/56378428
复制相似问题