Trong bài này, chúng ta sử dụng Water Level Sensor (cảm biến mực nước) để đo mức nước theo dạng analog, sau đó chuẩn hoá thành % mực nước và gửi dữ liệu lên IoTLabs Cloud MQTT để theo dõi realtime.
Đây là cảm biến DIY rất phổ biến, thường dùng cho:
- Bồn nước gia đình
- Cảnh báo tràn / cạn nước
- Trạm thời tiết mini
- Ứng dụng nông nghiệp, thủy canh
Bài viết gồm 2 ví dụ code:
- Đọc mực nước local (Serial)
- Gửi mực nước lên IoTLabs Cloud MQTT để theo dõi realtime
1) Water Level Sensor là gì?
- Water Level Sensor hoạt động dựa trên độ dẫn điện của nước
- Khi mực nước tăng:
- Nhiều vạch đồng tiếp xúc nước hơn
- Điện trở giảm → giá trị ADC thay đổi
📌 Khác với Rain Sensor:
- Rain: phát hiện mưa / ướt
- Water Level: đo mức nước tuyến tính
2) Chuẩn bị
Phần cứng
- ESP32-C3 SuperMini (Tenstar Robot)
- Water Level Sensor module
- Breadboard + dây nối
Chân sử dụng
- AO → GPIO1 (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 Water Level Sensor với ESP32
Water Level Sensor ESP32-C3 SuperMini
-------------------------------------
VCC ------------ 5V
GND ------------ GND
AO ------------ GPIO1 (ADC)
4) Giá trị đọc & chuẩn hoá mực nước
ESP32 ADC (12-bit):
- Giá trị đọc: 0 → 4095
| Trạng thái | ADC (ước lượng) |
|---|---|
| Không có nước | 0 – 500 |
| Thấp | 500 – 1500 |
| Trung bình | 1500 – 3000 |
| Cao / đầy | > 3000 |
📌 Giá trị thay đổi theo loại cảm biến & chất lượng nước → cần hiệu chỉnh.
Ví dụ 1 — Code local đơn giản (đo mực nước)
Mục tiêu: in mực nước (%) ra Serial.
// ===== Water Level Sensor Local Read =====
const int WATER_PIN = 1; // ADC
void setup() {
Serial.begin(115200);
delay(200);
Serial.println("Water level sensor monitor started...");
}
void loop() {
int raw = analogRead(WATER_PIN);
// Chuẩn hoá % (0 = cạn, 100 = đầy)
int waterPct = map(raw, 0, 4095, 0, 100);
waterPct = constrain(waterPct, 0, 100);
Serial.print("ADC: ");
Serial.print(raw);
Serial.print(" | Water level: ");
Serial.print(waterPct);
Serial.println("%");
delay(1000);
}
5) Chuẩn dữ liệu realtime cho IoTLabs Cloud
Topic
iotlabs/<orgId>/devices/<deviceId>/telemetry
Payload JSON
{
"ts": 1760000000,
"metrics": {
"water_level": 72
},
"status": {
"level": "normal"
}
}
| water_level | Ý nghĩa |
|---|---|
| 0–20 | thấp |
| 20–80 | bình thường |
| >80 | cao |
Ví dụ 2 — Gửi mực nước lên IoTLabs Cloud MQTT
Chiến lược:
- Gửi định kỳ 5–10 giây
- Có thể kết hợp cảnh báo ngưỡng (Level 2)
#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";
// ===== WATER =====
const int WATER_PIN = 1;
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-water", 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(WATER_PIN);
int waterPct = map(raw, 0, 4095, 0, 100);
waterPct = constrain(waterPct, 0, 100);
long ts = millis() / 1000;
String payload = "{";
payload += "\"ts\":" + String(ts) + ",";
payload += "\"metrics\":{\"water_level\":" + String(waterPct) + "},";
payload += "\"status\":{\"level\":\"normal\"}";
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 cảm biến
- Không để ngâm lâu ngày
- Lau khô sau khi test
- ADC nhảy loạn
- Lấy trung bình 5–10 mẫu
- Sai %
- In raw ADC để tự hiệu chỉnh min/max
7) Ứng dụng thực tế
- Giám sát bồn nước
- Cảnh báo cạn / tràn
- Kết hợp Rain Sensor (Bài 8)
- Nâng cấp cảnh báo thông minh (Level 2)
Bài tiếp theo (Level 1 – bài cuối)
👉 Bài 10: Hướng dẫn đọc cảm biến Sound Sensor (KY-038 / KY-037) bằng ESP32: đo mức âm thanh & theo dõi realtime


