I've been trying to interface XY-MD02 sht20 sensors to an opta plc. There are no problems when i use only one sensor but when i try to use two only one of them works the other one prints "Response not from requested slave"
/**
Getting Started with Modbus RTU on Opta™
Name: Opta_Client
Purpose: Writes Coil and Holding Register values; Reads Coil, Discrete Input, Holding Registers, and Input Register values.
@author Arduino
*/
#include <ArduinoModbus.h>
#include <ArduinoRS485.h> // ArduinoModbus depends on the ArduinoRS485 library
#include "OptaBlue.h"
//RTU SLAVES
//Inlet SHT
#define SLAVE_ID1 1
#define FUNC_ADD1 3
#define START_ADD1 0x01
#define READ_REG1 2
#define CALIB_H1 0
#define CALIB_T1 0
//Outlet SHT
#define SLAVE_ID2 3
#define FUNC_ADD2 3
#define START_ADD2 0x01
#define READ_REG2 2
#define CALIB_H2 12
#define CALIB_T2 -3
using namespace Opta;
constexpr auto baudrate{ 9600 };
// Calculate preDelay and postDelay in microseconds as per Modbus RTU Specification
// MODBUS over serial line specification and implementation guide V1.02
// Paragraph 2.5.1.1 MODBUS Message RTU Framing
// https://modbus.org/docs/Modbus_over_serial_line_V1_02.pdf
constexpr auto bitduration{ 1.f / baudrate };
constexpr auto preDelayBR{ bitduration * 9.6f * 3.5f * 1e6 };
constexpr auto postDelayBR{ bitduration * 9.6f * 3.5f * 1e6 };
//constexpr auto preDelayBR { bitduration * 10.0f * 3.5f * 1e6 };
//Relays
int R1 = 0;
int D1608E_R1 = 0;
//sensor readings memory
float temperature = 0;
float temperature1 = 0;
float humidity = 0;
float humidity1 = 0;
void setup() {
Serial.begin(9600);
Serial.println("Modbus RTU Client");
RS485.setDelays(preDelayBR, postDelayBR);
// Start the Modbus RTU client
if (!ModbusRTUClient.begin(baudrate, SERIAL_8N1)) {
Serial.println("Failed to start Modbus RTU Client!");
while (1)
;
}
pinMode(LED_D0, OUTPUT);
pinMode(R1, OUTPUT);
pinMode(D1608E_R1, OUTPUT);
OptaController.begin();
delay(1000);
}
void loop() {
DigitalMechExpansion mechExp = OptaController.getExpansion(0);
mechExp.updateDigitalInputs();
// if (currentSensor == 1) {
Serial.println("==============================================================================================================================================");
Serial.println("INPUT");
readAndPrintRegisterValues(SLAVE_ID1, START_ADD1, READ_REG1, "Inlet temperature", "Inlet Humidity", temperature1, humidity1, CALIB_H1, CALIB_T1); // Slave ID 1
delay(100);
readAndPrintRegisterValues(SLAVE_ID2, START_ADD2, READ_REG2, "Outlet temperature", "Outlet Humidity", temperature, humidity, CALIB_H2, CALIB_T2); // Slave ID 2
Serial.println("==============================================================================================================================================");
Serial.println("OUTPUT");
if (humidity1 >= 65) {
digitalWrite(R1, HIGH);
digitalWrite(LED_D0, HIGH);
Serial.print("R1: ON , ");
} else if (humidity1 <= 65) {
digitalWrite(R1, LOW);
digitalWrite(LED_D0, LOW);
Serial.print("R1: OFF, ");
}
if (temperature1 >= 32) {
mechExp.digitalWrite(D1608E_R1, HIGH);
Serial.println(" D1608E_R1: ON ");
} else if (temperature1 <= 32) {
mechExp.digitalWrite(D1608E_R1, LOW);
Serial.println(" D1608E_R1: OFF");
}
mechExp.updateDigitalOutputs();
delay(1000);
}
/**
Reads Input Register values from the server under specified address.
*/
void readAndPrintRegisterValues(uint8_t slaveId, uint16_t startAddress, uint16_t numRegisters, const char* tempLabel, const char* humLabel, float& temp, float& hum, float hum_calib, float temp_calib) {
Serial.print("Reading input register values SLAVE ID: ");
Serial.print(slaveId);
Serial.println(" ... ");
// Request data from the specified slave ID
if (!ModbusRTUClient.requestFrom(slaveId, INPUT_REGISTERS, startAddress, numRegisters)) {
error++;
Serial.print("failed! ");
Serial.println(ModbusRTUClient.lastError());
return;
}
// Check if enough data is available
if (ModbusRTUClient.available() >= numRegisters) {
uint16_t firstRegister = ModbusRTUClient.read(); //Read temperature
uint16_t secondRegistor = ModbusRTUClient.read(); //Read humidity
// Convert raw values to readable values
float temperature = firstRegister / 10.0; // Scale by 10 if required
float humidity = secondRegistor / 10.0; // Scale by 10 if required
temp = temperature;
hum = humidity;
if (hum > 100) {
hum = hum - 100;
}
hum = hum + hum_calib;
temp = temp + temp_calib;
// Print the converted values
Serial.print(tempLabel);
Serial.print(": ");
Serial.print(temp);
Serial.print(" °C, ");
Serial.print(humLabel);
Serial.print(": ");
Serial.println(hum);
} else {
Serial.println("Insufficient data received!");
}
Serial.println("");
}
The interesting thing is that the issue is only with the slave ID which is called firsi.e., readAndPrintRegisterValues(SLAVE_ID1, START_ADD1, READ_REG1, "Inlet temperature", "Inlet Humidity", temperature1, humidity1, CALIB_H1, CALIB_T1); // Slave ID 1 t which means its not a sensor issue (and yes, both of them work in individual code)
the connection of A and B lines is standard with common ground and separate power sources.
Can someone please figure out what the issue might be?