/**********************************************************************************
* 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 "TMPL6NPf1sYFF"
#define BLYNK_TEMPLATE_NAME "home"
#define BLYNK_AUTH_TOKEN "_iJze8DDOqOkvBx0Wn5Q81LCaFlMIh4Y"
// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "Mi_Sanju";
char pass[] = "Forever1";
// Set Water Level Distances in CM for each sensor
int emptyTankDistance1 = 70; // Distance when tank 1 is empty
int fullTankDistance1 = 30; // Distance when tank 1 is full
int emptyTankDistance2 = 80; // Distance when tank 2 is empty
int fullTankDistance2 = 40; // 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
#define SwitchPin 25 // D25 (push button to toggle sensors)
// 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;
bool displaySensor1 = true; // Flag to display sensor 1 reading by default
bool prevButtonState = HIGH; // Previous state of the button
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() {
if (displaySensor1) {
// 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);
}
} else {
// 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); // Set text size to 2
display.setTextColor(WHITE);
if (displaySensor1) {
// Display Sensor 1 value
display.setCursor(0, 0);
display.print("Sensor 1: ");
display.print(waterLevelPer);
display.print("%");
} else {
// Display Sensor 2 value
display.setCursor(0, 0);
display.print("Sensor 2: ");
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);
pinMode(SwitchPin, INPUT_PULLUP); // Push button to toggle sensors
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() {
measureDistance();
// Read the current state of the button
int buttonState = digitalRead(SwitchPin);
// Check if the button is pressed
if (buttonState == LOW && prevButtonState == HIGH) {
// Button is pressed, toggle between displaying Sensor 1 and Sensor 2 readings
displaySensor1 = !displaySensor1;
delay(500); // Delay to debounce the button
}
prevButtonState = buttonState; // Update the previous button state
displayData(); // Display the selected sensor's reading
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;
}
}