// Advanced Automatic Water Dispenser with LED, Buzzer Alerts, and Blind Detection Beeps
// Features: LCD, Potentiometer refill control, Ultrasonic glass detection,
// Buzzer and 3-color LED status indicators (Green, Yellow, Red),
// Blind-friendly beeps for water level after dispensing
#include <LiquidCrystal.h>
#define TRIG_PIN 7
#define ECHO_PIN 6
#define POT_PIN A0
#define REFILL_BUTTON_PIN 8
#define GREEN_LED_PIN 9
#define YELLOW_LED_PIN 10
#define RED_LED_PIN A1 // Using analog pin as digital
#define BUZZER_PIN A2 // Tank status buzzer
#define BLIND_BUZZER_PIN A3 // New buzzer for blind beeps
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int waterLevelPercent = 100;
unsigned long dispenseStartTime = 0;
bool dispensing = false;
bool glassWasPresent = false;
bool waitingForGlassRemoval = false;
bool allowSensorUpdate = false;
void setup() {
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(REFILL_BUTTON_PIN, INPUT_PULLUP);
pinMode(GREEN_LED_PIN, OUTPUT);
pinMode(YELLOW_LED_PIN, OUTPUT);
pinMode(RED_LED_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(BLIND_BUZZER_PIN, OUTPUT);
lcd.begin(16, 2);
lcd.print("Water Level:");
delay(1000);
int initialLevel = map(analogRead(POT_PIN), 0, 1023, 0, 100);
waterLevelPercent = initialLevel;
showWaterLevel(waterLevelPercent);
}
long readDistanceCM() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duration = pulseIn(ECHO_PIN, HIGH);
return duration * 0.034 / 2;
}
void updateIndicators(int level) {
digitalWrite(GREEN_LED_PIN, level > 50);
digitalWrite(YELLOW_LED_PIN, level <= 50 && level > 10);
digitalWrite(RED_LED_PIN, level <= 10);
if (level <= 0) {
tone(BUZZER_PIN, 1000);
} else {
noTone(BUZZER_PIN);
}
}
void showWaterLevel(int level) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Water Level: ");
lcd.print(level);
lcd.print("%");
lcd.setCursor(0, 1);
if (level <= 10) {
lcd.print("Tank Empty");
} else if (level <= 50) {
lcd.print("Tank Half Full");
} else {
lcd.print("Tank Full");
}
updateIndicators(level);
}
void blindBeepLevel(int percentUsed) {
if (percentUsed >= 7) {
beepCount(3);
} else if (percentUsed >= 4) {
beepCount(2);
} else {
beepCount(1);
}
}
void beepCount(int count) {
for (int i = 0; i < count; i++) {
tone(BLIND_BUZZER_PIN, 1500);
delay(300);
noTone(BLIND_BUZZER_PIN);
delay(200);
}
}
void loop() {
long distance = readDistanceCM();
bool glassPresent = (distance < 5);
bool refillPressed = digitalRead(REFILL_BUTTON_PIN) == LOW;
if (refillPressed) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Filling Tank...");
delay(300);
int potLevel = analogRead(POT_PIN);
int potPercent = map(potLevel, 0, 1023, 0, 100);
waterLevelPercent = potPercent;
showWaterLevel(waterLevelPercent);
delay(500);
return;
}
// Start dispensing
if (!dispensing && glassPresent && !glassWasPresent && waterLevelPercent > 0) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Dispensing Water");
dispensing = true;
dispenseStartTime = millis();
waitingForGlassRemoval = true;
}
// During dispensing
if (dispensing) {
if (!glassPresent && waitingForGlassRemoval) {
unsigned long dispenseDuration = millis() - dispenseStartTime;
float mlDispensed = dispenseDuration / 1000.0; // 1 sec = 1 ml
int percentUsed = mlDispensed * 0.5; // 1 ml = 0.5%
if (percentUsed < 1) percentUsed = 1;
waterLevelPercent -= percentUsed;
if (waterLevelPercent < 0) waterLevelPercent = 0;
showWaterLevel(waterLevelPercent);
blindBeepLevel(percentUsed);
dispensing = false;
waitingForGlassRemoval = false;
} else if (millis() - dispenseStartTime > 15000) {
int percentUsed = 7;
waterLevelPercent -= percentUsed;
if (waterLevelPercent < 0) waterLevelPercent = 0;
showWaterLevel(waterLevelPercent);
blindBeepLevel(percentUsed);
dispensing = false;
waitingForGlassRemoval = false;
}
}
glassWasPresent = glassPresent;
delay(500);
}
Activate water sensor