Soil Moisture Sensor điện trở là cảm biến rẻ nhất để đo độ ẩm đất — chỉ 2 điện cực kim loại cắm xuống đất, đo điện trở giữa chúng. Giản dị nhưng có những vấn đề quan trọng cần hiểu: tại sao điện cực bị ăn mòn, module LM393 dùng như thế nào, và cách hiệu chỉnh đúng để có kết quả ổn định.
Nguyên Lý Hoạt Động
1. Đo Độ Dẫn Điện Của Đất (Soil Electrical Conductivity)
Đất khô là chất cách điện kém — điện trở rất cao (hàng MΩ). Đất ướt dẫn điện tốt hơn — điện trở thấp (hàng kΩ đến trăm kΩ).
Tại sao đất ướt dẫn điện?
Nước thuần túy (H₂O) không dẫn điện tốt. Nhưng đất tự nhiên luôn chứa ion khoáng hòa tan: Ca²⁺, Mg²⁺, K⁺, Na⁺, NO₃⁻, Cl⁻. Các ion này là điện tích tự do trong dung dịch đất → dẫn điện.
Nguyên lý đo:
Đất (điện trở R_soil)
Điện cực A ────┤~~~~~~~~~~~~~~~~~~├──── Điện cực B
↑ ↑
Cấp nguồn Đo điện áp
R_soil cao (đất khô) → V đo cao (gần VCC)
R_soil thấp (đất ướt) → V đo thấp (gần GND)
Cách module đo thực tế:
Module dùng mạch voltage divider (cầu phân áp):
VCC
│
R_cố_định (trên module, thường 10kΩ)
│
├──── Chân AOUT (đọc điện áp)
│
R_soil (điện trở đất — thay đổi)
│
GND
Điện áp AOUT = VCC × Rsoil / (Rcốđịnh + Rsoil)
- Đất ướt → R_soil nhỏ → AOUT thấp → ADC đọc giá trị nhỏ
- Đất khô → R_soil lớn → AOUT cao → ADC đọc giá trị lớn
Lưu ý ngược đầu: ADC nhỏ = đất ướt, ADC lớn = đất khô. Nhiều người bị nhầm điều này.
2. Module LM393 Comparator — Ngõ Ra Digital
Ngoài chân AOUT (analog), module còn có chân DOUT (digital). Đây là ngõ ra của LM393 — một op-amp comparator.
AOUT ─→ LM393 (+IN)
LM393 (-IN) ─→ Triết áp (ngưỡng điều chỉnh)
LM393 OUT ─→ DOUT
Khi đất khô: AOUT > ngưỡng → DOUT = HIGH
Khi đất ướt: AOUT < ngưỡng → DOUT = LOW
Triết áp trên module cho phép điều chỉnh ngưỡng: đất cần ướt đến mức nào thì DOUT chuyển LOW.
DOUT dùng khi: Chỉ cần biết “đủ ẩm” hay “cần tưới” mà không quan tâm mức độ cụ thể. AOUT dùng khi: Muốn biết chính xác mức độ ẩm (ứng dụng tưới cây thông minh).
3. Vấn Đề Điện Phân — Ăn Mòn Điện Cực
Đây là nhược điểm lớn nhất của sensor điện trở.
Khi dòng điện DC chạy qua đất → điện phân: ion trong đất di chuyển về phía điện cực tương ứng → tích tụ → ăn mòn kim loại điện cực.
Điện cực (+): Kim loại bị oxi hóa: Fe → Fe²⁺ + 2e⁻
Điện cực (-): Ion H⁺ bị khử: 2H⁺ + 2e⁻ → H₂↑
Kết quả sau vài tuần: Điện cực gỉ, bong tróc → điện trở thay đổi → đọc sai
Giải pháp thực tế:
- Cấp nguồn xung thay vì liên tục: bật sensor vài giây để đo, rồi tắt → giảm điện phân 99%
- Dùng GPIO cấp nguồn cho sensor: chỉ set HIGH khi cần đo
- Sensor điện dung (capacitive) thay thế: không dùng dòng điện DC qua đất nên không bị ăn mòn
Thông Số Kỹ Thuật (Module Thông Dụng)
| Thông số | Giá trị |
|---|---|
| Điện áp hoạt động | 3.3V – 5V |
| Dòng tiêu thụ | ~20–35mA (khi bật) |
| Ngõ ra analog (AOUT) | 0V – VCC |
| Ngõ ra digital (DOUT) | 0V / VCC (qua LM393) |
| Chiều dài điện cực | ~60mm |
| Thời gian đáp ứng | <1 giây |
| Tuổi thọ điện cực | Vài tuần (nếu cấp điện liên tục) → nhiều tháng (nếu dùng xung) |
Sensor điện dung thay thế (Capacitive Soil Moisture v1.2/v2.0):
| Điện trở | Điện dung | |
|---|---|---|
| Nguyên lý | Đo điện trở đất | Đo điện dung tụ xuyên đất |
| Ăn mòn | Có (DC electrolysis) | Không (không dòng qua đất) |
| Giá | Rẻ hơn | Đắt hơn ~2-3× |
| Ổn định | Kém hơn | Tốt hơn |
| Khuyến nghị | Thử nghiệm ngắn hạn | Ứng dụng thực tế dài hạn |
Sơ Đồ Chân (Pinout)
Module Soil Moisture (loại phổ biến nhất)
┌──────────────────────┐
│ ┌────────────────┐ │
│ │ LM393 │ │
│ │ Comparator │ │
│ └────────────────┘ │
│ ┌────┐ │
│ │[O] │← Triết áp │
│ └────┘ │
└──────────────────────┘
VCC GND DOUT AOUT
│ │ │ │
| Chân | Tên | Chức năng |
|---|---|---|
| VCC | VCC | Nguồn 3.3V hoặc 5V |
| GND | GND | Đất |
| DOUT | D0 | Digital output (HIGH/LOW, điều chỉnh bằng triết áp) |
| AOUT | A0 | Analog output (điện áp tỷ lệ với độ ẩm) |
Đầu Cắm Đất (Probe/Fork)
Nối với module qua dây, cắm thẳng xuống đất. Không cần quan tâm cực tính (2 điện cực đối xứng).
Các Biến Thể Cùng Loại
| Loại | Mô tả | Ưu điểm | Nhược điểm |
|---|---|---|---|
| Soil Moisture Resistive | 2 điện cực, LM393 | Rẻ, đơn giản | Ăn mòn nhanh |
| Capacitive v1.2 | NE555 oscillator | Không ăn mòn | Cần calibration |
| Capacitive v2.0 | STM32F030, 12-bit ADC | Chính xác cao | Giá cao hơn |
| YL-69 | Như resistive, PCB riêng | Rẻ nhất | Kém bền nhất |
| FC-28 | Module + probe tách rời | Dễ thay probe | Như YL-69 |
Kết Nối Phần Cứng
Kết Nối với ESP32 DevKit V1
ESP32 lấy mẫu ADC 12-bit (0–4095). ADC1 hoạt động tốt khi WiFi bật.
ESP32 DevKit V1 Soil Moisture Module
───────────────────── ─────────────────────
GPIO26 (Digital) ──────→ VCC ← Cấp nguồn qua GPIO → tắt khi không đo
GND ──────────────────→ GND
GPIO32 (ADC1_CH4) ─────→ AOUT ← Đọc analog
GPIO25 (Digital) ─────→ DOUT ← Đọc digital (tùy chọn)
Tại sao cấp nguồn qua GPIO26: Bật GPIO26 HIGH khi cần đo → giảm điện phân. GPIO26 là OUTPUT thường, không phải ADC pin.
GPIO32 cho AOUT: ADC1 (GPIO32–39) hoạt động ổn khi WiFi bật. Không dùng ADC2 (GPIO0,2,4,12-15,25-27) — bị block khi WiFi active.
Kết Nối với Arduino Uno
Arduino Uno Soil Moisture Module
───────────────────── ─────────────────────
Pin 7 (Digital) ───────→ VCC ← Cấp nguồn xung qua GPIO
GND ──────────────────→ GND
A0 (Analog) ───────────→ AOUT
Pin 6 (Digital) ───────→ DOUT ← Tùy chọn
Arduino Uno ADC: 10-bit (0–1023), điện áp tham chiếu 5V (hoặc 3.3V nếu cấp sensor 3.3V).
Code Arduino IDE
Bước 1 — Hiệu Chỉnh (Calibration) Trước Khi Dùng
Hiệu chỉnh 2 điểm là bắt buộc để có kết quả ý nghĩa:
- Cắm sensor vào không khí (khô hoàn toàn) → ghi giá trị ADC raw → đây là
DRY_VALUE - Nhúng sensor vào nước (ướt hoàn toàn) → ghi giá trị ADC raw → đây là
WET_VALUE - Dùng 2 giá trị này để map sang % độ ẩm
Hai giá trị này khác nhau giữa từng sensor và từng loại đất. Phải đo cho từng thiết lập cụ thể.
Code Hiệu Chỉnh — Arduino Uno
/*
* Soil Moisture Sensor — Hiệu chỉnh 2 điểm
* Board: Arduino Uno
* Dùng code này trước để tìm DRY_VALUE và WET_VALUE cho sensor của bạn
* Kết nối: VCC→Pin7, GND→GND, AOUT→A0
*/
const int POWER_PIN = 7; // Cấp nguồn cho sensor qua pin này
const int SENSOR_PIN = A0; // Đọc giá trị analog
void setup() {
Serial.begin(9600);
pinMode(POWER_PIN, OUTPUT);
digitalWrite(POWER_PIN, LOW); // Tắt nguồn ban đầu
Serial.println("=== Soil Moisture Calibration ===");
Serial.println("Bước 1: Cắm sensor vào KHÔNG KHÍ (không chạm đất/nước)");
Serial.println("Chờ 5 giây...");
delay(5000);
}
void loop() {
// Bật nguồn sensor
digitalWrite(POWER_PIN, HIGH);
delay(100); // Chờ ổn định điện áp
// Đọc 10 lần lấy trung bình
int total = 0;
for (int i = 0; i < 10; i++) {
total += analogRead(SENSOR_PIN);
delay(10);
}
int avgValue = total / 10;
// Tắt nguồn (giảm ăn mòn)
digitalWrite(POWER_PIN, LOW);
Serial.print("ADC raw = ");
Serial.print(avgValue);
Serial.println(" | Ghi lại giá trị này");
Serial.println(" → Không khí: là DRY_VALUE");
Serial.println(" → Trong nước: là WET_VALUE");
delay(3000);
}
Code Đo Độ Ẩm + Tưới Tự Động — Arduino Uno
/*
* Soil Moisture Sensor — Đo độ ẩm và điều khiển tưới cây
* Board: Arduino Uno
* Library: Không cần
* Kết nối: VCC→Pin7, GND→GND, AOUT→A0, (Relay IN→Pin8)
*
* QUAN TRỌNG: Chạy code calibration trước, điền DRY_VALUE và WET_VALUE bên dưới
*/
// Giá trị hiệu chỉnh — thay bằng giá trị thực đo được
// Arduino Uno ADC 10-bit: giá trị từ 0 đến 1023
const int DRY_VALUE = 700; // ADC khi sensor trong không khí (khô)
const int WET_VALUE = 250; // ADC khi sensor trong nước (ướt nhất)
// Ngưỡng tưới: tưới khi độ ẩm dưới 30%, dừng khi đạt 60%
const int WATER_THRESHOLD_LOW = 30; // % — bắt đầu tưới
const int WATER_THRESHOLD_HIGH = 60; // % — dừng tưới
const int POWER_PIN = 7; // Cấp nguồn sensor
const int SENSOR_PIN = A0;
const int RELAY_PIN = 8; // Relay điều khiển máy bơm (LOW = bật với relay active LOW)
// Nếu không có relay: comment bỏ phần relay
bool isWatering = false; // Trạng thái đang tưới
void setup() {
Serial.begin(9600);
pinMode(POWER_PIN, OUTPUT);
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(POWER_PIN, LOW);
digitalWrite(RELAY_PIN, HIGH); // Relay active LOW: HIGH = tắt máy bơm
Serial.println("=== Soil Moisture Monitor - Arduino Uno ===");
}
// Đọc độ ẩm, trả về % (0-100)
int readMoisture() {
digitalWrite(POWER_PIN, HIGH);
delay(150); // Chờ ổn định — quan trọng!
// Đọc 5 lần lấy trung bình
int total = 0;
for (int i = 0; i < 5; i++) {
total += analogRead(SENSOR_PIN);
delay(20);
}
int raw = total / 5;
digitalWrite(POWER_PIN, LOW); // Tắt nguồn ngay sau khi đo
// Map ADC raw sang % độ ẩm
// DRY_VALUE → 0%, WET_VALUE → 100%
// constrain() đảm bảo kết quả trong 0-100
int moisture = map(raw, DRY_VALUE, WET_VALUE, 0, 100);
return constrain(moisture, 0, 100);
}
void loop() {
int moisture = readMoisture();
Serial.print("Độ ẩm đất: ");
Serial.print(moisture);
Serial.print("% | Trạng thái: ");
// Logic tưới có hysteresis: tránh bật/tắt liên tục
if (!isWatering && moisture < WATER_THRESHOLD_LOW) {
// Đất khô → bắt đầu tưới
isWatering = true;
digitalWrite(RELAY_PIN, LOW); // Bật máy bơm (relay active LOW)
Serial.println("TƯỚI BẮT ĐẦU");
} else if (isWatering && moisture >= WATER_THRESHOLD_HIGH) {
// Đủ ẩm → dừng tưới
isWatering = false;
digitalWrite(RELAY_PIN, HIGH); // Tắt máy bơm
Serial.println("TƯỚI DỪNG");
} else {
Serial.println(isWatering ? "Đang tưới..." : "Bình thường");
}
delay(10000); // Đo mỗi 10 giây — phù hợp cho tưới cây
}
Code Đo Độ Ẩm + Tưới Tự Động — ESP32
/*
* Soil Moisture Sensor — Đo độ ẩm và điều khiển tưới cây
* Board: ESP32 DevKit V1
* Kết nối:
* GPIO26 → VCC sensor (cấp nguồn xung qua GPIO)
* GPIO32 (ADC1_CH4) → AOUT sensor
* GPIO27 → Relay IN
*
* ESP32 ADC 12-bit: giá trị 0-4095 (thay vì 0-1023 của Arduino Uno)
*/
// Hiệu chỉnh cho ESP32 — ADC 12-bit, thường:
// Không khí: ~3200-3600 (gần VCC 3.3V)
// Trong nước: ~1200-1600 (thấp hơn)
// Đo thực tế bằng code calibration trước!
const int DRY_VALUE = 3400; // ADC 12-bit khi khô
const int WET_VALUE = 1300; // ADC 12-bit khi ướt
const int WATER_THRESHOLD_LOW = 30;
const int WATER_THRESHOLD_HIGH = 60;
const int POWER_PIN = 26; // Cấp nguồn sensor
const int SENSOR_PIN = 32; // ADC1 — hoạt động tốt khi WiFi bật
const int RELAY_PIN = 27; // Relay (LOW = bật nếu relay active LOW)
bool isWatering = false;
unsigned long lastReadTime = 0;
const unsigned long READ_INTERVAL = 10000; // Đo mỗi 10 giây
void setup() {
Serial.begin(115200);
pinMode(POWER_PIN, OUTPUT);
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(POWER_PIN, LOW);
digitalWrite(RELAY_PIN, HIGH); // Tắt máy bơm ban đầu
// analogSetAttenuation: mở rộng dải đọc ADC
// ADC_11db → đọc được 0-3.3V (mặc định 0-1.1V quá hẹp)
analogSetAttenuation(ADC_11db);
analogReadResolution(12); // 12-bit: 0-4095
Serial.println("=== Soil Moisture Monitor - ESP32 ===");
}
int readMoisture() {
// Bật nguồn sensor
digitalWrite(POWER_PIN, HIGH);
delay(200); // ESP32: cần thời gian ổn định ADC lâu hơn
// ESP32 ADC có noise cao hơn Arduino Uno — đọc nhiều lần hơn
int total = 0;
for (int i = 0; i < 10; i++) {
total += analogRead(SENSOR_PIN);
delay(10);
}
int raw = total / 10;
// Tắt nguồn ngay sau khi đọc xong
digitalWrite(POWER_PIN, LOW);
Serial.printf(" ADC raw: %d\n", raw);
int moisture = map(raw, DRY_VALUE, WET_VALUE, 0, 100);
return constrain(moisture, 0, 100);
}
void loop() {
unsigned long now = millis();
// Đo theo khoảng thời gian, không dùng delay() dài để không block
if (now - lastReadTime >= READ_INTERVAL) {
lastReadTime = now;
int moisture = readMoisture();
Serial.printf("Độ ẩm đất: %d%% | ", moisture);
if (!isWatering && moisture < WATER_THRESHOLD_LOW) {
isWatering = true;
digitalWrite(RELAY_PIN, LOW);
Serial.println("TƯỚI BẮT ĐẦU");
} else if (isWatering && moisture >= WATER_THRESHOLD_HIGH) {
isWatering = false;
digitalWrite(RELAY_PIN, HIGH);
Serial.println("TƯỚI DỪNG");
} else {
Serial.println(isWatering ? "Đang tưới..." : "Bình thường");
}
}
// Loop chạy liên tục — có thể thêm logic khác (WiFi, MQTT, v.v.)
}
Kết Quả Mong Đợi
=== Soil Moisture Monitor - ESP32 ===
ADC raw: 3380
Độ ẩm đất: 2% | Bình thường
ADC raw: 3350
Độ ẩm đất: 4% | TƯỚI BẮT ĐẦU
ADC raw: 2100
Độ ẩm đất: 49% | Đang tưới...
ADC raw: 1450
Độ ẩm đất: 92% | TƯỚI DỪNG
Ứng Dụng Thực Tế
| Ứng dụng | Chi tiết |
|---|---|
| Tưới cây tự động | Kết hợp relay + máy bơm mini |
| Vườn thông minh | Nhiều sensor cho nhiều chậu cây khác nhau |
| Cảnh báo khô hạn | Gửi thông báo qua WiFi (ESP32) khi đất quá khô |
| Logger độ ẩm | Ghi dữ liệu theo thời gian → tối ưu lịch tưới |
| Nhà kính IoT | Kết hợp DHT22 (nhiệt độ/độ ẩm không khí) + soil moisture |
Lưu Ý Khi Sử Dụng
1. Bắt buộc hiệu chỉnh 2 điểm trước khi dùng
Giá trị ADC raw của sensor này thay đổi giữa các cá thể, giữa các loại đất, và ngay cả khi điện cực bị ăn mòn. Không có giá trị “chuẩn” chung. Luôn đo DRY và WET thực tế cho đúng setup của bạn.
2. Cấp nguồn xung — không cấp liên tục
Cấp VCC cho sensor chỉ khi đo (vài trăm ms), rồi tắt. Cấp liên tục → điện phân → điện cực gỉ sau 1-2 tuần → đọc sai. Sử dụng kỹ thuật này: bật GPIO cấp nguồn → delay ổn định → đọc ADC → tắt GPIO.
3. ADC ESP32 khác Arduino Uno
- Arduino Uno: 10-bit (0–1023), tham chiếu 5V (hoặc 3.3V)
- ESP32: 12-bit (0–4095), tham chiếu 3.3V, cần
analogSetAttenuation(ADC_11db)để đọc đúng dải - DRY/WET values hoàn toàn khác nhau giữa 2 board → phải calibrate riêng cho mỗi board
4. Logic hysteresis cho tưới cây
Không dùng 1 ngưỡng duy nhất (nếu <30% thì tưới). Dùng 2 ngưỡng: bật tưới khi <30%, tắt khi >60%. Lý do: nếu chỉ có 1 ngưỡng là 30%, relay sẽ bật-tắt liên tục khi độ ẩm dao động xung quanh 30% → hỏng relay và máy bơm.
5. Độ trễ sau khi bật nguồn
Sau khi bật GPIO cấp nguồn, cần delay ít nhất 100–200ms trước khi đọc ADC. Điện áp cần ổn định trước khi đọc. Đọc ngay → kết quả không ổn định.
6. Cân nhắc chuyển sang sensor điện dung
Nếu ứng dụng dài hạn (>1 tháng), hãy dùng Capacitive Soil Moisture v1.2 hoặc v2.0. Không có vấn đề ăn mòn, tín hiệu ổn định hơn theo thời gian, mặc dù giá cao hơn một chút.


