Cảm biến
Series ESP32 & Cảm biến: Bài 9 – Đọc cảm biến Water Level Sensor: đo mực nước & theo dõi realtime
Th1 2026

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