#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <NewPing.h> // Include the NewPing library for HC-SR04
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define TRIGGER_PIN 2 // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN 3 // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 400 // Maximum distance we want to ping for (in centimeters).
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.
int potPin = A0; // Analog pin connected to the potentiometer
int tankHeight = 200; // Default total tank height in centimeters
int waterLevel = 0; // Current water level percentage
const int relayPin = 4; // Pin connected to relay
const int buttonPin = 6; // Pin connected to push button
bool manualOverride = false; // Manual relay override flag
bool relayState = false; // Current state of the relay
void setup()
{
Serial.begin(9600);
// Initialize relay and button pins
pinMode(relayPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP); // Button pin with internal pull-up resistor
// Initialize potentiometer pin
pinMode(potPin, INPUT);
// Initialize OLED display
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C))
{
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.clearDisplay(); // Clear the display buffer
display.display(); // Display the cleared buffer
delay(2000); // Pause for 2 seconds
display.clearDisplay(); // Clear the display buffer again
}
void loop()
{
// Read potentiometer value and map it to tank height range (2cm to 400cm)
int potValue = analogRead(potPin);
tankHeight = map(potValue, 0, 1023, 2, 400);
// Measure distance with HC-SR04 and calculate water level percentage
unsigned int distance = sonar.ping_cm(); // Get distance in centimeters
// Calculate water level percentage
if (distance != 0 && distance <= tankHeight)
{
waterLevel = map(distance, 0, tankHeight, 100, 0); // Invert mapping for display
waterLevel = constrain(waterLevel, 0, 100); // Ensure waterLevel is between 0 and 100%
}
else
{
waterLevel = 0; // No water detected or out of range
}
// Manual override logic (button toggles relay state only if water level < 90%)
if (waterLevel < 90 && digitalRead(buttonPin) == LOW)
{
delay(200); // Simple debounce delay
if (digitalRead(buttonPin) == LOW) // If button is still pressed after debounce
{
manualOverride = !manualOverride; // Toggle manual override mode
relayState = !relayState; // Toggle relay state
digitalWrite(relayPin, relayState ? LOW : HIGH); // Update relay (low active type)
}
while (digitalRead(buttonPin) == LOW); // Wait until button is released
}
// Ensure relay turns off if water level exceeds 98%, even in manual override mode
if (waterLevel > 98)
{
relayState = false; // Turn relay off
digitalWrite(relayPin, HIGH); // Deactivate relay
manualOverride = false; // Exit manual override mode
}
// Auto control logic when not manually overridden and water level below 10%
if (!manualOverride && waterLevel < 10)
{
relayState = true; // Turn relay on
digitalWrite(relayPin, LOW); // Activate relay (low active type)
}
// Exit manual override mode and activate relay if water level drops below 10%
if (waterLevel < 10)
{
manualOverride = false; // Exit manual override mode
relayState = true; // Turn relay on
digitalWrite(relayPin, LOW); // Activate relay (low active type)
}
display.clearDisplay();
// Draw tank outline (vertical)
display.drawRect(10, 18, 34, 44, WHITE);
// Calculate bar height increment based on the tank height and the number of bars
int barHeightIncrement = 40 / 4; // Adjust this value based on the tank height and the number of bars
int barWidth = 30; // Width of each bar
// Determine which bar to show based on water level percentage
int numBars = 0;
if (waterLevel >= 10 && waterLevel <= 24)
{
numBars = 1;
}
else if (waterLevel >= 25 && waterLevel <= 49)
{
numBars = 2;
}
else if (waterLevel >= 50 && waterLevel <= 74)
{
numBars = 3;
}
else if (waterLevel >= 75 && waterLevel <= 100)
{
numBars = 4;
}
// Draw bars
for (int i = 0; i < numBars; i++)
{
int barHeight = 50 - i * barHeightIncrement; // Calculate bar height from bottom up
display.fillRect(12, barHeight, barWidth, 10, WHITE); // Draw bars vertically
}
// Display pump status based on relay state
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(49, 45);
if (digitalRead(relayPin) == LOW)
{
display.print("Pump: ON"); // Display pump is on
}
else
{
display.print("Pump: OFF"); // Display pump is off
}
// Headline
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(10, 5);
display.print("Smart Tank Monitor");
// Display water level percentage
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(49, 18);
display.print("Water Level: ");
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(55, 30);
display.print(waterLevel);
display.print("%");
// Display tank height setting
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(49, 55);
display.print("Tank(H):");
display.print(tankHeight);
display.print("cm");
display.display();
delay(1000); // Adjust delay as needed for refresh rate
}