I want to combine the code for an RS485 Modbus RTU soil sensor with single relay control using Modbus RTU. The concept is that when the soil humidity is above 30 percent, the relay remains inactive; if the humidity is below 30 percent, the relay activates.
The main device I'm using is an ESP32 connected to a UART TTL to RS485 Two-way Converter Module.
When I connect only the RS485 Modbus RTU soil sensor, the serial monitor can display the sensor readings.
Here’s the code:
#include <ModbusMaster.h>
ModbusMaster THCPH;
char buff[10];
void setup() {
Serial.begin(9600);
Serial.println("Starting..");
Serial2.begin(9600, SERIAL_8N1, 16, 17);
THCPH.begin(2, Serial2);
}
void loop() {
Serial.println("Read 4in1 sensor...");
uint8_t result;
result = THCPH.readHoldingRegisters(0x0000, 1);
if (result == THCPH.ku8MBSuccess)
{
sprintf(buff, "%.1f", THCPH.getResponseBuffer(0x00) / 10.0f);
Serial.print("Humidity = ");
Serial.println(buff);
}
delay(100);
result = THCPH.readHoldingRegisters(0x0001, 1);
if (result == THCPH.ku8MBSuccess)
{
sprintf(buff, "%.1f", THCPH.getResponseBuffer(0x00) / 10.0f);
Serial.print("Temperature = ");
Serial.println(buff);
}
delay(100);
result = THCPH.readHoldingRegisters(0x0002, 1);
if (result == THCPH.ku8MBSuccess)
{
sprintf(buff, "%.1f", THCPH.getResponseBuffer(0x00) / 10.0f);
Serial.print("Conductivity = ");
Serial.println(buff);
}
delay(100);
result = THCPH.readHoldingRegisters(0x0003, 1);
if (result == THCPH.ku8MBSuccess)
{
sprintf(buff, "%.1f", THCPH.getResponseBuffer(0x00) / 10.0f);
Serial.print("pH = ");
Serial.println(buff);
}
Serial.println("Done");
delay(1000);
}
When only using the single relay, it can activate and deactivate properly.
Here’s the code:
#include <HardwareSerial.h>
// Initialize the serial port for RS485
HardwareSerial mySerial(1);
uint8_t Relay0_ON[8] = {0x01, 0x05, 0x00, 0x00, 0xFF, 0x00, 0x8C, 0x3A};
uint8_t Relay0_OFF[8] = {0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0xCD, 0xCA};
void setup() {
// Start serial communication
Serial.begin(9600);
mySerial.begin(9600, SERIAL_8N1, 16, 17); // U2RXD pin 16, U2TXD pin 17
// Wait for the serial to connect
while (!Serial) {
; // Wait until Serial is connected
}
Serial.println("Modbus RTU Relay Control with ESP32");
}
void loop() {
// Open the valve by activating relay 0 (red wire)
Serial.println("Opening valve...");
sendCommand(Relay0_ON, sizeof(Relay0_ON));
delay(1000); // Wait for 3 seconds
Serial.println("Closing valve...");
sendCommand(Relay0_OFF, sizeof(Relay0_OFF));
// Wait a bit before closing the valve
delay(1000); // Wait for 1 second
}
// Function to send commands to the relay
void sendCommand(uint8_t *cmd, size_t length) {
mySerial.write(cmd, length);
mySerial.flush();
Serial.print("Command sent: ");
for (size_t i = 0; i < length; i++) {
Serial.print(cmd[i], HEX);
Serial.print(" ");
}
Serial.println();
}
I would like to combine these two codes so that they work according to the concept. I’ve tried modifying or combining the code several times, but I keep encountering errors.
here is the concept I want:
Here’s the soil sensor manual:
THCPH-S (5pin probe) manual_V1.3
Here’s the Modbus RTU relay manual:
Protocol Manual of Control Modbus RTU single relay
Thank you.





