Reading XY-MD02 Temperature and Humidity Data from RS485 using ESP32

Hello everyone, i got this code to read the temperature and humidity data from XY-MD02 sensor but i got this reply back ���W��«�U����, i try to solve the problem by changing the byte command to suit the XY-MD02 datasheet but it's just not working and I'm at my wits end cause I rarely use Arduino and my boss ask me to do this project so if you can kindly give a solution for my trouble it'll be very much appreciated.

here's the code i used

#include <WiFi.h>
#include <WebServer.h>
#include <SoftwareSerial.h>

const char* ssid = "WIRA_UTAMA";
const char* password = "bandung2019";

#define RS485_TX_PIN  27 // Define TX pin of RS485 to ESP32
#define RS485_RX_PIN  26 // Define RX pin of RS485 to ESP32
#define RS485_TRANSCEIVER_PIN 14 // Define transceiver control pin of RS485 to ESP32

WebServer server(80);
SoftwareSerial rs485(RS485_RX_PIN, RS485_TX_PIN); // Define SoftwareSerial object for RS485 communication

const unsigned long RS485_TIMEOUT = 1000; // Timeout for RS485 communication in milliseconds

// Command to request temperature data
byte tempCommand[] = {0x01, 0x04, 0x00, 0x01, 0x00, 0x01, 0x60, 0x0A}; 

// Command to request humidity data
byte humCommand[] = {0x01, 0x04, 0x00, 0x02, 0x00, 0x01, 0x90, 0x0A}; 

void setup() {
  Serial.begin(115200);
  
  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  
  // Print ESP32 IP address
  Serial.println(WiFi.localIP());

  // Initialize RS485 communication
  rs485.begin(9600);
  pinMode(RS485_TRANSCEIVER_PIN, OUTPUT); // Set transceiver control pin as output

  // Route for root / web page
  server.on("/", HTTP_GET, handleRoot);
  
  // Start server
  server.begin();
}

void loop() {
  server.handleClient();
}

void handleRoot() {
  // Read temperature and humidity data
  float temperature, humidity;
  bool success = true;
  if (!readTemperature(tempCommand, sizeof(tempCommand), temperature)) {
    success = false;
  }
  if (!readHumidity(humCommand, sizeof(humCommand), humidity)) {
    success = false;
  }

  if (success) {
    String page = "<!DOCTYPE html><html><head><title>Temperature and Humidity</title></head><body>";
    page += "<h1>Temperature and Humidity</h1>";
    page += "<p>Temperature: " + String(temperature) + " °C</p>";
    page += "<p>Humidity: " + String(humidity) + " %</p>";
    page += "</body></html>";
    server.send(200, "text/html", page);
  } else {
    server.send(500, "text/plain", "Failed to read temperature and humidity data");
  }
}

bool readTemperature(byte command[], int length, float& temperature) {
  return readData(command, length, 3, temperature);
}

bool readHumidity(byte command[], int length, float& humidity) {
  return readData(command, length, 3, humidity);
}

bool readData(byte command[], int length, int dataIndex, float& data) {
  // Send command to request data
  sendCommand(command, length);

  // Wait for response
  unsigned long startTime = millis();
  while (!rs485.available()) {
    if (millis() - startTime > RS485_TIMEOUT) {
      return false; // Timeout occurred
    }
  }

  // Read response
  byte response[7]; // Response packet length is 9 bytes
  for (int i = 0; i < 7; i++) {
    response[i] = rs485.read();
    Serial.print(response[i], HEX); // Print each byte of the response
    Serial.print(" ");
  }
  Serial.println(); // Print newline after printing the entire response

  // Check response integrity
  if (response[0] != command[0] || response[1] != command[1] || response[2] != command[2] || response[3] != command[3] || response[4] != command[4]) {
    return false; // Invalid response
  }

  // Calculate temperature or humidity
  int value = response[dataIndex] << 7 | response[dataIndex + 1];
  data = value / 10.0;

  return true; // Data read successfully
}

void sendCommand(byte command[], int length) {
  digitalWrite(RS485_TRANSCEIVER_PIN, HIGH); // Set transceiver to transmit mode
  rs485.write(command, length);
  digitalWrite(RS485_TRANSCEIVER_PIN, LOW); // Set transceiver to receive mode
}

Thank you

I don't think your readData routine is coded correctly.

It waits for the first byte of the response to be received (or it times out). Once the first byte has been received, the code assumes that all the other bytes of the response are instantly available and reads them in.

You should check that a byte has been received before reading the software serial port.

I would also check to see where those unprintable characters are coming from in your code. The serial port read function usually (I think from memory) returns -1 or 0xFF when there is no data available. If that is correct, then your code should have output a bunch of FFs.

I don't think your check for response integrity is correct. I'm guessing from the commands that your sensor is a modbus device? If it is, then I would suggest you use a modbus library that will handle the Comms for you.

Also, since your sensor is offering simple UART protocol, why don't you use that instead of Modbus?
Command "READ" should give you both h and t.
Is your RS485-ttl-converter wired correctly?