Cảm biến siêu âm chống nước JSN-SR04T, A02YYUW đo mực nước bồn với ESP32: lắp đặt, code, thể tích
Đo mực nước bồn bằng cảm biến siêu âm chống nước JSN-SR04T và A02YYUW với ESP32: so sánh, vùng mù, lắp trên nắp bồn, khung UART, code tính chiều cao nước, phần trăm và thể tích.
Đo mực nước bồn, bể chứa, hố ga là ứng dụng hay gặp của cảm biến siêu âm. Nhưng HC-SR04 thông thường có đầu dò hở, hơi nước làm hỏng nhanh. Hai loại cảm biến siêu âm chống nước phổ biến hơn cho việc này là JSN-SR04T và A02YYUW: đầu dò kín, dây dài, gắn được trên nắp bồn. Bài này so sánh hai loại, cách lắp trên bồn, nối với ESP32, đọc khung dữ liệu UART của A02YYUW, và chương trình tính chiều cao nước, phần trăm, thể tích nước trong bồn.
1. JSN-SR04T, A02YYUW khác HC-SR04 thế nào

- JSN-SR04T: đầu dò kim loại kín nước nối với mạch điều khiển bằng dây dài khoảng 2,5 m. Ở chế độ mặc định, dùng giống HC-SR04 (chân Trig, Echo). Nhược điểm: vùng mù gần khoảng 20–25 cm (vật gần hơn thì đo sai) và góc đo rộng, dễ nhận tiếng vọng từ thành bồn.
- A02YYUW: đầu dò và mạch đúc chung trong vỏ nhựa kín, gửi khoảng cách qua UART. Vùng mù chỉ khoảng 3 cm, chạy 3,3–5 V, đã lọc sẵn trong cảm biến nên số đo ổn định hơn.
Với bồn nước gia đình cao 1–2 m, A02YYUW dễ dùng hơn. JSN-SR04T rẻ hơn, hợp với bể lớn, hố sâu nơi mặt nước luôn cách đầu dò trên 30 cm.
2. Lắp đầu dò trên nắp bồn

- Khoét lỗ trên nắp bồn, gắn đầu dò hướng thẳng đứng xuống mặt nước; nghiêng vài độ đã làm sai số tăng.
- Đặt đầu dò xa thành bồn, xa ống cấp nước, phao cơ: tiếng vọng từ các vật này lẫn với tiếng vọng mặt nước.
- Mực nước cao nhất phải thấp hơn đầu dò một khoảng lớn hơn vùng mù. Nếu bồn đầy tới sát nắp, nâng đầu dò lên bằng một đoạn ống.
- Đo khoảng cách thật từ mặt đầu dò tới đáy bồn bằng thước, ghi vào chương trình.
Chiều cao nước = khoảng cách tới đáy − khoảng cách đo được. Bồn trụ đứng: thể tích (lít) = π × r² × chiều cao nước / 1000 với r, chiều cao tính bằng cm. Bồn nằm ngang hình trụ không tính được theo công thức thẳng này: dùng bảng tra hoặc công thức diện tích hình viên phân.
3. Nối dây với ESP32

- A02YYUW: VCC vào 3V3 (để tín hiệu ra cũng là 3,3 V), GND vào GND, TX của cảm biến vào RX2 (GPIO16) của ESP32. Chân RX của cảm biến để hở: cảm biến tự gửi khoảng cách đã lọc khoảng 100 ms một lần.
- JSN-SR04T: nối như HC-SR04: VCC vào 5 V (chân VIN), Trig vào D5, Echo vào D18 qua cầu chia 1 kΩ / 2 kΩ để hạ 5 V xuống khoảng 3,3 V.
Chuẩn bị ESP32 DevKit V1, cảm biến (shop chưa bán hai loại này), dây cắm. Lắp ngoài trời thì nối dây qua đầu nối tròn GX16 để tháo lắp, và đặt mạch trong hộp kín.
4. Khung dữ liệu UART của A02YYUW

Mỗi lần đo, A02YYUW gửi 4 byte ở 9600 baud: byte 0xFF đánh dấu đầu khung, hai byte khoảng cách (milimét), và một byte tổng kiểm bằng tổng ba byte trước lấy 8 bit thấp. Chương trình chờ byte 0xFF, gom đủ 4 byte rồi kiểm tra tổng; khung sai thì bỏ qua.
5. Chương trình đo mực nước
// PYWORLD.VN - Đo mực nước bồn bằng cảm biến siêu âm chống nước với ESP32: A02YYUW (UART) hoặc JSN-SR04T (Trig/Echo)
// PYWORLD.VN - A02YYUW: TX cảm biến vào RX2 (GPIO16), nguồn 3V3; JSN-SR04T: Trig D5, Echo D18 qua cầu chia 1 kΩ / 2 kΩ, nguồn 5 V
// PYWORLD.VN - Tính chiều cao nước, phần trăm và thể tích của bồn trụ đứng; lọc trung vị 5 lần đo
const bool DUNG_JSN_SR04T = false; // false: A02YYUW; true: JSN-SR04T
const int CHAN_RX2 = 16, CHAN_TX2 = 17; // A02YYUW: TX -> GPIO16; chân RX của cảm biến để hở (xuất dữ liệu đã xử lý)
const int CHAN_TRIG = 5, CHAN_ECHO = 18;
// Kích thước bồn (đo thực tế rồi sửa)
const float KHOANG_CACH_TOI_DAY_CM = 150.0f; // từ mặt đầu dò tới đáy bồn
const float MUC_DAY_CM = 125.0f; // chiều cao nước khi bồn đầy (chừa vùng mù phía trên)
const float DUONG_KINH_CM = 96.0f; // bồn trụ đứng
const float TOC_DO_AM_CM_US = 0.0346f; // khoảng 25 °C
uint8_t khung[4];
int viTri = 0;
int docUart = -1; // mm, -1 là chưa có
// A02YYUW gửi khung 4 byte: 0xFF, H, L, SUM; khoảng cách mm = H * 256 + L; SUM = (0xFF + H + L) & 0xFF
void docA02() {
while (Serial2.available()) {
uint8_t b = Serial2.read();
if (viTri == 0 && b != 0xFF) {
continue; // chờ byte đầu khung
}
khung[viTri++] = b;
if (viTri == 4) {
viTri = 0;
uint8_t tong = (khung[0] + khung[1] + khung[2]) & 0xFF;
if (tong == khung[3]) {
docUart = khung[1] * 256 + khung[2];
}
}
}
}
float doMotLanCm() {
if (DUNG_JSN_SR04T) {
digitalWrite(CHAN_TRIG, LOW);
delayMicroseconds(4);
digitalWrite(CHAN_TRIG, HIGH);
delayMicroseconds(20); // JSN-SR04T cần xung kích dài hơn HC-SR04
digitalWrite(CHAN_TRIG, LOW);
unsigned long us = pulseIn(CHAN_ECHO, HIGH, 40000);
return us ? us * TOC_DO_AM_CM_US / 2.0f : -1;
}
uint32_t batDau = millis();
docUart = -1;
while (docUart < 0 && millis() - batDau < 300) {
docA02();
delay(5);
}
return docUart > 0 ? docUart / 10.0f : -1;
}
float doTrungViCm() {
float ds[5];
int n = 0;
for (int i = 0; i < 5; i++) {
float d = doMotLanCm();
if (d > 0) {
ds[n++] = d;
}
delay(DUNG_JSN_SR04T ? 80 : 120);
}
if (n == 0) {
return -1;
}
for (int i = 1; i < n; i++) {
float x = ds[i];
int j = i - 1;
while (j >= 0 && ds[j] > x) {
ds[j + 1] = ds[j];
j--;
}
ds[j + 1] = x;
}
return ds[n / 2];
}
void setup() {
Serial.begin(115200);
if (DUNG_JSN_SR04T) {
pinMode(CHAN_TRIG, OUTPUT);
pinMode(CHAN_ECHO, INPUT);
} else {
Serial2.begin(9600, SERIAL_8N1, CHAN_RX2, CHAN_TX2);
}
Serial.printf("Do muc nuoc: %s\n", DUNG_JSN_SR04T ? "JSN-SR04T" : "A02YYUW");
}
void loop() {
float d = doTrungViCm();
if (d < 0) {
Serial.println("Khong doc duoc cam bien (kiem tra day, nguon, vung mu)");
} else {
float muc = KHOANG_CACH_TOI_DAY_CM - d;
if (muc < 0) {
muc = 0;
}
float phanTram = muc * 100.0f / MUC_DAY_CM;
float banKinh = DUONG_KINH_CM / 2.0f;
float lit = 3.14159f * banKinh * banKinh * muc / 1000.0f;
Serial.printf("Khoang cach %.1f cm | muc nuoc %.1f cm (%.0f %%) | khoang %.0f lit\n", d, muc, phanTram, lit);
}
delay(2000);
}
Sửa ba hằng số theo bồn thật: KHOANG_CACH_TOI_DAY_CM, MUC_DAY_CM, DUONG_KINH_CM. Dùng JSN-SR04T thì đặt DUNG_JSN_SR04T = true. Chương trình đo 5 lần, lấy trung vị để bỏ số đo lỗi do sóng mặt nước, bọt khí.

Từ đây có thể bật tắt máy bơm theo mực nước (dùng module relay điều khiển contactor), có ngưỡng trễ để bơm không bật tắt liên tục, hoặc gửi số liệu lên điện thoại.
6. Lỗi hay gặp
| Hiện tượng | Nguyên nhân | Cách xử lý |
|---|---|---|
| Bồn gần đầy thì số đo nhảy lung tung | Mặt nước vào vùng mù | Nâng đầu dò lên; với JSN-SR04T giữ nước cách đầu dò trên 30 cm |
| Số đo cố định, không đổi theo nước | Tiếng vọng từ thành bồn, ống, phao | Dời đầu dò ra giữa bồn, thẳng đứng |
| Không đọc được A02YYUW | Nhầm dây TX, RX; sai baud | TX cảm biến vào RX2, 9600 baud |
| Trong bồn kín, đầu dò đọng nước | Hơi nước ngưng tụ trên mặt đầu dò | Lau định kỳ; thông hơi cho bồn; chọn loại có màng chống đọng |
| Thể tích lệch xa thực tế | Bồn không phải hình trụ đều; đáy cong | Đổ từng lượng nước đã biết, lập bảng hiệu chuẩn mực nước theo lít |
Xem thêm