Closed chaotix- closed 10 months ago
You are right. It is something I have overlooked, probably because I was using the RS485 module with auto-direction control. Indeed, we have to assert the RE pin by calling serialPort->receive()
before doing any read operations. For a client device who always initiates a request, this is not a problem. But for server, it can be a problem.
I have applied a few changes to the CSE_ModbusRTU
library fix this issue.
CSE_ModbusRTU::receive()
.enableReceive()
and disableReceive()
functions to CSE_ModbusRTU
class.disableReceive()
in CSE_ModbusRTU_Client:: receive()
after a response is received or timeout occurs.These changes will be available in version 0.0.7
.
In the CSE_ArduinoRS485
library, I made the following changes.
assertDE()
, deassertDE()
, assertRE()
, deassertRE()
functions to the RS485Class
class. These functions will set the GPIO pins associated with DE and RE pins if they are defined in the port.These changes will be available in 1.0.11
.
Please update to the new versions when they are available, and let me know if it is working as expected.
The new versions work for me out of the box.
Thank you for your quick response.
CSE_ModbusRTU::receive does handle the RE pin. Just calling serialPort->receive() before and serialPort->noReceive() after receiving data should be sufficient. This call is necessary if a RE pin is specified for the RS485Class. It sets RE LOW to receive and HIGH to stop receiving. If no RE pin is set the call does nothing.
Just calling RS485.receive() before issuing e.g. a CSE_ModbusRTU_Client::readHoldingRegister call does not work as the sent request will be in the serial port queue if RE is LOW while the request is sent.
The fix (that works for me) is trivial:
As I don't use CSE_ModbusRTU_Server I don't know if this conflicts with this. If CSE_Modbus_RTU::receive() should receive data that was sent while this function is not active this would obviously not work. Then RE should be LOW all the time except when sending data. Then serialPort->receive() would need to be called when initializing and at the end of CSE_ModbusRTU::sent and serialPort->noReceive() at the beginning of CSE_ModbusRTU::sent.
An alternative approach would be to discard the first bytes of the received data after sending a request if the read data starts with the sent request.