#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// Pin definitions
const int relayPin = 10;
const int lowerSensorPin = 8;
const int upperSensorPin = 9;
const int thirdSensorPin = 5;
const int specialPin = 13;
const int buzzerPin = 12;
const int pin6 = 6;
const int resetButtonPin = 11;
const int modeSwitchPin = 7;
const int manualControlPin = 4;
// OLED display setup
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Variables
bool motorState = false;
unsigned long motorOffTime = 0;
unsigned long buzzerStartTime = 0;
bool buzzerActive = false;
unsigned long motorOnTime = 0;
unsigned long pin6LowTime = 0;
bool dryRun = false;
bool resetRequired = false;
bool manualMotorState = false;
bool lastAutoMode = false;
unsigned long autoModeOffTime = 0;
bool autoModeOffTimerSet = false;
unsigned long lastBlinkTime = 0; // Track the last time "Low" was shown
bool blinkState = false; // Track the blink state
void setup() {
pinMode(relayPin, OUTPUT);
pinMode(lowerSensorPin, INPUT);
pinMode(upperSensorPin, INPUT);
pinMode(thirdSensorPin, INPUT);
pinMode(specialPin, INPUT);
pinMode(buzzerPin, OUTPUT);
pinMode(pin6, INPUT);
pinMode(resetButtonPin, INPUT_PULLUP);
pinMode(modeSwitchPin, INPUT_PULLUP);
pinMode(manualControlPin, INPUT_PULLUP);
digitalWrite(relayPin, LOW);
digitalWrite(buzzerPin, LOW);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 initialization failed!"));
for (;;);
}
// Custom Splash Screen
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(21, 20);
display.println("KAYYALA");
display.setTextSize(1);
display.setCursor(10, 40);
display.println("Water Level System");
display.display();
delay(7000);
display.clearDisplay();
}
void loop() {
// Read sensor and pin states
bool lowerSensor = digitalRead(lowerSensorPin);
bool upperSensor = digitalRead(upperSensorPin);
bool thirdSensor = digitalRead(thirdSensorPin);
bool specialCondition = digitalRead(specialPin);
bool pin6State = digitalRead(pin6);
bool resetButton = digitalRead(resetButtonPin);
bool autoMode = !digitalRead(modeSwitchPin);
bool manualControlButton = digitalRead(manualControlPin) == LOW;
// Turn motor OFF and reset manual motor state if any mode change occurs
if (lastAutoMode != autoMode) {
motorState = false;
manualMotorState = false;
autoModeOffTimerSet = false;
}
lastAutoMode = autoMode;
// Reset condition: clear dry run flag and reset motor state
if (resetButton == LOW) {
dryRun = false;
resetRequired = false;
motorState = false;
digitalWrite(relayPin, LOW);
digitalWrite(buzzerPin, LOW);
buzzerActive = false;
delay(500);
}
if (dryRun) {
// If dry run is active, disable the Auto/Manual switch
digitalWrite(relayPin, LOW);
if (!buzzerActive) {
buzzerStartTime = millis();
buzzerActive = true;
digitalWrite(buzzerPin, HIGH);
}
if (millis() - buzzerStartTime >= 3000) {
digitalWrite(buzzerPin, LOW);
buzzerActive = false;
}
} else if (autoMode && !resetRequired) {
// Automatic mode
if (specialCondition == HIGH) {
motorOffTime = millis() + 50000;
motorState = false;
} else if (millis() < motorOffTime) {
motorState = false;
} else if (lowerSensor == LOW) {
if (!motorState) {
motorState = true;
motorOnTime = millis();
pin6LowTime = millis();
dryRun = false;
beepBuzzer(3);
}
} else if (lowerSensor == HIGH && upperSensor == HIGH) {
if (!autoModeOffTimerSet) {
autoModeOffTime = millis() + 5000;
autoModeOffTimerSet = true;
} else if (millis() >= autoModeOffTime) {
motorState = false;
}
} else {
autoModeOffTimerSet = false;
}
if (manualControlButton && lowerSensor == HIGH && upperSensor == LOW) {
motorState = true;
pin6LowTime = millis();
beepBuzzer(3);
}
if (motorState && pin6State == LOW && millis() - pin6LowTime >= 50000) {
motorState = false;
dryRun = true;
resetRequired = true;
buzzerStartTime = millis();
buzzerActive = true;
} else if (motorState && pin6State == HIGH) {
pin6LowTime = millis();
}
} else if (!autoMode) {
// Manual mode
if (manualControlButton) {
manualMotorState = !manualMotorState;
delay(1000);
}
motorState = manualMotorState;
dryRun = false;
// Blinking "Low" condition
if (lowerSensor == LOW && thirdSensor == LOW) {
if (millis() - lastBlinkTime >= 1000) {
blinkState = !blinkState;
lastBlinkTime = millis();
}
} else {
blinkState = false;
}
}
// Control relay
if (!dryRun) {
digitalWrite(relayPin, motorState ? HIGH : LOW);
} else {
digitalWrite(relayPin, LOW);
}
// Update display
display.clearDisplay();
if (dryRun) {
display.setCursor(0, 2); //0 , 0
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.println(" Dry Run");
display.setTextSize(1);
display.setCursor(0, 50);
display.println("Motor OFF");
display.setCursor(0, 30);
display.println(" Check Motor");
} else {
display.setCursor(0, 0);
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
if (lowerSensor == LOW && upperSensor == LOW && thirdSensor == LOW) {
display.println("Tank Low");
drawTankLevel(24);
} else if (lowerSensor == HIGH && upperSensor == HIGH && thirdSensor == HIGH) {
display.println("Tank Full");
drawTankLevel(83);
} else if (lowerSensor == HIGH && upperSensor == LOW && thirdSensor == HIGH) {
display.println("Tank Mediu");
drawTankLevel(65);
} else {
display.println("Tank Half");
drawTankLevel(45);
}
// Blink "Low" text in Manual mode
if (!autoMode && lowerSensor == LOW && thirdSensor == LOW && blinkState) {
display.setCursor(0, 30);
display.setTextSize(1);
display.println(" Low");
}
display.setTextSize(1);
display.setCursor(0, 40);
display.print("Motor: ");
display.println(motorState ? "ON" : "OFF");
display.setCursor(0, 52);
display.print("Mode : ");
display.println(autoMode ? "Auto" : "Manual");
}
display.display();
delay(1000);
}
// Function to beep the buzzer
void beepBuzzer(int times) {
for (int i = 0; i < times; i++) {
digitalWrite(buzzerPin, HIGH);
delay(100);
digitalWrite(buzzerPin, LOW);
delay(100);
}
}
void drawTankLevel(int level) {
// Draw the tank outline///
display.drawRect(90, 18, 30, 40, SSD1306_WHITE); // 90, 19, 30, 40,
// Draw the tank with out Top line//
//display.drawLine(90, 19, 90, 59, SSD1306_WHITE); // Left line
//display.drawLine(120, 19, 120, 59, SSD1306_WHITE); // Right line
//display.drawLine(90, 59, 120, 59, SSD1306_WHITE); // Bottom line 59
// Calculate the height of the filled portion
int fillHeight = map(level, 0, 100, 0, 40); // 0 , 100, 0, 40
// Draw the filled portion
display.fillRect(91, 57 - fillHeight, 28, fillHeight, SSD1306_WHITE); //91,58, 28
}