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

Bảng so sánh HC-SR04, JSN-SR04T, A02YYUW: đầu dò hở hay kín chống nước, ngõ ra Trig Echo hay UART 9600, nguồn, khoảng đo, vùng mù gần 2 cm, 20–25 cm, 3 cm, góc đo, ứng dụng phù hợp
So sánh ba loại cảm biến siêu âm.
  • 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

Mặt cắt bồn nước với đầu dò trên nắp, vùng mù ngay dưới đầu dò, khoảng cách đo được d từ đầu dò xuống mặt nước, mực nước bằng khoảng cách tới đáy trừ d
Lắp đầu dò và cách tính mực nước (hình minh họa).
  • 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

Sơ đồ nối A02YYUW với ESP32: VCC dây đỏ vào 3V3, GND dây đen vào GND, TX dây trắng vào RX2 GPIO16, RX dây vàng để hở
Nối A02YYUW với ESP32 (hình minh họa).
  • 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

Khung bốn byte FF 02 70 71: byte đầu khung FF, byte cao H 02, byte thấp L 70, tổng kiểm 71; khoảng cách bằng 0x02 nhân 256 cộng 0x70 bằng 624 mm
Khung dữ liệu A02YYUW, ví dụ 624 mm.

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í.

Serial Monitor in khoảng cách 62,4 cm, mực nước 87,6 cm, 70 phần trăm, khoảng 634 lít, rồi các dòng khi nước giảm tới 9,8 cm, 8 phần trăm, 71 lít
Kết quả khi nước trong bồn giảm dần (hình minh họa).

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ượngNguyên nhânCách xử lý
Bồn gần đầy thì số đo nhảy lung tungMặ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ướcTiếng vọng từ thành bồn, ống, phaoDời đầu dò ra giữa bồn, thẳng đứng
Không đọc được A02YYUWNhầm dây TX, RX; sai baudTX cảm biến vào RX2, 9600 baud
Trong bồn kín, đầu dò đọng nướcHơ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

7. Xem thêm


Tin tức liên quan

Nhà kính mini với ESP32: đo nhiệt độ, độ ẩm đất, ánh sáng; tự tưới, bật quạt, đèn trồng cây
Nhà kính mini với ESP32: đo nhiệt độ, độ ẩm đất, ánh sáng; tự tưới, bật quạt, đèn trồng cây

Làm nhà kính mini với ESP32: DHT22, cảm biến độ ẩm đất, quang trở; relay điều khiển bơm, quạt, đèn trồng cây 12 V có khoảng trễ, tưới từng đợt, hạn mức bơm, trang web tự động và bằng tay.

LCD I2C không hiện chữ, chỉ hiện ô vuông, sai địa chỉ 0x27/0x3F: tìm lỗi từng bước
LCD I2C không hiện chữ, chỉ hiện ô vuông, sai địa chỉ 0x27/0x3F: tìm lỗi từng bước

LCD 1602, LCD 2004 I2C không hiện chữ, chỉ hiện hàng ô vuông đen hoặc sai địa chỉ 0x27/0x3F: tìm lỗi nguồn, tương phản, dây I2C, địa chỉ và chương trình kiểm tra tự động.

Module thời gian thực DS3231 với ESP32: đọc giờ, đặt giờ, báo thức hằng ngày, giữ giờ khi mất điện
Module thời gian thực DS3231 với ESP32: đọc giờ, đặt giờ, báo thức hằng ngày, giữ giờ khi mất điện

DS3231 khác DS1307 thế nào, nối với ESP32 qua I2C, thanh ghi và mã BCD, chương trình đọc giờ, nhiệt độ, đặt giờ qua Serial và báo thức hằng ngày qua chân SQW, kèm bảng lỗi.

Màn hình TFT SPI ILI9341 với ESP32: nối dây, lệnh khởi động, vẽ chữ và đồ thị không cần thư viện
Màn hình TFT SPI ILI9341 với ESP32: nối dây, lệnh khởi động, vẽ chữ và đồ thị không cần thư viện

Nối màn hình TFT ILI9341 2.4–2.8 inch với ESP32, các lệnh khởi động và vẽ vùng, màu RGB565, bộ chữ 5x7, chương trình vẽ số lớn và đồ thị điện áp không nhấp nháy, bảng sửa lỗi.

Cấu hình Wi-Fi cho ESP32 bằng điện thoại, không nạp lại code: tự làm trang cài đặt như WiFiManager
Cấu hình Wi-Fi cho ESP32 bằng điện thoại, không nạp lại code: tự làm trang cài đặt như WiFiManager

ESP32 tự phát mạng Wi-Fi khi chưa có cấu hình, điện thoại vào là bật trang chọn mạng, lưu bằng Preferences; chỉ dùng thư viện có sẵn, giữ BOOT 3 giây để xóa.

Báo rò khí gas qua Telegram với ESP32 và MQ-2: hai mức cảnh báo, còi, báo lỗi cảm biến, tự kiểm tra
Báo rò khí gas qua Telegram với ESP32 và MQ-2: hai mức cảnh báo, còi, báo lỗi cảm biến, tự kiểm tra

Làm máy báo rò khí gas với ESP32 và MQ-2: hai mức cảnh báo, còi tại chỗ, nhắn Telegram nhắc lại mỗi 2 phút, báo lỗi cảm biến, tự kiểm tra mỗi sáng, cách đặt cảm biến và lưu ý an toàn.

ESP32 với Firebase Realtime Database qua REST: đăng nhập ẩn danh, làm mới token, điều khiển relay
ESP32 với Firebase Realtime Database qua REST: đăng nhập ẩn danh, làm mới token, điều khiển relay

ESP32 dùng Firebase Realtime Database không cần thư viện Firebase: đăng nhập ẩn danh, tự làm mới token, đọc lệnh relay, ghi trạng thái và lịch sử, Rules theo uid.

Hướng dẫn làm đồng hồ Internet với ESP32, NTP và màn hình OLED 0.96 inch
Hướng dẫn làm đồng hồ Internet với ESP32, NTP và màn hình OLED 0.96 inch

Hướng dẫn ESP32 lấy giờ Việt Nam từ Internet bằng NTP trên Arduino IDE, in ra Serial Monitor và làm đồng hồ hiển thị thứ, ngày, giờ trên màn hình OLED 0.96 inch SSD1306.


Bình luận
Đã thêm vào giỏ hàng