ESP32-WROOM-DA MODULE and 7 in 1 Soil sensor using RS485 to TTL converter

Hello comm I really need your help for my project. I am trying to test the readings of the soil sensor I bought for our software engineering project. I use this code to test the sensor for the data readings of it on the soil

#define DE 32  // DE connected to GPIO 32
#define RE 33  // RE connected to GPIO 33
#define MODBUS_RX 16 // RX2 for ESP32
#define MODBUS_TX 17 // TX2 for ESP32

void setup() {
  Serial.begin(9600); // For serial monitor
  Serial2.begin(4800, SERIAL_8N1, MODBUS_RX, MODBUS_TX); // RS485 communication with sensor

  pinMode(DE, OUTPUT);
  pinMode(RE, OUTPUT);
  digitalWrite(DE, LOW);  // Start in receive mode
  digitalWrite(RE, LOW);  // Start in receive mode
}

void loop() {
  // Query for multiple parameters
  uint8_t query[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x07, 0x04, 0x08};
  byte receivedData[20]; // Extended buffer for received data

  // Print the sent query
  Serial.print("Sent Query: ");
  for (int i = 0; i < sizeof(query); i++) {
    Serial.print(query[i], HEX);
    Serial.print(" ");
  }
  Serial.println();

  // Set to transmission mode
  // Set to transmission mode
// Set to transmission mode
// Set to transmission mode
digitalWrite(DE, HIGH);  // Enable Driver
digitalWrite(RE, HIGH);  // Disable Receiver
delay(30);  // Ensure mode switch is stable

// Send the query
Serial2.write(query, sizeof(query)); // Send the 8-byte query
delay(35);  // Delay to allow time for the entire query to be transmitted

// Set to receive mode after sending
digitalWrite(DE, LOW);   // Disable Driver
digitalWrite(RE, LOW);   // Enable Receiver
delay(50);  // Short delay to give the sensor time to respond

  // Check and print the received data
  int bytesAvailable = Serial2.available();
  Serial.print("Bytes available: ");
  Serial.println(bytesAvailable);

  if (bytesAvailable > 0) {
    Serial.print("Received Data: ");
    for (int i = 0; i < bytesAvailable && i < 20; i++) { // Limit to 20 bytes
      receivedData[i] = Serial2.read();
      Serial.print(receivedData[i], HEX);
      Serial.print(" ");
    }
    Serial.println();
  } else {
    Serial.println("No response or insufficient data received");
  }

  delay(5000); // Wait 10 seconds before sending the next query
}

now after uploading it this is the result I get

Sent Query: 1 3 0 0 0 7 4 8
Bytes available: 17
Received Data: E 0 0 1 B 0 0 0 3A 0 0 0 0 0 0 AD F1
Sent Query: 1 3 0 0 0 7 4 8
Bytes available: 15
Received Data: 80 1 B 0 0 0 3A 0 0 0 0 0 0 AD F1
Sent Query: 1 3 0 0 0 7 4 8
Bytes available: 15
Received Data: 4 1 B 0 0 0 3A 0 0 0 0 0 0 AD F1

so after that I try to convert the data using this codes

#include <Wire.h>

#define RE 33  // Receiver Enable
#define DE 32  // Driver Enable
#define DI 17  // TX2 for ESP32
#define RO 16  // RX2 for ESP32

const byte H[8] = {0x01, 0x03, 0x00, 0x12, 0x00, 0x01, 0x24, 0x0F};   // Soil Humidity
const byte T[8] = {0x01, 0x03, 0x00, 0x13, 0x00, 0x01, 0x75, 0xCF};   // Soil Temperature
const byte CE[8] = {0x01, 0x03, 0x00, 0x15, 0x00, 0x01, 0x95, 0xCE};   // Soil Conductivity
const byte PH[8] = {0x01, 0x03, 0x00, 0x06, 0x00, 0x01, 0x64, 0x0B};   // Soil PH
const byte N[8] = {0x01, 0x03, 0x00, 0x1E, 0x00, 0x01, 0xE4, 0x0C};    // Soil Nitrogen
const byte P[8] = {0x01, 0x03, 0x00, 0x1F, 0x00, 0x01, 0xB5, 0xCC};    // Soil Phosphorus
const byte K[8] = {0x01, 0x03, 0x00, 0x20, 0x00, 0x01, 0x85, 0xC0};    // Soil Potassium

byte values[9];
float temperature_val = 0.00;
float humidity_val = 0.00;
float PH_val = 0.00;
int CE_val;
byte N_val, P_val, K_val;

void setup() {
  Serial.begin(9600);
  Serial2.begin(4800, SERIAL_8N1, RO, DI); // Use Serial2 for RS485

  pinMode(DE, OUTPUT);
  pinMode(RE, OUTPUT);
  digitalWrite(DE, LOW);
  digitalWrite(RE, LOW);
}

void loop() {
  humidity_val = Collect_Data(H, "Humidity");
  temperature_val = Collect_Data(T, "Temperature");
  CE_val = Collect_Data(CE, "Conductivity");
  N_val = Collect_Data(N, "Nitrogen");
  P_val = Collect_Data(P, "Phosphorus");
  K_val = Collect_Data(K, "Potassium");
  PH_val = Collect_Data(PH, "PH");

  Serial.print("Humidity: "); Serial.println(humidity_val);
  Serial.print("Temperature: "); Serial.println(temperature_val);
  Serial.print("CE: "); Serial.println(CE_val);
  Serial.print("PH: "); Serial.println(PH_val);
  Serial.print("N: "); Serial.println(N_val);
  Serial.print("P: "); Serial.println(P_val);
  Serial.print("K: "); Serial.println(K_val);
  Serial.println("----------------------");
  delay(5000);
}

float Collect_Data(const byte *query, const char *dataLabel) {
  float result = 0.0;
  uint8_t i = 0;
  uint32_t startTime;
  while (Serial2.available()) Serial2.read();  // Clear buffer before new query
  
  // Send the query
  digitalWrite(DE, HIGH);
  digitalWrite(RE, HIGH);
  delay(10);
  Serial2.write(query, 8);
  delay(10);
  digitalWrite(DE, LOW);
  digitalWrite(RE, LOW);
  
  // Collect response
  startTime = millis();
  while (millis() - startTime <= 500) {
    if (Serial2.available() && i < sizeof(values)) {
      values[i++] = Serial2.read();
    }
  }
  
  // Validate response
  if (i >= 5 && values[0] == 0x01 && values[1] == 0x03) {  // Ensure correct address and function code
    result = (values[3] << 8 | values[4]) * 0.1;  // Convert to proper scale
  } else {
    Serial.print("Invalid response for ");
    Serial.println(dataLabel);
  }
  
  return result;
}

now I've got this result

Invalid response for Humidity
Invalid response for Temperature
Invalid response for Conductivity
Invalid response for Nitrogen
Invalid response for Phosphorus
Invalid response for Potassium
Invalid response for PH
Humidity: 0.00
Temperature: 0.00
CE: 0
PH: 0.00
N: 0
P: 0
K: 0


I really don't have an Idea what to do next, this is how my wirings looks like

ESP32              RS485 Module             Soil Sensor
------------------------------------------------------------
17   (TX)   ---->   DI (Data In)         
16  (RX)   <----   RO (Receiver Out)     
32  (DE)   ---->   DE (Direction Enable)  
33  (RE)   ---->   RE (Receive Enable)   
GND       ---->   GND                     Black (GND)
5V        ---->   VCC                     Brown (Power)
               A  <---->  Yellow (RS485 A)
               B  <---->  Blue (RS485 B)

I am stuck to this I just need the values for this then I can finally proceed from the rest of the project please help me I need your guidance I am so new to this, thanks for the future help

Hi, @iverson_89
Welcome to the forum.

Can you post a link to the soil sensor you purchased please.

Can you please post a copy of your circuit, a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.

Thanks.. Tom.... :smiley: :+1: :coffee: :australia:

Hi sorry for the incomplete info
this is the sensor model

Name: Type 485 five-pin multi-element sensor
Model: ZTS-3002-TR-ECTHNPKPH-N01
DC power supply (default): 4.5-30V
Batch number: 2450 | 様: Power supply positive black: power supply negative Yellow: 485A Blue: 485B
Manufacturer: Jinan Zhaoweisheng Electronic Technology Co., Ltd.
Factory site 1st floor, Comprehensive Service Building, No. 2966 Century Avenue, High-tech Zone, Jinan City, Shandong Province

I am connecting the
RO to GPIO16
RE to GPIO 33
DE to GPIO 32
DI to GPIO17

this my pin references

also I am using ESP32 WROOM thankyou

This is a new twist. Let me check the calendar... No, it's not 1st April....

You have an ESP32 WROOM module, which is breadboard compatible. You have plugged that into some kind of adapter PCB, making it breadboard incompatible. Then you have used Dupont cables to connect the whole thing to... a breadboard? :rofl:

1 Like

sorry im so frustrated to this project so much AHHAHAHAHAHAHAAHHAH pleasee help me huhu :rofl::sob::sob:

Sorry. Hi @iverson_89

Thanks for the info;
Here is the manual for the sensor;
Five-pin soil transmitter (Type 485).pdf (419.9 KB)

Tom.. Tom.... :smiley: :+1: :coffee: :australia:

I have many components that I need to integrate to the controller thats why I do it :<

thank you I will read it first

That adapter PCB adds nothing to your project as far as I can see. It just makes your prototype more complex and fragile and increases the chance of wiring errors.

Unplug the ESP32 module from the adapter and plug it directly onto the breadboard. Make sure the 2 breadboards are clipped together correctly. ESP32 modules are wide, so you may need to plug it in across the two breadboards.

Your sensor has an RS485 interface? I don't see an RS485-to-serial adapter for the ESP. Is an ESP32 directly compatible with RS485 signals?

1 Like

I research and it say this

No, the ESP32 is not directly compatible with RS485 signals because the ESP32 operates on TTL logic levels (0–3.3V), while RS485 uses differential signaling which involves a pair of wires (A and B) with voltage differences that can be much higher than 3.3V.
To interface an ESP32 with RS485, you need an RS485 transceiver module like the MAX485 or SN75176. These modules:

  • Convert the differential RS485 signals to TTL levels that the ESP32 can understand.
  • Handle the half-duplex communication required by RS485 (i.e., switching between transmitting and receiving on the same wire pair).

Typical Wiring:

  • Connect the DI (Data In) pin of the transceiver to the TX pin of the ESP32.
  • Connect the RO (Receiver Out) pin to the RX pin of the ESP32.
  • Connect DE (Driver Enable) and RE (Receiver Enable) together and control them using a GPIO pin on the ESP32 to switch between transmitting and receiving modes.
  • Connect the A and B lines to the RS485 bus.

so I just followed the wiring

I'm sorry, I thought the component on your breadboard was the sensor, but now I see that it is your RS485 to serial adapter, and your sensor is not in the pictures.

Please follow advice from @TomGeorge in post #2.

1 Like

Integrate them later. For now connect your Esp32 directly to Rs485.
Your problem smells like bad contact on rx line.

1 Like

this is the sensor im sorry for lack of info im getting cultured shock from what I'm doing but I really appreciate your help guys thankyou so much

noted sir im doing it thankyou :smiling_face_with_tear:

Now I'm done doing the breadboarding


i did try this code

#define DE 32  // DE connected to GPIO 32
#define RE 33  // RE connected to GPIO 33
#define MODBUS_RX 16 // RX2 for ESP32
#define MODBUS_TX 17 // TX2 for ESP32

void setup() {
  Serial.begin(9600); // For serial monitor
  Serial2.begin(4800, SERIAL_8N1, MODBUS_RX, MODBUS_TX); // RS485 communication with sensor

  pinMode(DE, OUTPUT);
  pinMode(RE, OUTPUT);
  digitalWrite(DE, LOW);  // Start in receive mode
  digitalWrite(RE, LOW);  // Start in receive mode
}

void loop() {
  // Query for multiple parameters
  uint8_t query[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x07, 0x04, 0x08};
  byte receivedData[20]; // Extended buffer for received data

  // Print the sent query
  Serial.print("Sent Query: ");
  for (int i = 0; i < sizeof(query); i++) {
    Serial.print(query[i], HEX);
    Serial.print(" ");
  }
  Serial.println();

  // Set to transmission mode
  // Set to transmission mode
// Set to transmission mode
// Set to transmission mode
digitalWrite(DE, HIGH);  // Enable Driver
digitalWrite(RE, HIGH);  // Disable Receiver
delay(30);  // Ensure mode switch is stable

// Send the query
Serial2.write(query, sizeof(query)); // Send the 8-byte query
delay(35);  // Delay to allow time for the entire query to be transmitted

// Set to receive mode after sending
digitalWrite(DE, LOW);   // Disable Driver
digitalWrite(RE, LOW);   // Enable Receiver
delay(50);  // Short delay to give the sensor time to respond

  // Check and print the received data
  int bytesAvailable = Serial2.available();
  Serial.print("Bytes available: ");
  Serial.println(bytesAvailable);

  if (bytesAvailable > 0) {
    Serial.print("Received Data: ");
    for (int i = 0; i < bytesAvailable && i < 20; i++) { // Limit to 20 bytes
      receivedData[i] = Serial2.read();
      Serial.print(receivedData[i], HEX);
      Serial.print(" ");
    }
    Serial.println();
  } else {
    Serial.println("No response or insufficient data received");
  }

  delay(5000); // Wait 10 seconds before sending the next query
}

and this is the result i get

Sent Query: 1 3 0 0 0 7 4 8
Bytes available: 16
Received Data: 8 1B 1 B 0 6B 0 39 0 0 0 8 0 0 E0 1A
Sent Query: 1 3 0 0 0 7 4 8
Bytes available: 14
Received Data: 51 B 0 6B 0 39 0 0 0 8 0 0 F1 D6
Sent Query: 1 3 0 0 0 7 4 8
Bytes available: 13
Received Data: 40 21 6B 0 39 0 0 0 8 0 0 E5 D9

but based on the result the valid response should start with 0x01 (slave address) and 0x03 (function code).

For the query {0x01, 0x03, 0x00, 0x00, 0x00, 0x07, 0x04, 0x08}, the expected response length should be:

  • 5 bytes header (Address, Function Code, Data Length, CRC) +
  • Data for 7 registers (2 bytes each) = 19 bytes.

If the response length is shorter than 19 bytes, it is likely incomplete.

I'm really lost

this is how I connect thee sensor do I need an external power or the 5v from the controller is enough since the voltage requirement of the sensor is 4.5v - 30v


You should try to power your sensor with higher voltage.
Also the fact that you are powering rs485 from Esp32 5V pin causes serial communication voltage levels incompatible between each other (and can damage Esp). I would power 485 from 3.3V pin (even if it's below Max485 specs).

Exactly, but it's also corrupted, so the length doesn't matter at the moment.

1 Like

this is the converter i bought
RS485 to TTL Serial Level Signal Converter Module MAX485

Yes, but Esp is 3.3V board.
If you want to wire it correctly, you need level shifters on serial lines.
But I have been using many of those boards at 3.3V supply and I never had a problem.

And may I suggest; don't use same color of wire for VCC and GND wiring. It's like digging blood from the nose. Sooner or later you fry something (if didn't already).

1 Like

[quote="kmin, post:21, topic:1353921, full:true"]

Also, to help you for debugging change request like this:
0x01, 0x03, 0x07, 0xD0, 0x00, 0x01, 0x84, 0x87
so the response will be known and doesn't change every request.
It should respond: 01, 03, 02, 00, 01, 79, 84 so you can see which part is corrupted.

1 Like