/**********************************************************************************
* TITLE: IoT-based Water Level Indicator using ESP32, Ultrasonic Sensor & Blynk with 0.96" OLED
* ... (other comments and includes remain the same)
**********************************************************************************/
/* Fill-in your Template ID (only if using Blynk.Cloud) */
#define BLYNK_TEMPLATE_ID "TMPL6kB7ugv-9"
#define BLYNK_TEMPLATE_NAME "Quickstart Template"
#define BLYNK_AUTH_TOKEN "Your Auth Token"
// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "We 2,4";
char pass[] = "zainabwanda";
// Set Water Level Distance in CM for each sensor
int emptyTankDistance1 = 400; // Distance when tank 1 is empty
int fullTankDistance1 = 30; // Distance when tank 1 is full
int emptyTankDistance2 = 400; // Distance when tank 2 is empty
int fullTankDistance2 = 30; // Distance when tank 2 is full
// Set trigger value in percentage
int triggerPer = 10; // Alarm will start when water level drops below triggerPer
#include <Adafruit_SSD1306.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <AceButton.h>
using namespace ace_button;
// Define connections to sensors
#define TRIGPIN 27 // D27 (first sensor)
#define ECHOPIN 26 // D26 (first sensor)
#define TRIGPIN2 32 // D32 (second sensor)
#define ECHOPIN2 33 // D33 (second sensor)
#define wifiLed 2 // D2
#define ButtonPin1 12 // D12
#define BuzzerPin 13 // D13
#define GreenLed 14 // D14
// Change the virtual pins according to the rooms
#define VPIN_BUTTON_1 V1
#define VPIN_BUTTON_2 V2
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
float duration;
float distance;
int waterLevelPer;
bool toggleBuzzer = HIGH; // Define to remember the toggle state
float duration2;
float distance2;
int waterLevelPer2;
char auth[] = BLYNK_AUTH_TOKEN;
ButtonConfig config1;
AceButton button1(&config1);
void handleEvent1(AceButton*, uint8_t, uint8_t);
BlynkTimer timer;
void checkBlynkStatus() { // called every 3 seconds by SimpleTimer
bool isconnected = Blynk.connected();
if (isconnected == false) {
digitalWrite(wifiLed, LOW);
}
if (isconnected == true) {
digitalWrite(wifiLed, HIGH);
}
}
BLYNK_CONNECTED() {
Blynk.syncVirtual(VPIN_BUTTON_1);
Blynk.syncVirtual(VPIN_BUTTON_2);
}
void measureDistance() {
// Measure distance for the first sensor
digitalWrite(TRIGPIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIGPIN, HIGH);
delayMicroseconds(20);
digitalWrite(TRIGPIN, LOW);
duration = pulseIn(ECHOPIN, HIGH);
distance = ((duration / 2) * 0.343) / 10;
if (distance > (fullTankDistance1 - 10) && distance < emptyTankDistance1 ) {
waterLevelPer = map((int)distance, emptyTankDistance1, fullTankDistance1, 0, 100);
}
// Measure distance for the second sensor
digitalWrite(TRIGPIN2, LOW);
delayMicroseconds(2);
digitalWrite(TRIGPIN2, HIGH);
delayMicroseconds(20);
digitalWrite(TRIGPIN2, LOW);
duration2 = pulseIn(ECHOPIN2, HIGH);
distance2 = ((duration2 / 2) * 0.343) / 10;
if (distance2 > (fullTankDistance2 - 10) && distance2 < emptyTankDistance2 ) {
waterLevelPer2 = map((int)distance2, emptyTankDistance2, fullTankDistance2, 0, 100);
}
else {
Serial.print("Sensor 2 Distance: ");
Serial.println(distance2);
}
}
void displayData() {
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
// Display Sensor 1 value
display.setCursor(0, 0);
display.print("Sen1:");
display.print(waterLevelPer);
display.print("%");
// Display Sensor 2 value
display.setCursor(0, 16);
display.print("Sen2:");
display.print(waterLevelPer2);
display.print("%");
display.display();
}
void setup() {
Serial.begin(115200);
pinMode(ECHOPIN, INPUT);
pinMode(TRIGPIN, OUTPUT);
pinMode(ECHOPIN2, INPUT);
pinMode(TRIGPIN2, OUTPUT);
pinMode(wifiLed, OUTPUT);
pinMode(GreenLed, OUTPUT);
pinMode(BuzzerPin, OUTPUT);
pinMode(ButtonPin1, INPUT_PULLUP);
digitalWrite(wifiLed, LOW);
digitalWrite(GreenLed, LOW);
digitalWrite(BuzzerPin, LOW);
config1.setEventHandler(button1Handler);
button1.init(ButtonPin1);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;) ;
}
delay(1000);
display.clearDisplay();
WiFi.begin(ssid, pass);
timer.setInterval(2000L, checkBlynkStatus);
Blynk.config(auth);
delay(1000);
}
void loop() {
// Trigger green LED when either sensor's water level is <= triggerPer
if (waterLevelPer <= triggerPer || waterLevelPer2 <= triggerPer){
digitalWrite(GreenLed, HIGH);
if (toggleBuzzer == HIGH) {
digitalWrite(BuzzerPin, HIGH);
}
} else {
digitalWrite(GreenLed, LOW);
if (toggleBuzzer == HIGH) {
digitalWrite(BuzzerPin, HIGH);
}
}
measureDistance();
displayData(); // Display both sensor values
Blynk.run();
timer.run();
button1.check();
}
void button1Handler(AceButton* button, uint8_t eventType, uint8_t buttonState) {
Serial.println("EVENT1");
switch (eventType) {
case AceButton::kEventReleased:
digitalWrite(BuzzerPin, LOW);
toggleBuzzer = LOW;
break;
}
}