#include <EEPROM.h> // Thư viện EEPROM để lưu trữ dữ liệu không mất đi khi tắt nguồn
#include <LiquidCrystal.h> // Thư viện điều khiển màn hình LCD
LiquidCrystal lcd(2, 3, 4, 5, 6, 7); // Khởi tạo đối tượng LCD với các chân kết nối
long duration, inches; // Biến lưu thời gian và khoảng cách đo được
int set_val, percentage; // Biến lưu giá trị cài đặt và phần trăm mức nước
bool state, pump; // Biến trạng thái nút nhấn và trạng thái bơm
void setup() {
lcd.begin(16, 2); // Khởi tạo màn hình LCD với kích thước 16x2
lcd.print("WATER LEVEL:"); // Hiển thị "WATER LEVEL:" trên dòng đầu tiên
lcd.setCursor(0, 1); // Di chuyển con trỏ đến đầu dòng thứ hai
lcd.print("PUMP:OFF MANUAL"); // Hiển thị trạng thái bơm và chế độ ban đầu
pinMode(8, OUTPUT); // Chân 8 làm OUTPUT (TRIG của cảm biến siêu âm)
pinMode(9, INPUT); // Chân 9 làm INPUT (ECHO của cảm biến siêu âm)
pinMode(10, INPUT_PULLUP); // Chân 10 làm INPUT với điện trở kéo lên (nút nhấn)
pinMode(11, INPUT_PULLUP); // Chân 11 làm INPUT với điện trở kéo lên (công tắc chế độ)
pinMode(12, OUTPUT); // Chân 12 làm OUTPUT (điều khiển rơ le bơm)
set_val = EEPROM.read(0); // Đọc giá trị cài đặt từ EEPROM
if (set_val > 150) set_val = 150; // Giới hạn giá trị cài đặt tối đa là 150
}
void loop() {
// Kích hoạt cảm biến siêu âm để đo khoảng cách
digitalWrite(3, LOW); // Đảm bảo chân 3 ở mức LOW
delayMicroseconds(2); // Chờ 2 micro giây
digitalWrite(8, HIGH); // Chân 8 lên mức HIGH
delayMicroseconds(10); // Giữ trong 10 micro giây
digitalWrite(8, LOW); // Đưa chân 8 xuống mức LOW
duration = pulseIn(9, HIGH);// Đo thời gian tín hiệu ECHO ở mức HIGH
inches = microsecondsToInches(duration); // Chuyển đổi thời gian thành khoảng cách (inch)
// Tính toán phần trăm mức nước hiện tại
percentage = (set_val - inches) * 100 / set_val;
lcd.setCursor(12, 0); // Di chuyển con trỏ đến vị trí hiển thị phần trăm
if (percentage < 0) percentage = 0; // Nếu phần trăm âm, đặt bằng 0
lcd.print(percentage); // Hiển thị phần trăm mức nước
lcd.print("% "); // Hiển thị ký hiệu '%' và xóa các ký tự thừa
// Điều khiển bơm dựa trên mức nước và chế độ hoạt động
if (percentage < 30 && digitalRead(11)) pump = 1; // Nếu mức nước dưới 30% và ở chế độ tự động, bật bơm
if (percentage > 99) pump = 0; // Nếu mức nước trên 99%, tắt bơm
digitalWrite(12, !pump); // Điều khiển rơ le bơm (chân 12)
// Cập nhật trạng thái bơm trên LCD
lcd.setCursor(5, 1); // Di chuyển con trỏ đến vị trí hiển thị trạng thái bơm
if (pump == 1) lcd.print("ON "); // Nếu bơm đang bật, hiển thị "ON "
else if (pump == 0) lcd.print("OFF"); // Nếu bơm tắt, hiển thị "OFF"
// Hiển thị chế độ hoạt động (TỰ ĐỘNG hoặc THỦ CÔNG)
lcd.setCursor(9, 1); // Di chuyển con trỏ đến vị trí hiển thị chế độ
if (!digitalRead(11)) lcd.print("MANUAL"); // Nếu công tắc ở chế độ THỦ CÔNG, hiển thị "MANUAL"
else lcd.print("AUTO "); // Nếu ở chế độ TỰ ĐỘNG, hiển thị "AUTO "
// Xử lý nút nhấn trong chế độ TỰ ĐỘNG
if (!digitalRead(10) && digitalRead(11)) {
state = 1; // Đánh dấu nút nhấn đã được xử lý
set_val = inches; // Cập nhật giá trị cài đặt với khoảng cách hiện tại
EEPROM.write(0, set_val); // Lưu giá trị cài đặt vào EEPROM
}
// Xử lý nút nhấn trong chế độ THỦ CÔNG
if (!digitalRead(10) && !state && !digitalRead(11)) {
state = 1; // Đánh dấu nút nhấn đã được xử lý
pump = !pump; // Đổi trạng thái bơm
}
if (digitalRead(10)) state = 0; // Nếu nút nhấn không được nhấn, đặt lại trạng thái
delay(500); // Chờ 500ms trước khi lặp lại
}
long microsecondsToInches(long microseconds) {
return microseconds / 74 / 2; // Chuyển đổi micro giây thành inch
}