// Smart Water Leak Detection System — with OLED + tone() buzzer
#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SENSOR_PIN 4
#define LED_RED 18
#define LED_GREEN 19
#define BUZZER_PIN 5
#define RELAY_PIN 23
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define OLED_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
bool leakDetected = false;
unsigned long lastUpdateTime = 0;
unsigned long lastBuzzTime = 0;
bool buzzState = false;
void updateDisplay(bool leak);
void setup() {
Serial.begin(115200);
pinMode(SENSOR_PIN, INPUT_PULLUP);
pinMode(LED_RED, OUTPUT);
pinMode(LED_GREEN, OUTPUT);
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(LED_RED, LOW);
digitalWrite(LED_GREEN, HIGH);
digitalWrite(RELAY_PIN, HIGH);
noTone(BUZZER_PIN);
if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDRESS)) {
Serial.println("OLED init failed!");
while (true);
}
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(2);
display.setCursor(10, 10);
display.println("WaterGuard");
display.setTextSize(1);
display.setCursor(20, 38);
display.println("Leak Detection v1.0");
display.setCursor(28, 52);
display.println("Initializing...");
display.display();
delay(2000);
Serial.println("WaterGuard ready. Monitoring started.");
}
void loop() {
int sensorValue = digitalRead(SENSOR_PIN);
unsigned long now = millis();
if (sensorValue == LOW) {
if (!leakDetected) {
leakDetected = true;
Serial.println("LEAK DETECTED! Triggering alerts...");
}
activateAlerts(now);
} else {
if (leakDetected) {
leakDetected = false;
Serial.println("Leak cleared. Resuming normal operation.");
}
normalOperation();
}
if (now - lastUpdateTime >= 500) {
lastUpdateTime = now;
updateDisplay(leakDetected);
Serial.print("[STATUS] Sensor: ");
Serial.print(sensorValue == LOW ? "WET" : "DRY");
Serial.print(" Valve: ");
Serial.print(leakDetected ? "CLOSED" : "OPEN");
Serial.print(" Alert: ");
Serial.println(leakDetected ? "ACTIVE" : "OFF");
}
}
void activateAlerts(unsigned long now) {
digitalWrite(LED_RED, HIGH);
digitalWrite(LED_GREEN, LOW);
digitalWrite(RELAY_PIN, LOW);
// Non-blocking beep: 200ms on / 200ms off using tone()
if (now - lastBuzzTime >= 200) {
lastBuzzTime = now;
buzzState = !buzzState;
if (buzzState) {
tone(BUZZER_PIN, 1000); // 1000 Hz beep
} else {
noTone(BUZZER_PIN);
}
}
}
void normalOperation() {
digitalWrite(LED_RED, LOW);
digitalWrite(LED_GREEN, HIGH);
digitalWrite(RELAY_PIN, HIGH);
noTone(BUZZER_PIN);
}
void updateDisplay(bool leak) {
display.clearDisplay();
if (leak) {
display.fillRect(0, 0, 128, 16, WHITE);
display.setTextColor(BLACK);
display.setTextSize(1);
display.setCursor(20, 4);
display.println("!! LEAK DETECTED !!");
display.setTextColor(WHITE);
display.setTextSize(2);
display.setCursor(28, 20);
display.println("ALERT!");
display.setTextSize(1);
display.setCursor(0, 42);
display.println("Valve: CLOSED");
display.setCursor(0, 52);
display.println("Buzzer: ACTIVE");
} else {
display.fillRect(0, 0, 128, 16, WHITE);
display.setTextColor(BLACK);
display.setTextSize(1);
display.setCursor(28, 4);
display.println("WaterGuard v1.0");
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0, 22);
display.println("Status: NORMAL");
display.setCursor(0, 32);
display.println("Sensor: DRY");
display.setCursor(0, 42);
display.println("Valve: OPEN");
display.setCursor(0, 52);
display.println("Alert: OFF");
}
display.display();
}