Thiết bị Theo dõi mực nước ao nuôi thủy sản
Trung cấp1/8/2026- Tác giả: IoTlabs Maker

Thiết bị Theo dõi mực nước ao nuôi thủy sản

Dùng cảm biến siêu âm HC-SR04 gắn trên ESP32 để đo mực nước ao nuôi thủy sản theo thời gian thực, cảnh báo tại chỗ bằng buzzer khi mực nước quá thấp hoặc quá cao.

esp32hc-sr04muc-nuocthuy-sansmart-farmcanh-baoiot

Trong dự án này, bạn sẽ xây dựng một hệ thống theo dõi mực nước ao nuôi thủy sản bằng cách sử dụng cảm biến siêu âm HC-SR04 gắn trên board ESP32. Hệ thống này sẽ đo lường mực nước trong ao nuôi theo thời gian thực và cảnh báo khi mực nước quá thấp hoặc quá cao bằng một buzzer. Đây là một dự án thú vị giúp bạn áp dụng kiến thức về IoT vào thực tiễn nuôi trồng thủy sản.

Những gì bạn sẽ học được

  • Cách sử dụng cảm biến siêu âm HC-SR04 để đo khoảng cách.

  • Cấu hình và lập trình ESP32 để kết nối và xử lý dữ liệu cảm biến.

  • Cách phát hiện và xử lý các tình huống cảnh báo khi mực nước không đạt yêu cầu.

  • Tích hợp buzzer để phát ra âm thanh cảnh báo.

  • Áp dụng các khái niệm về IoT trong một dự án thực tế.

Tính năng nổi bật

  • Đo mực nước chính xác và nhanh chóng với cảm biến HC-SR04.

  • Cảnh báo tại chỗ ngay lập tức bằng buzzer khi mực nước vượt ngưỡng cho phép.

  • Thiết kế đơn giản, dễ hiểu, phù hợp cho những người mới bắt đầu và cả những người có kinh nghiệm.

  • Có thể mở rộng thêm tính năng ghi dữ liệu hoặc gửi thông tin qua mạng.

Tại sao dự án này thú vị?

Dự án này không chỉ giúp bạn nâng cao kỹ năng lập trình và hiểu biết về IoT mà còn mang lại giá trị thực tiễn trong lĩnh vực nuôi trồng thủy sản. Mực nước là yếu tố quan trọng quyết định đến sự sống còn của thủy sản, do đó việc theo dõi và kiểm soát mực nước là cần thiết. Hệ thống này giúp người nuôi có thể chủ động hơn trong việc chăm sóc và bảo vệ đàn thủy sản của mình, từ đó nâng cao năng suất và chất lượng sản phẩm.

Hướng dẫn chi tiết

ESP32 + HC-SR04 đo mực nước ao nuôi thủy sản không tiếp xúc, cảnh báo tại chỗ bằng buzzer khi nước quá thấp hoặc quá cao, kèm lưu ý an toàn cầu phân áp cho chân ECHO 5V.

1. Giới thiệu

Trong nuôi trồng thủy sản (tôm, cá), mực nước ao/hồ ảnh hưởng trực tiếp đến sức khỏe vật nuôi — nước cạn quá gây stress nhiệt và thiếu oxy hòa tan, nước tràn quá gây thất thoát và ô nhiễm khu vực xung quanh. Dự án này dùng cảm biến siêu âm HC-SR04 gắn cố định phía trên mặt ao để đo khoảng cách từ cảm biến xuống mặt nước theo thời gian thực, quy đổi ra phần trăm mực nước, và phát cảnh báo tại chỗ bằng buzzer khi mực nước xuống quá thấp (cần bơm bổ sung) hoặc lên quá cao (nguy cơ tràn/ngập).

Đây là bài toán đo lường không tiếp xúc (non-contact) phù hợp với môi trường ao nuôi vì cảm biến không cần ngâm trong nước, giảm nguy cơ hư hỏng do ăn mòn/đóng cặn so với cảm biến mực nước kiểu phao hoặc điện cực.

2. Linh kiện cần có

Linh kiện

Số lượng

Giá tham khảo

ESP32 DevKit V1 (30 chân)

1

~90.000 - 120.000đ

HC-SR04 – Cảm biến siêu âm đo khoảng cách

1

~15.000 - 25.000đ

Active Buzzer – còi cảnh báo tại chỗ

1

~5.000 - 10.000đ

Điện trở 1kΩ + 2kΩ (cầu phân áp cho chân ECHO)

1 bộ

~5.000đ

Hộp chống nước (IP65+) gắn cảm biến trên mép ao

1

tuỳ vật liệu

Dây jumper, giá đỡ cảm biến, nguồn 5V

1 bộ

~20.000 - 30.000đ

3. Sơ đồ kết nối

HC-SR04

ESP32

VCC

VIN (5V)

GND

GND

TRIG

GPIO26

ECHO

GPIO27 (qua cầu phân áp, xem lưu ý bên dưới)

Active Buzzer

ESP32

VCC

3V3

GND

GND

IO

GPIO25

Lưu ý quan trọng về an toàn phần cứng:

  • HC-SR04 xuất xung ECHO ở mức 5V, nhưng GPIO của ESP32 chỉ chịu được tối đa khoảng 3.3V (~3.6V tuyệt đối). Khi triển khai thực tế trên phần cứng thật,

  • Bắt buộc phải dùng cầu phân áp điện trở (ví dụ 1kΩ nối tiếp GND qua 2kΩ, lấy điểm giữa vào GPIO27) hoặc module level-shifter trên chân ECHO trước khi nối vào ESP32 nếu không sẽ có nguy cơ làm hỏng chân GPIO/chip về lâu dài.

  • Ngoài ra, cảm biến cần được lắp trong hộp chống nước (watertight) khi đặt ngoài trời hoặc trên mặt ao để tránh hư hỏng do mưa/ẩm.

4. Code ví dụ #1 – Đo khoảng cách cơ bản với HC-SR04

#define TRIG_PIN 26
#define ECHO_PIN 27

void setup() {
  Serial.begin(115200);
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
}

void loop() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  long duration = pulseIn(ECHO_PIN, HIGH, 25000);
  float distanceCm = duration * 0.0343 / 2.0;

  if (duration == 0) {
    Serial.println("Khong doc duoc cam bien (timeout)");
  } else {
    Serial.print("Khoang cach: ");
    Serial.print(distanceCm);
    Serial.println(" cm");
  }

  delay(1000);
}

5. Code ví dụ #2 – Cảnh báo buzzer khi mực nước vượt ngưỡng

#define BUZZER_PIN 25

const float DISTANCE_LOW_WATER_CM = 130.0;  // qua xa cam bien = nuoc thap

void setup() {
  pinMode(BUZZER_PIN, OUTPUT);
  digitalWrite(BUZZER_PIN, LOW);
}

void loop() {
  float distanceCm = 140.0; // thay bang gia tri do tu HC-SR04 thuc te

  if (distanceCm > DISTANCE_LOW_WATER_CM) {
    digitalWrite(BUZZER_PIN, HIGH); // canh bao nuoc thap
  } else {
    digitalWrite(BUZZER_PIN, LOW);
  }

  delay(1000);
}

6. Code ví dụ #3 – Ứng dụng thực tế: theo dõi mực nước ao nuôi đầy đủ

/*
  Theo doi muc nuoc ao nuoi thuy san
  Board: ESP32 DevKit V1 (30 pins)
  Cam bien: HC-SR04 (sieu am do khoang cach tu mep ao xuong mat nuoc)
  Canh bao tai cho: Active Buzzer

  Wiring (khop voi diagram tren IoTLabs Maker):
    HC-SR04   TRIG -> GPIO26     ECHO -> GPIO27
              VCC  -> VIN(5V)    GND  -> GND
    Buzzer    IO   -> GPIO25     VCC  -> 3V3   GND -> GND

  LUU Y QUAN TRONG (an toan phan cung):
    HC-SR04 xuat xung ECHO muc 5V nhung GPIO ESP32 chi chiu duoc toi da 3.3V (~3.6V).
    Trien khai thuc te BAT BUOC dung cau phan ap tro (vi du 1kOhm + 2kOhm) tren chan ECHO
    truoc khi noi vao GPIO27, neu khong se co nguy co hong chan GPIO/chip ve lau dai.
    Ngoai ra can op ky watertight cho dau do khi lap ngoai troi/tren mat ao.

  Nguyen ly do muc nuoc:
    distance_cm = khoang cach tu cam bien (gan mieng ao) xuong mat nuoc.
    muc nuoc CAO  <-> distance_cm NHO (nuoc gan cam bien)
    muc nuoc THAP <-> distance_cm LON (nuoc xa cam bien)
  Canh bao khi muc nuoc qua thap (can bom bo sung) hoac qua cao (nguy co tran/ngap).
*/

#define TRIG_PIN 26
#define ECHO_PIN 27
#define BUZZER_PIN 25

// Hieu chinh theo kich thuoc ao thuc te (khoang cach tu cam bien den day/mep ao)
const float SENSOR_TO_EMPTY_CM = 150.0; // khoang cach khi ao can (muc nuoc = 0%)
const float SENSOR_TO_FULL_CM  = 20.0;  // khoang cach khi ao day (muc nuoc = 100%)

const float LOW_LEVEL_ALERT_PCT  = 20.0;  // canh bao muc nuoc thap
const float HIGH_LEVEL_ALERT_PCT = 95.0;  // canh bao muc nuoc qua cao / sap tran

const unsigned long MEASURE_INTERVAL_MS = 3000;
const unsigned long PULSE_TIMEOUT_US = 25000; // ~4.3m, du cho khoang cach thuc te trong ao

unsigned long lastMeasure = 0;
bool sensorTimeoutSeen = false;

float measureDistanceCm() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  unsigned long duration = pulseIn(ECHO_PIN, HIGH, PULSE_TIMEOUT_US);
  if (duration == 0) {
    return -1.0; // timeout / khong doc duoc - cam bien mat ket noi hoac ngoai tam
  }
  return duration * 0.0343 / 2.0; // toc do am thanh ~343 m/s
}

void setBuzzer(bool on) {
  digitalWrite(BUZZER_PIN, on ? HIGH : LOW);
}

void setup() {
  Serial.begin(115200);
  delay(300);
  Serial.println();
  Serial.println(F("=== Theo doi muc nuoc ao nuoi IoTLabs - Boot OK ==="));

  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  digitalWrite(TRIG_PIN, LOW);
  setBuzzer(false);

  Serial.println(F("HC-SR04 + Buzzer san sang. Bat dau do muc nuoc dinh ky."));
}

void loop() {
  unsigned long now = millis();
  if (now - lastMeasure < MEASURE_INTERVAL_MS) {
    return;
  }
  lastMeasure = now;

  float distanceCm = measureDistanceCm();

  if (distanceCm < 0) {
    sensorTimeoutSeen = true;
    setBuzzer(false); // khong doan canh bao khi khong co du lieu tin cay
    Serial.println(F("{\"distance_cm\":null,\"level_pct\":null,\"alert\":null,\"status\":\"sensor_timeout\"}"));
    return;
  }
  sensorTimeoutSeen = false;

  // Quy doi khoang cach -> % muc nuoc, gioi han 0-100
  float levelPct = (SENSOR_TO_EMPTY_CM - distanceCm) /
                    (SENSOR_TO_EMPTY_CM - SENSOR_TO_FULL_CM) * 100.0;
  if (levelPct < 0) levelPct = 0;
  if (levelPct > 100) levelPct = 100;

  const char* alert = "normal";
  bool buzzerOn = false;
  if (levelPct <= LOW_LEVEL_ALERT_PCT) {
    alert = "low_water";
    buzzerOn = true;
  } else if (levelPct >= HIGH_LEVEL_ALERT_PCT) {
    alert = "high_water";
    buzzerOn = true;
  }
  setBuzzer(buzzerOn);

  Serial.print(F("{\"distance_cm\":"));
  Serial.print(distanceCm, 1);
  Serial.print(F(",\"level_pct\":"));
  Serial.print(levelPct, 1);
  Serial.print(F(",\"alert\":\""));
  Serial.print(alert);
  Serial.println(F("\",\"status\":\"ok\"}"));
}

7. Lỗi thường gặp

Lỗi

Nguyên nhân

Cách sửa

pulseIn() luôn trả về 0 (timeout)

Cảm biến hướng lệch khỏi mặt nước phẳng, hoặc khoảng cách vượt quá 400cm tầm đo HC-SR04

Đảm bảo cảm biến vuông góc với mặt nước, khoảng cách lắp đặt trong tầm đo 2-400cm

Giá trị đo nhảy loạn (nhiễu) khi có gió/sóng nước

Sóng gợn trên mặt nước làm phản xạ âm thanh không ổn định

Lọc trung bình động (moving average) nhiều lần đo, hoặc tăng chu kỳ đo lên vài giây

ESP32 hỏng GPIO sau thời gian dài sử dụng ngoài trời

Không dùng cầu phân áp trên chân ECHO, GPIO liên tục chịu xung 5V vượt ngưỡng chịu đựng

Bắt buộc dùng cầu phân áp trở (1kΩ+2kΩ) hoặc level-shifter trên ECHO trước khi nối GPIO27

Buzzer kêu liên tục dù mực nước bình thường

Ngưỡng cảnh báo đặt sai (LOW/HIGH ngược), hoặc SENSOR_TO_EMPTY_CM/SENSOR_TO_FULL_CM chưa hiệu chỉnh theo ao thực tế

Đo thực tế khoảng cách khi ao cạn và khi ao đầy để hiệu chỉnh 2 hằng số này

8. Tổng kết

Hệ thống theo dõi mực nước ao nuôi này giúp phát hiện sớm tình trạng nước quá thấp hoặc quá cao mà không cần cảm biến tiếp xúc trực tiếp với nước, phù hợp với môi trường ao nuôi thủy sản khắc nghiệt.

Cảnh báo tại chỗ bằng buzzer đảm bảo người vận hành biết ngay cả khi không có kết nối mạng.

Có thể mở rộng bằng cách gửi dữ liệu mực nước qua MQTT lên dashboard giám sát nhiều ao cùng lúc, hoặc tích hợp điều khiển bơm nước tự động qua relay khi mực nước xuống dưới ngưỡng an toàn.