//Monitoring the Tank water level
#include <WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
#include <EEPROM.h>
#include <LiquidCrystal_I2C.h>
// Function prototypes
long microsecondsToInches(long microseconds);
long microsecondsToCentimeters(long microseconds);
void connectToWiFi();
void printWiFiStatus();
void connectToAdafruit();
// Initialize I2C LCD (change address if needed)
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Adafruit IO credentials
#define AIO_SERVER "io.adafruit.com" // adafruit server
#define AIO_SERVERPORT 1883
#define AIO_USERNAME "kamaladhi" //adafruit username
#define AIO_KEY "aio_TWZW3153YXMV2m3w2FGhLoFLxTiT" //adafruit api key
//MQTT is used here
WiFiClient client;
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
Adafruit_MQTT_Publish send = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/water-level");
// Pin definitions
const int trigPin = 13; // ultrasonic sensor trigger pin
const int echoPin = 12; // ultrasonic sensor echo pin
const int relayPin = 14; //relay pin
int lastPublishedPercentage = -1;
// Variables declaration
long duration, inches;
int set_val, percentage;
bool pump;
// WiFi credentials
const char* ssid = "Wokwi-GUEST";
const char* password = "";
void setup() {
Serial.begin(115200);
delay(1000); // Wait for serial monitor
// Initialize LCD
lcd.init();
lcd.backlight();
lcd.print("Initializing...");
// Initialize pins
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(relayPin, OUTPUT);
digitalWrite(relayPin, HIGH); // Relay off initially
// Initialize EEPROM
EEPROM.begin(512);
set_val = EEPROM.read(0);
if (set_val > 150 || set_val <= 0) {
set_val = 100; // Default value
EEPROM.write(0, set_val);
EEPROM.commit();
}
// Connect to WiFi
connectToWiFi();
// Initialize MQTT
if (WiFi.status() == WL_CONNECTED) {
connectToAdafruit();
}
}
void loop() {
// Check WiFi connection
if (WiFi.status() != WL_CONNECTED) {
lcd.clear();
lcd.print("WiFi Disconnected");
printWiFiStatus();
connectToWiFi();
delay(5000);
return;
}
// Check MQTT connection
if (!mqtt.ping(3) && !mqtt.connected()) {
lcd.clear();
lcd.print("MQTT Disconnected");
connectToAdafruit();
delay(5000);
return;
}
// Read water level
digitalWrite(trigPin, LOW); //trig pin of ultrasonic sensor
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH, 30000); // 30ms timeout
if (duration == 0) {
Serial.println("Sensor timeout");
lcd.clear();
lcd.print("Sensor Error");
delay(2000);
return;
}
//converts the timetaken for the ultrasonic pulse to bounce back into inches
inches = microsecondsToInches(duration);
percentage = (set_val - inches) * 100 / set_val;//Calculates the water level percentage
percentage = constrain(percentage, 0, 100);
// Display water level
lcd.clear();
lcd.print("WATER LEVEL:");
lcd.setCursor(12, 0);
lcd.print(percentage);
lcd.print("%");
// Control pump
pump = (percentage < 30);
digitalWrite(relayPin, !pump);
lcd.setCursor(0, 1);
lcd.print("PUMP: ");
lcd.print(pump ? "ON " : "OFF");
// Publish to Adafruit IO
if (abs(percentage - lastPublishedPercentage) >= 1) {
if (!send.publish((int32_t)percentage)) {
Serial.println("Publish failed");
} else {
Serial.println("Published");
lastPublishedPercentage = percentage; // Update last published value
}
}
delay(2000); // Wait between readings
}
// Error Handling ....................................................................
// WiFi connection function
void connectToWiFi() {
Serial.println("\nConnecting to WiFi...");
lcd.clear();
lcd.print("Connecting WiFi");
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
WiFi.begin(ssid, password);
unsigned long startTime = millis();
while (WiFi.status() != WL_CONNECTED && millis() - startTime < 20000) {
delay(500);
Serial.print(".");
lcd.print(".");
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nConnected!");
Serial.print("IP: ");
Serial.println(WiFi.localIP());
lcd.clear();
lcd.print("WiFi Connected");
lcd.setCursor(0, 1);
lcd.print("IP: ");
lcd.print(WiFi.localIP().toString());
delay(2000);
} else {
Serial.println("\nConnection Failed!");
lcd.clear();
lcd.print("WiFi Failed!");
printWiFiStatus();
}
}
// Adafruit IO connection function
void connectToAdafruit() {
Serial.print("Connecting to Adafruit IO... ");
lcd.clear();
lcd.print("Connecting MQTT");
int8_t ret;
int attempts = 0;
while ((ret = mqtt.connect()) != 0 && attempts < 3) {
attempts++;
switch (ret) {
case 1: Serial.println("Wrong protocol"); break;
case 2: Serial.println("ID rejected"); break;
case 3: Serial.println("Server unavailable"); break;
case 4: Serial.println("Bad credentials"); break;
default: Serial.println("Connection failed"); break;
}
lcd.clear();
lcd.print("MQTT Fail ");
lcd.print(attempts);
delay(5000);
}
if (mqtt.connected()) {
Serial.println("Connected!");
lcd.clear();
lcd.print("MQTT Connected");
delay(1000);
} else {
Serial.println("Failed after 3 attempts");
lcd.clear();
lcd.print("MQTT Failed");
}
}
// WiFi status printer
void printWiFiStatus() {
Serial.print("WiFi Status: ");
switch(WiFi.status()) {
case WL_NO_SHIELD: Serial.println("No WiFi shield"); break;
case WL_IDLE_STATUS: Serial.println("Idle"); break;
case WL_NO_SSID_AVAIL: Serial.println("SSID not available"); break;
case WL_SCAN_COMPLETED: Serial.println("Scan completed"); break;
case WL_CONNECTED: Serial.println("Connected"); break;
case WL_CONNECT_FAILED: Serial.println("Connect failed"); break;
case WL_CONNECTION_LOST: Serial.println("Connection lost"); break;
case WL_DISCONNECTED: Serial.println("Disconnected"); break;
default: Serial.println("Unknown status"); break;
}
}
//...........................................................................
//helper functions :
// Conversion functions
long microsecondsToInches(long microseconds) {
return microseconds / 74 / 2;
}
long microsecondsToCentimeters(long microseconds) {
return microseconds / 29 / 2;
}