/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial

/* Fill in information from Blynk Device Info here */
#define BLYNK_TEMPLATE_ID "TMPL3Zzb0MnqQ"
#define BLYNK_TEMPLATE_NAME "wowki"
#define BLYNK_AUTH_TOKEN "ymuoOn4YbJqRjVYrZqGeFBIlB3MW9iry"

char ssid[] = "Wokwi-GUEST";
char pass[] = "";


#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#include <ESP32Servo.h> // Standard Servo library for ESP32

// Define Ultrasonic Sensor Pins
const int trigPin = 5;
const int echoPin = 18;

// Define Servo Pin
const int servoPin = 13; // Change to the appropriate pin for your servo

// Define LEDs for status indication
const int greenLedPin = 25;   // Green LED pin (Empty)
const int redLedPin = 26;     // Red LED pin (Full)
const int orangeLedPin = 27;  // Orange LED pin (Filling)

// I2C LCD
LiquidCrystal_I2C lcd(0x27, 16, 2);  // Set the LCD address to 0x27 for a 16 chars and 2 line display


BlynkTimer timer;

// Servo object
Servo myservo;

// Variable to keep track of the servo state
bool isServoClosed = false;

void setup() {
  Serial.begin(115200);
  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);

  // Set sensor pins as input and output
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);

  // Initialize the LCD
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Initializing...");

  // Attach the servo to the pin
  myservo.attach(servoPin);

  // Set LED pins as output
  pinMode(greenLedPin, OUTPUT);
  pinMode(redLedPin, OUTPUT);
  pinMode(orangeLedPin, OUTPUT);

  // Setup a function to send data to Blynk every second
  timer.setInterval(1000L, sendSensorData);
}

void sendSensorData() {
  // Clear the trigPin
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);

  // Set the trigPin HIGH for 10 microseconds
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  // Read the echoPin, returns the sound wave travel time in microseconds
  long duration = pulseIn(echoPin, HIGH);

  // Calculate the distance in cm
  float distanceCm = duration * 0.034 / 2;

  // Map the distance from 2-400 cm to 1-100
  int mappedDistance = map(distanceCm, 2, 400, 1, 100);

  // Print distance to Serial Monitor
  Serial.print("Distance: ");
  Serial.print(distanceCm);
  Serial.print(" cm, mappedsensorvalue: ");
  Serial.println(mappedDistance);

  // Send the mapped distance to Blynk
  Blynk.virtualWrite(V0, mappedDistance);

  // Display distance on LCD
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Fill: ");
  lcd.print(100-mappedDistance);
  lcd.print("%");

  // Turn off all LEDs initially
  digitalWrite(greenLedPin, LOW);
  digitalWrite(redLedPin, LOW);
  digitalWrite(orangeLedPin, LOW);

  // Check if the tank is empty or needs to be emptied
  if (mappedDistance <= 10) {
    lcd.setCursor(0, 1);
    lcd.print("Status: FULL");
    digitalWrite(redLedPin, HIGH); // Red LED for full

  } else if (mappedDistance > 80) {
    lcd.setCursor(0, 1);
    lcd.print("Status: EMPTY");
    digitalWrite(greenLedPin, HIGH); // Green LED for empty

    // Close the servo if not already closed
    if (!isServoClosed) {
      myservo.write(0);  // Close the servo (assumes 0 degrees is closed)
      isServoClosed = true;
    }
  } else {
    lcd.setCursor(0, 1);
    lcd.print("Status: FILLING");
    digitalWrite(orangeLedPin, HIGH); // Orange LED for filling
  }

  // Open the servo if the tank is empty
  if (mappedDistance <= 10 && isServoClosed) {
    myservo.write(90);  // Open the servo (assumes 90 degrees is open)
    isServoClosed = false;
  }
}

void loop() {
  Blynk.run();
  timer.run();
}
$abcdeabcde151015202530fghijfghij