Trong bài này, chúng ta sử dụng Rain Sensor (cảm biến mưa) để phát hiện có mưa hay không, đồng thời theo dõi realtime mức ướt thông qua IoTLabs Cloud MQTT.
Đây là cảm biến analog rất phổ biến, thường dùng cho:
- Trạm thời tiết DIY
- Hệ thống tưới cây tự động
- Đóng/mở mái che
- Cảnh báo mưa sớm
Bài viết gồm 2 ví dụ code:
- Đọc cảm biến mưa local (Serial)
- Gửi trạng thái mưa + mức ướt lên IoTLabs Cloud MQTT để theo dõi realtime
1) Rain Sensor là gì?
- Rain Sensor hoạt động dựa trên độ dẫn điện của nước
- Khi có mưa:
- Nước tạo cầu dẫn giữa các vạch đồng
- Điện trở giảm → giá trị analog thay đổi
Module phổ biến gồm:
- Tấm cảm biến mưa (plate)
- Module so sánh LM393
- AO: Analog Output (mức ướt)
- DO: Digital Output (có/không mưa)
📌 Trong bài này:
- Dùng AO (analog) để:
- Đo mức ướt
- Linh hoạt hơn cho IoT realtime
2) Chuẩn bị
Phần cứng
- ESP32-C3 SuperMini (Tenstar Robot)
- Rain Sensor module
- Breadboard + dây nối
Chân sử dụng
- AO → GPIO0 (ADC)
- VCC → 5V
- GND → GND
⚠️ Khuyến nghị cấp 5V cho module để tín hiệu ổn định
ESP32 chỉ đọc analog (3.3V safe)
3) Nối dây Rain Sensor với ESP32
Rain Sensor ESP32-C3 SuperMini
------------------------------------
VCC ------------ 5V
GND ------------ GND
AO ------------ GPIO0 (ADC)
4) Giá trị đọc & cách hiểu
ESP32 ADC (12-bit):
- Giá trị đọc: 0 → 4095
| Trạng thái | Giá trị ADC (ước lượng) |
|---|---|
| Khô | 3500 – 4095 |
| Ẩm nhẹ | 2000 – 3500 |
| Mưa | < 2000 |
📌 Giá trị phụ thuộc module & môi trường → nên test thực tế.
Ví dụ 1 — Code local đơn giản (đọc mưa + Serial)
Mục tiêu: đọc mức ướt (%) và xác định có mưa hay không.
// ===== Rain Sensor Local Read =====
const int RAIN_PIN = 0; // ADC
const int RAIN_THRESHOLD = 2000; // ngưỡng mưa
void setup() {
Serial.begin(115200);
delay(200);
Serial.println("Rain sensor monitor started...");
}
void loop() {
int raw = analogRead(RAIN_PIN);
// Chuẩn hoá % (0 = khô, 100 = ướt)
int rainPct = map(raw, 4095, 0, 0, 100);
rainPct = constrain(rainPct, 0, 100);
bool isRaining = raw < RAIN_THRESHOLD;
Serial.print("ADC: ");
Serial.print(raw);
Serial.print(" | Wet: ");
Serial.print(rainPct);
Serial.print("% | ");
if (isRaining) {
Serial.println("🌧️ ĐANG MƯA");
} else {
Serial.println("☀️ KHÔ");
}
delay(1000);
}
5) Chuẩn dữ liệu realtime
Topic
iotlabs/<orgId>/devices/<deviceId>/telemetry
Payload JSON
{
"ts": 1760000000,
"metrics": {
"rain_pct": 65
},
"status": {
"rain": "detected"
}
}
| Trường | Ý nghĩa |
|---|---|
| rain_pct | % ướt |
| rain | detected / none |
Ví dụ 2 — Gửi dữ liệu mưa lên IoTLabs Cloud MQTT
Chiến lược:
- Gửi định kỳ 5–10s
- Chỉ đổi status khi vượt ngưỡng
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>
// ===== CONFIG =====
const char* WIFI_SSID = "YOUR_WIFI";
const char* WIFI_PASS = "YOUR_PASS";
const char* MQTT_HOST = "mqtt.iotlabs.vn";
const int MQTT_PORT = 8883;
const char* MQTT_USER = "YOUR_MQTT_USER";
const char* MQTT_PASS = "YOUR_MQTT_PASS";
const char* MQTT_TOPIC =
"iotlabs/<orgId>/devices/<deviceId>/telemetry";
// ===== RAIN =====
const int RAIN_PIN = 0;
const int RAIN_THRESHOLD = 2000;
WiFiClientSecure net;
PubSubClient mqtt(net);
unsigned long lastSend = 0;
const unsigned long SEND_INTERVAL = 5000;
void connectWiFi() {
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(400);
Serial.print(".");
}
Serial.println("\nWiFi connected");
}
void connectMQTT() {
net.setInsecure(); // demo
mqtt.setServer(MQTT_HOST, MQTT_PORT);
while (!mqtt.connected()) {
if (mqtt.connect("esp32c3-rain", MQTT_USER, MQTT_PASS)) {
Serial.println("MQTT connected");
break;
}
delay(1000);
}
}
void setup() {
Serial.begin(115200);
connectWiFi();
connectMQTT();
}
void loop() {
if (!mqtt.connected()) connectMQTT();
mqtt.loop();
unsigned long now = millis();
if (now - lastSend > SEND_INTERVAL) {
lastSend = now;
int raw = analogRead(RAIN_PIN);
int rainPct = map(raw, 4095, 0, 0, 100);
rainPct = constrain(rainPct, 0, 100);
bool isRaining = raw < RAIN_THRESHOLD;
long ts = millis() / 1000;
String payload = "{";
payload += "\"ts\":" + String(ts) + ",";
payload += "\"metrics\":{\"rain_pct\":" + String(rainPct) + "},";
payload += "\"status\":{\"rain\":\"";
payload += (isRaining ? "detected" : "none");
payload += "\"}}";
mqtt.publish(MQTT_TOPIC, payload.c_str());
Serial.println(payload);
}
}
6) Lỗi thường gặp & kinh nghiệm thực tế
- Ăn mòn tấm cảm biến
- Lau khô sau mưa
- Không để ngoài trời lâu ngày
- Nhiễu số
- Lấy trung bình 5–10 mẫu
- Ngưỡng không chuẩn
- In raw ADC để tự hiệu chỉnh
7) Ứng dụng thực tế
- Trạm thời tiết DIY
- Tưới cây thông minh
- Đóng mái che tự động
- Kết hợp Water Level Sensor (Bài 9)
Bài tiếp theo (Level 1)
👉 Bài 9: Hướng dẫn đọc cảm biến Water Level Sensor bằng ESP32: đo mực nước & theo dõi realtime


