I currently trying to receive data from my Arduino slave to my computer. I am successful in creating an Arduino slave. However, when I am trying to receive the data from my computer using the Pymodbus library, my code fails to receive the data from the Arduino and raises a ModbusIOException. For the specifications of my project, I am trying to build a Modbus RTU with the Arduino to simulate a sensor with random numbers as readings. The Arduino code uses the Modbus-Arduino library of Andre Sarmento.
https://github.com/andresarmento/modbus-arduino
I already checked my Arduino slave if it is working. I tried reading the data through a Modbus Master emulator (QModMaster), and it worked just fine. This might prove that the problem itself is from the code for the Master. Furthermore, the serial connection seems to work fine, since the self.client.connect() returns True.
These are the screenshots of the QModMaster configurations.
Slave configurations Serial Port configurations
Python code for the master:
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 code for the simulated slave and sensor:
#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));
}
Upon printing the results.registers
, it is supposedly a list of integers. However, it just raises a ModbusIOException with a message of:
'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)
It also gives this message as well.
Modbus Error: [Input/Output] Modbus Error: [Invalid Message] Incomplete message received, expected at least 2 bytes (0 received)
I already found out the solution for this thanks for the help of few people. The QModMaster uses a library called libmodbus. Since the Arduino simulated slave and sensor worked with QModMaster, it would be easier to change the previous library and instead use libmodbus. Luckily, there is a python equivalent for libmodbus which is pylibmodbus. This is the link for the library 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)