How to Read Soil EC, Temperature and Humidity with Arduino and PR-3000-ECTH-N01 Sensor
How to Read Soil EC, Temperature and Humidity with Arduino and PR-3000-ECTH-N01 Sensor
This guide covers how to use the PR-3000-ECTH-N01 soil sensor with an Arduino UNO. The sensor measures three values in a single probe: Electrical Conductivity (EC), temperature, and soil moisture. It communicates over RS485 using the Modbus RTU protocol, which is stable and well-suited for outdoor agricultural environments.
Key Features of the PR-3000-ECTH-N01
- 3-in-1 measurement: Moisture, temperature, and EC from one probe
- RS485 protocol: Supports up to 1,200 meters cable length, immune to noise in field conditions
- Modbus RTU: Industrial standard, registers are straightforward to read
- 12V DC power: Powers the entire probe without needing multiple voltage sources
Why Measure EC Alongside Temperature
Electrical Conductivity (EC) in soil indicates the amount of dissolved salts or fertilizer concentration. However, EC is directly influenced by temperature. When temperature rises, EC rises too, even if the actual salt content in the soil has not changed. This sensor solves that problem by reporting temperature alongside EC, allowing you to correct EC values based on actual field conditions.
Required Components
| Component | Quantity | Notes |
|---|---|---|
| Arduino UNO R3 | 1 | |
| MAX485 Module RS485 to TTL | 1 | Signal converter |
| PR-3000-ECTH-N01 Soil Sensor | 1 | Main probe |
| Power Adapter 12V DC | 1 | Sensor power supply |
| OLED 128x64 I2C Display | 1 | Optional readout |
| Breadboard MB-102 | 1 | Circuit assembly |
| Jumper Wires Set | - | M-M, M-F, F-F |
Wiring Diagram: Arduino with PR-3000-ECTH-N01
The circuit has three main sections: power supply, RS485 communication, and optional display output.
Part 1: MAX485 Connected to Arduino UNO
| Arduino UNO | MAX485 Module | Role |
|---|---|---|
| 5V | VCC | Power |
| GND | GND | Ground |
| Pin 2 (RX) | RO | Receive Output |
| Pin 3 (TX) | DI | Driver Input |
| Pin 7 | DE | Driver Enable |
| Pin 8 | RE | Receiver Enable |
Part 2: PR-3000-ECTH-N01 Connected to MAX485 and Power
| Sensor Wire | Connection | Notes |
|---|---|---|
| Blue Wire (B) | MAX485 B | RS485 B line |
| Yellow Wire (A) | MAX485 A | RS485 A line |
| Brown Wire | 12V DC (+) | Positive power |
| Black Wire | 12V DC (-) | Ground |
Critical: The GND of Arduino, MAX485, and the 12V power supply must share a common ground. Without a shared ground, RS485 signals cannot be read correctly.
Part 3: OLED Display (Optional)
| Arduino UNO | OLED I2C | Notes |
|---|---|---|
| 5V | VCC | |
| GND | GND | |
| A4 | SDA | |
| A5 | SCL |
Modbus Registers of PR-3000-ECTH-N01
This sensor uses Modbus RTU Function Code 0x04 (Read Input Registers). Three registers are available:
| Register | Data | Unit |
|---|---|---|
| 0x0000 | Soil Moisture | % |
| 0x0001 | Temperature | °C |
| 0x0002 | Electrical Conductivity (EC) | mS/cm |
Installing Required Libraries
- Download the library bundle from MediaFire — OLED and SoftwareSerial Libraries
- Extract the archive with WinRAR or WinZip
- Copy the library folders into
Documents/Arduino/libraries/ - Restart Arduino IDE
Arduino Code: Reading PR-3000-ECTH-N01 via Modbus RTU
#include <SoftwareSerial.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SENSOR_SERIAL_RX 2
#define SENSOR_SERIAL_TX 3
#define MAX485_DE_RE 7
#define MAX485_RE 8
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
SoftwareSerial sensorSerial(SENSOR_SERIAL_RX, SENSOR_SERIAL_TX);
// Modbus RTU Function Code 0x04 (Read Input Registers)
byte readCommand[8] = {
0x01, // Slave Address
0x04, // Function Code: Read Input Registers
0x00, 0x00, // Starting Address: 0x0000 (Moisture)
0x00, 0x03, // Quantity: 3 registers (moisture, temp, EC)
0x00, 0x00 // CRC (calculated below)
};
void setup() {
Serial.begin(9600);
sensorSerial.begin(9600);
pinMode(MAX485_DE_RE, OUTPUT);
pinMode(MAX485_RE, OUTPUT);
digitalWrite(MAX485_DE_RE, LOW); // Receive mode
digitalWrite(MAX485_RE, LOW);
// Calculate CRC16 for Modbus command
unsigned int crc = modbusCrc16(readCommand, 6);
readCommand[6] = lowByte(crc);
readCommand[7] = highByte(crc);
// Initialize OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("OLED init failed"));
for (;;);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.display();
}
void loop() {
// Send read command to sensor
digitalWrite(MAX485_DE_RE, HIGH);
digitalWrite(MAX485_RE, HIGH);
sensorSerial.write(readCommand, 8);
sensorSerial.flush();
digitalWrite(MAX485_DE_RE, LOW);
digitalWrite(MAX485_RE, LOW);
// Wait for response (expected: 11 bytes)
delay(100);
byte response[20];
int bytesReceived = 0;
unsigned long startTime = millis();
while (sensorSerial.available() && bytesReceived < 20) {
if (millis() - startTime > 1000) break;
response[bytesReceived++] = sensorSerial.read();
}
if (bytesReceived >= 9) {
// Response format: [addr][func][bytecount][reg1_H][reg1_L][reg2_H][reg2_L][reg3_H][reg3_L][CRC_L][CRC_H]
int moisture = (response[3] << 8) | response[4];
int temperature = (response[5] << 8) | response[6];
int ecRaw = (response[7] << 8) | response[8];
float tempC = temperature / 10.0;
float ecValue = ecRaw / 1000.0; // Convert to mS/cm
// Print to Serial Monitor
Serial.print("Moisture: ");
Serial.print(moisture);
Serial.print("% | Temp: ");
Serial.print(tempC);
Serial.print("C | EC: ");
Serial.print(ecValue, 3);
Serial.println(" mS/cm");
// Display on OLED
display.clearDisplay();
display.setCursor(0, 0);
display.print("Moisture: ");
display.print(moisture);
display.println("%");
display.print("Temp: ");
display.print(tempC, 1);
display.println("C");
display.print("EC: ");
display.print(ecValue, 3);
display.println(" mS/cm");
display.display();
}
delay(1000);
}
// CRC16 calculation for Modbus RTU
unsigned int modbusCrc16(byte *data, int length) {
unsigned int crc = 0xFFFF;
for (int i = 0; i < length; i++) {
crc ^= data[i];
for (int j = 0; j < 8; j++) {
if (crc & 0x0001) {
crc = (crc >> 1) ^ 0xA001;
} else {
crc >>= 1;
}
}
}
return crc;
}
How to Use This Code
- Wire the circuit as shown in the diagram above
- Open Arduino IDE, paste the code, and select Board → Arduino UNO
- Select the correct Port and click Upload
- Open Serial Monitor and set Baud Rate to 9600
- Insert the probe into soil and observe the readings
Note: If readings show 0 or no response, check that GND is shared across Arduino, MAX485, and the 12V power supply. Also verify that the A (yellow) and B (blue) wires are connected to the correct terminals on the MAX485 module.
Reference Video
Soil EC Values and Practical Field Use
Soil EC is a critical indicator for crop management:
| EC Value (mS/cm) | Interpretation | Action |
|---|---|---|
| 0 – 1.0 | Nutrient-poor soil | Add fertilizer |
| 1.0 – 3.0 | Normal for agriculture | Maintain current condition |
| 3.0 – 4.0 | Moderately high | Reduce fertilizer application |
| > 4.0 | Excessively high — salt risk | Cut fertilizer, increase irrigation |
Summary
The PR-3000-ECTH-N01 is a practical sensor for smart agriculture systems, combining EC, temperature, and moisture in one probe. Communication happens over RS485 using standard Modbus RTU, making the code relatively straightforward to write. The most important wiring detail is establishing a common ground across the entire system and providing 12V DC power to the sensor separately from the 5V logic used by Arduino.
อยากทำโปรเจคแบบนี้?
รับทำโปรเจค Arduino / IoT จบงานไว ส่งงานครบ พร้อมสอน
If you need Arduino project service or urgent IoT development, see full service details on the home page
จ้างทำโปรเจคเลย