#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
#define TRIGGER_PIN A3
#define ECHO_PIN A2
#define LED_PIN2 2
#define LED_PIN3 3
#define LED_PIN4 4
#define BUZZER_PIN 13
#define BTN_UP 9
#define BTN_DOWN 12
#define BTN_SELECT 11
#define BTN_MUTE 10
#define LED_1_PIN 5
#define LED_2_PIN 6
#define LED_3_PIN 7
#define LED_4_PIN 8
LiquidCrystal_I2C lcd(0x27, 20, 4);
int maxDistance = 65;
int minDistance = 0;
bool isBuzzerActive = true;
bool isMuteMode = false;
bool screenCleared = false;
bool isEditing = false; // حالة التعديل
int currentMode = 0; // الوضع الحالي
unsigned long lastButtonPressTime = 0;
unsigned long lastSensorReadTime = 0;
const unsigned long sensorReadInterval = 5000; // فترة القراءة من الحساس
unsigned long lastMutePressTime = 0;
const unsigned long muteDebounceDelay = 500;
unsigned long lastBlinkTime = 0;
int blinkInterval = 500;
void setup() {
lcd.begin(20, 4); lcd.begin(20, 4);
lcd.backlight();
pinMode(LED_PIN4, OUTPUT);
pinMode(LED_PIN3, OUTPUT);
pinMode(LED_PIN2, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(LED_1_PIN, OUTPUT);
pinMode(LED_2_PIN, OUTPUT);
pinMode(LED_3_PIN, OUTPUT);
pinMode(LED_4_PIN, OUTPUT);
pinMode(BTN_UP, INPUT_PULLUP);
pinMode(BTN_DOWN, INPUT_PULLUP);
pinMode(BTN_SELECT, INPUT_PULLUP);
pinMode(BTN_MUTE, INPUT_PULLUP);
maxDistance = EEPROM.read(0);
minDistance = EEPROM.read(1);
lcd.setCursor(0, 0);
lcd.print("Tank System");
delay(1000);
if (maxDistance == 255) maxDistance = 165;
if (minDistance == 255) minDistance = 0;
}
bool debounce(int buttonPin) {
bool state = digitalRead(buttonPin);
delay(50); // تأخير بسيط لتجنب القراءات غير الصحيحة
bool state2 = digitalRead(buttonPin);
return state == state2 ? state : false;
}
void loop() {
unsigned long currentTime = millis();
handleEditing();
if (currentTime - lastSensorReadTime > sensorReadInterval) {
int tankLevelCM = getDistance();
displayTankLevel(tankLevelCM);
handleBuzzer(tankLevelCM);
displayMeasuredDistance();
lastSensorReadTime = currentTime;
}
int waterLevelCM = getWaterLevelCM();
controlLEDs(waterLevelCM);
displayModeValues();
handleMute();
handleBlinking();
}
int getDistance() {
// إرسال نبضة للحساس
digitalWrite(TRIGGER_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIGGER_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIGGER_PIN, LOW);
// قراءة زمن الاستجابة
long duration = pulseIn(ECHO_PIN, HIGH);
// حساب المسافة (السنتيمترات)
int distanceCM = duration * 0.034 / 2; // سرعة الصوت 343 متر/ثانية => 0.034 سنتيمتر/ميكروثانية
return distanceCM;
}
int getWaterLevelCM() {
int distanceCM = getDistance();
if (distanceCM == 0 || distanceCM > maxDistance) distanceCM = maxDistance;
return distanceCM;
}
void displayMeasuredDistance() {
int distanceCM = getDistance(); // قياس المسافة من الحساس
// عرض المسافة المقاسة في السطر الثالث
lcd.setCursor(14, 0);
lcd.print("M:");
lcd.print(distanceCM);
}
void handleEditing() {
if (!debounce(BTN_UP) && !debounce(BTN_DOWN)) {
if (millis() - lastButtonPressTime > 500) {
isEditing = !isEditing; // تبديل وضع التعديل
lastButtonPressTime = millis();
}
}
if (!debounce(BTN_SELECT)) {
if (millis() - lastButtonPressTime > 500) {
currentMode = (currentMode + 1) % 4; // التنقل بين الأوضاع المختلفة
lastButtonPressTime = millis();
}
}
if (isEditing) {
if (!debounce(BTN_UP)) {
adjustValue(1);
delay(200); // تأخير لتجنب القراءة المتكررة السريعة
}
if (!debounce(BTN_DOWN)) {
adjustValue(-1);
delay(200); // تأخير لتجنب القراءة المتكررة السريعة
}
}
}
// دالة تعديل القيم بناءً على الوضع الحالي
void adjustValue(int change) {
switch (currentMode) {
case 0:
maxDistance += change;
if (maxDistance < minDistance) maxDistance = minDistance;
EEPROM.write(0, maxDistance);
break;
case 1:
minDistance += change;
if (minDistance > maxDistance) minDistance = maxDistance;
EEPROM.write(1, minDistance);
break;
}
}
void displayTankLevel(int levelCM) {
int remainingWater = maxDistance - levelCM;
lcd.setCursor(0, 0);
lcd.print("Water: ");
lcd.print(remainingWater);
lcd.print(" cm ");
lcd.setCursor(0, 3);
if (levelCM >= maxDistance) {
lcd.print("Tank is empty ");
} else if (levelCM <= minDistance) {
lcd.print("Tank is full ");
} else {
lcd.print(" ");
}
}
void displayModeValues() {
lcd.setCursor(0, 1);
lcd.print("MODE ");
// عرض الوضع الحالي (تحرير أو عرض)
if (isEditing) {
lcd.print("Edit");
} else {
lcd.print("View");
}
// الانتقال إلى السطر الثاني وعرض القيم بناءً على الوضع الحالي
lcd.setCursor(0, 2);
switch (currentMode) {
case 0:
lcd.print("MaxD: ");
lcd.print(maxDistance); // عرض قيمة maxDistance
lcd.print(" cm ");
break;
case 1:
lcd.print("MinD: ");
lcd.print(minDistance); // عرض قيمة minDistance
lcd.print(" cm ");
break;
}
// إظهار أو إخفاء المؤشر بناءً على حالة التعديل
if (isEditing) {
lcd.cursor(); // إظهار المؤشر إذا كان في وضع التحرير
} else {
lcd.noCursor(); // إخفاء المؤشر إذا كان في وضع العرض
}
}
void controlLEDs(int levelCM) {
int remainingWater = maxDistance - levelCM;
digitalWrite(LED_1_PIN, remainingWater <= (maxDistance *0.05) ? LOW : HIGH );
digitalWrite(LED_2_PIN, remainingWater <= (maxDistance * 0.25) ? LOW : HIGH ); // نصف المسافة القصوى
digitalWrite(LED_3_PIN, remainingWater <= (maxDistance * 0.5) ? LOW : HIGH ); // ربع المسافة القصوى
digitalWrite(LED_4_PIN, remainingWater <= (maxDistance*0.9 )? LOW : HIGH );
}
void handleBuzzer(int levelCM) {
static unsigned long lastBuzzerTime = 0;
unsigned long currentTime = millis();
int delayTime = 10000; // 30 seconds
if (levelCM >= maxDistance-5 || levelCM <= minDistance+5) {
if (currentTime - lastBuzzerTime >= delayTime) {
if (isBuzzerActive) {
digitalWrite(BUZZER_PIN, HIGH);
delay(30);
digitalWrite(BUZZER_PIN, LOW);
delay(200);
}
lastBuzzerTime = currentTime;
}
} else {
digitalWrite(BUZZER_PIN, LOW);
}
}
void handleBlinking() {
unsigned long currentTime = millis();
if (getWaterLevelCM() >= maxDistance-10) {
if (currentTime - lastBlinkTime >= blinkInterval) {
digitalWrite(LED_PIN2, !digitalRead(LED_PIN2));
lastBlinkTime = currentTime;
}
} else if (getWaterLevelCM() <= minDistance+15) {
if (currentTime - lastBlinkTime >= blinkInterval) {
digitalWrite(LED_PIN3, !digitalRead(LED_PIN3));
lastBlinkTime = currentTime;
}
}
}
void handleMute() {
if (!debounce(BTN_MUTE)) {
unsigned long currentTime = millis();
if (currentTime - lastMutePressTime > muteDebounceDelay) {
isMuteMode = !isMuteMode;
isBuzzerActive = !isBuzzerActive; // تبديل حالة البزر
lastMutePressTime = currentTime;
}
}
}