// issue >> the buzzer on for 18 seconds
// the button delay in working if the measurement kept on updating
// eg . the water lvl measurement is unstable
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHTesp.h>
#define PIN_TRIG 5
#define PIN_ECHO 18
#define ON_LED 0
#define ALERT_LED 17
#define TANK_HEIGHT_CM 300
#define BUZZER_ALARM 23
#define BUZZER_DURATION_MS 5000 // set as 300000ms
#define PUSH_BUTTON 13
#define DHT_22 33
LiquidCrystal_I2C lcd(0x27, 16, 2);
DHTesp dhtSensor;
///
unsigned long buzzerStartTime = 0; // store the time when the buzzer was turned on
bool buzzerActive = false; // track the buzzer state
///
bool warningOrNormalDetected = false; // track if warning or normal level was detected
unsigned long previousMillis = 0; // stores the last time LED was updated
const long interval = 500; // interval at which to blink (in milliseconds)
bool ledState = LOW; // current state of the LED
// Variable to track the current display mode
enum DisplayMode { WATER_LEVEL, TEMPERATURE, HUMIDITY };
DisplayMode currentDisplayMode = HUMIDITY; // Start with Water Level display
// Variables to store previous sensor values
int prevWaterLevel = -1;
float prevTemperature = -1.0;
float prevHumidity = -1.0;
void setup() {
Serial.begin(115200); // Baud rate of ESP32
pinMode(PIN_TRIG, OUTPUT);
pinMode(PIN_ECHO, INPUT);
pinMode(ON_LED, OUTPUT);
pinMode(ALERT_LED, OUTPUT);
pinMode(BUZZER_ALARM, OUTPUT);
pinMode(PUSH_BUTTON, INPUT_PULLUP); // Use internal pull-up resistor
digitalWrite(ON_LED, HIGH);
digitalWrite(ALERT_LED, LOW);
digitalWrite(BUZZER_ALARM, LOW);
dhtSensor.setup(DHT_22, DHTesp::DHT22);
lcd.init();
lcd.backlight();
displayMsg("System Initialize", "Please wait...");
displayMsg("Water Level", "Monitoring");
}
void displayMsg(String message1, String message2) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(message1);
lcd.setCursor(0, 1);
lcd.print(message2);
delay(3000);
}
int measureWaterLvl() {
digitalWrite(PIN_TRIG, LOW);
delayMicroseconds(2);
digitalWrite(PIN_TRIG, HIGH);
delayMicroseconds(10);
digitalWrite(PIN_TRIG, LOW);
int duration = pulseIn(PIN_ECHO, HIGH);
return duration * 0.0343 / 2; // Convert duration to distance (cm)
}
int calcWaterLevel(int distanceCM) {
return distanceCM; // Update here later for water level
}
void handleWarningLevel() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
ledState = !ledState; // Toggle LED state
digitalWrite(ALERT_LED, ledState); // Update LED state
}
digitalWrite(BUZZER_ALARM, LOW);
noTone(BUZZER_ALARM);
buzzerActive = false;
warningOrNormalDetected = true; // Set warning/normal detection flag
}
void handleCriticalLevel() {
digitalWrite(ALERT_LED, HIGH);
if (!buzzerActive && warningOrNormalDetected) {
digitalWrite(BUZZER_ALARM, HIGH);
tone(BUZZER_ALARM, 1000);
buzzerStartTime = millis();
buzzerActive = true;
warningOrNormalDetected = false; // Reset warning/normal detection flag
}
}
void handleNormalLevel() {
digitalWrite(ALERT_LED, LOW);
digitalWrite(BUZZER_ALARM, LOW);
noTone(BUZZER_ALARM);
buzzerActive = false;
warningOrNormalDetected = true;
}
void checkBuzzer() {
if (buzzerActive && (millis() - buzzerStartTime >= BUZZER_DURATION_MS)) {
noTone(BUZZER_ALARM); // Turn off the buzzer
buzzerActive = false;
}
}
String waterLvlStatus(int waterLevel) {
if (waterLevel <= 50) {
return "CRITICAL";
} else if (waterLevel <= 150) {
return "WARNING";
} else {
return "NORMAL";
}
}
String tempStatus(float temperature) {
if (temperature < 5.0 || temperature > 45.0) {
return "WARNING";
} else {
return "NORMAL";
}
}
String humStatus(float humidity) {
if (humidity < 20.0 || humidity > 80.0) {
return "WARNING";
} else {
return "NORMAL";
}
}
void displayWaterLevel(int waterLevel) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("WaterLvl: ");
lcd.print(waterLevel);
lcd.print(" cm");
lcd.setCursor(0, 1);
lcd.print("Status: ");
lcd.print(waterLvlStatus(waterLevel));
}
void displayTemperature(float temperature) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Temp: ");
lcd.print(temperature, 1);
lcd.print(" degC");
lcd.setCursor(0, 1);
lcd.print("Status: ");
lcd.print(tempStatus(temperature));
}
void displayHumidity(float humidity) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Hum: ");
lcd.print(humidity, 1);
lcd.print(" %RH");
lcd.setCursor(0, 1);
lcd.print("Status: ");
lcd.print(humStatus(humidity));
}
void loop() {
int distanceCM = measureWaterLvl();
int waterLevel = calcWaterLevel(distanceCM);
TempAndHumidity data = dhtSensor.getTempAndHumidity();
float temperature = data.temperature;
float humidity = data.humidity;
/// HEREEEE CHECK BALIK ---------------------------------------------------------------------
// Check if button is pressed
int buttonState = digitalRead(PUSH_BUTTON); // Read the button state
static unsigned long lastButtonPress = 0;
static bool buttonPressed = false;
if (buttonState == LOW) { // Button pressed
if (!buttonPressed && (millis() - lastButtonPress > 500)) { // Debounce and state change
lastButtonPress = millis(); // Update last button press time
buttonPressed = true; // Set button pressed state
// Switch display mode
switch (currentDisplayMode) {
case WATER_LEVEL:
currentDisplayMode = TEMPERATURE;
break;
case TEMPERATURE:
currentDisplayMode = HUMIDITY;
break;
case HUMIDITY:
currentDisplayMode = WATER_LEVEL;
break;
}
}
} else {
buttonPressed = false; // Reset button pressed state when button is released
}
// Update the display based on the current display mode if there is a change in readings
static unsigned long lastUpdateMillis = 0;
const unsigned long updateInterval = 1000; // Update interval for display (1 second)
switch (currentDisplayMode) {
case WATER_LEVEL:
if (waterLevel != prevWaterLevel || (millis() - lastUpdateMillis >= updateInterval)) { // Check for change or time interval
displayWaterLevel(waterLevel);
prevWaterLevel = waterLevel;
lastUpdateMillis = millis();
}
break;
case TEMPERATURE:
if (temperature != prevTemperature || (millis() - lastUpdateMillis >= updateInterval)) { // Check for change or time interval
displayTemperature(temperature);
prevTemperature = temperature;
lastUpdateMillis = millis();
}
break;
case HUMIDITY:
if (humidity != prevHumidity || (millis() - lastUpdateMillis >= updateInterval)) { // Check for change or time interval
displayHumidity(humidity);
prevHumidity = humidity;
lastUpdateMillis = millis();
}
break;
}
////// -----------------------------------------------------------------------------------------
// handle alarm and led
if (waterLevel <= 50) {
handleCriticalLevel();
} else if (waterLevel <= 150) {
handleWarningLevel();
} else {
handleNormalLevel();
}
checkBuzzer();
}