#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <WiFi.h>
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const int wifiChannel = 6;
#define TRIG_PIN 12
#define ECHO_PIN 13
#define RELAY_PIN 19
#define TANK_HEIGHT 20
#define PUMP_ON_LEVEL 15
#define PUMP_OFF_LEVEL 3
#define NUM_SAMPLES 20
#define MIN_VALID_DISTANCE 2
float distanceSamples[NUM_SAMPLES];
LiquidCrystal_I2C lcd(0x27, 16, 2);
enum RelayState { RELAY_OFF, RELAY_ON };
RelayState relayState = RELAY_OFF;
void connectToWiFi() {
Serial.print("Connecting to WiFi");
WiFi.begin(ssid, password, wifiChannel);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(".");
}
Serial.println(" Connected!");
}
void setup() {
Serial.begin(115200);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, LOW);
lcd.init();
lcd.backlight();
lcd.begin(16, 2);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Distance:");
connectToWiFi();
for (int i = 0; i < NUM_SAMPLES; i++) {
distanceSamples[i] = 0;
}
}
float measureDistance() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duration = pulseIn(ECHO_PIN, HIGH, 25000);
float distance = (duration * 0.0343) / 2;
return distance;
}
float getAverageDistance() {
float distances[NUM_SAMPLES];
for (int i = 0; i < NUM_SAMPLES; i++) {
distances[i] = measureDistance();
delay(50);
}
for (int i = 0; i < NUM_SAMPLES - 1; i++) {
for (int j = i + 1; j < NUM_SAMPLES; j++) {
if (distances[i] > distances[j]) {
float temp = distances[i];
distances[i] = distances[j];
distances[j] = temp;
}
}
}
if (NUM_SAMPLES % 2 == 0) {
return (distances[NUM_SAMPLES / 2 - 1] + distances[NUM_SAMPLES / 2]) / 2;
} else {
return distances[NUM_SAMPLES / 2];
}
}
void loop() {
float distance = getAverageDistance();
if (distance >= MIN_VALID_DISTANCE) {
Serial.print("Distance: ");
Serial.print(distance);
Serial.println(" cm");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Distance: ");
lcd.print(distance);
lcd.print(" cm");
lcd.setCursor(0, 1);
if (distance >= PUMP_ON_LEVEL && relayState != RELAY_ON) {
lcd.print("Pump: ON");
digitalWrite(RELAY_PIN, HIGH);
relayState = RELAY_ON;
} else if (distance <= PUMP_OFF_LEVEL && relayState != RELAY_OFF) {
lcd.print("Pump: OFF");
digitalWrite(RELAY_PIN, LOW);
relayState = RELAY_OFF;
} else {
lcd.print("Pump: WAIT");
}
}
delay(1000);
}