Hello everyone,
I'm trying to establish a MODBUS RTU communication between my Opta WiFi and some expansion modules that I have. I am using the libraries ArduinoModbus and ArduinoRS485, as suggested in this tutorial. I already managed to successfully send commands both to read and write both coils and holding registers with some other modules from different brands, but I am having difficulties with working with this one in particular.
My wiring is quite simple: both the Opta and the module are powered with the same +24V DC supply, and the A and B connections of the Opta go into A and B of the module. A USB cable connects the Opta and my PC. All the rest is unwired. That is the only module connected to the Opta.
About the code, I started from the code in the tutorial linked above and cleaned it of all the unnecessary functions, leaving only readHoldingRegisterValues() (this is the function that I need to work with now) and adapting modbus parameters (the module requires baudrate 9600, parity N, data bits 8, stop bit 1; the address is 105, it was changed some time ago and I'm 100% sure it's the correct address since I tested it with QModMaster, as explained below). Here is the current code that I am running:
#include <ArduinoModbus.h>
#include <ArduinoRS485.h>
constexpr auto baudrate { 9600 };
constexpr auto bitduration { 1.f / baudrate };
constexpr auto preDelayBR { bitduration * 9.6f * 3.5f * 1e6 };
constexpr auto postDelayBR { bitduration * 9.6f * 3.5f * 1e6 };
void setup() {
Serial.begin(9600);
while (!Serial);
Serial.println("Modbus RTU Client");
RS485.setDelays(preDelayBR, postDelayBR);
if (!ModbusRTUClient.begin(baudrate, SERIAL_8N1)) {
Serial.println("Failed to start Modbus RTU Client!");
while (1);
}
}
void loop() {
readHoldingRegisterValues();
delay(2000);
Serial.println();
}
void readHoldingRegisterValues() {
Serial.print("Reading Holding Register values ... ");
if (!ModbusRTUClient.requestFrom(105, HOLDING_REGISTERS, 0, 8)) {
Serial.print("failed! ");
Serial.println(ModbusRTUClient.lastError());
} else {
Serial.println("success");
while (ModbusRTUClient.available()) {
Serial.print(ModbusRTUClient.read());
Serial.print(' ');
}
Serial.println();
}
}
but, instead of the actual values in the holding registers, this is the line that I get in the Serial Monitor:
Reading Holding Register values ... failed! Response not from requested slave
What am I doing wrong? Do I need to change some parameters like bitduration, pre and post delay, or something else?
Here is what I already tried:
1) If I replace that module with another one, without changing any wiring or code (except the address of the new module), the reading works! I can get the values stored in the 8 holding registers as expected.
2) If I connect the module directly to my PC with a USB-RTU adaptor and use qModMaster (with the same device address, baudrate, parity, number of data bits and stop bits that I am using in the Arduino code) to send the same commands, it works! I can read the values stored in the holding registers. So, it seems that the communication issue happens only when the Arduino Opta and that specific module in particular are communicating. Indeed, the Opta is able to communicate with other modules, and that module is able to communicate with my PC.
3) I tried to switch A and B connections in case this module had an inverted standard, but nothing (if I do so, I get a timeout error instead).
4) I tried to add a resistor (1kOhm) between A and B, but nothing. EDIT: I tried replacing the resistor with a 100 Ohm one, but nothing. I even tried with placing two resistors of 100 Ohm, one close to the Opta and one close to the module, but still nothing.
5) I tried both with and without the MODBUS GND connection between Opta and expansion module, but nothing.
6) I tried to use a different function: instead of reading the holding registers, I tried to write them (I don't report the code because it's redundant: it's again an extract of the code in the tutorial above, where in this case I leave only writeHoldingRegisterValues()). And here something curious happens: I can actually measure with a multimeter a change in the voltages on the outputs of the module, with the wanted values as expected! Nevertheless, even though the values are actually written in the holding registers of the module, the function "ModbusRTUClient.endTransmission()" outputs 0 (failure): in other words, the registers are actually written, but the Opta thinks they were not and that the communication failed.
I hope I provided you all with enough information, and thank you very much in advance!
Matteo