I'm using a water level sensor with two outputs, a 5V fan and a water pump. Here's the wiring
.
What I want to do with this project is:
- When the water reaches 2 cm, then the water pump is on while the fan is off.
- When the water is less than 2 cm, then the water pump is off and fan is on.
The problem is, when the water is below the threshold, the sensor reading is quite unstable, thus making the relay switching too fast (see the video).
How to eliminate this problem?
#include <Wire.h>
#include <Blynk.h>
#include <LiquidCrystal_I2C.h>
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
//Initialize the LCD display
LiquidCrystal_I2C lcd(0x27, 16, 2);
char auth[] = "xxx";//Enter your Auth token
char ssid[] = "xxx";//Enter your WIFI name
char pass[] = "xxx";//Enter your WIFI password
BlynkTimer timer;
#define pinSensor A0
#define PIN_RELAY_1 D3
#define PIN_RELAY_2 D4
const int startThreshold = 2; // pumping shall start at startThreshold [cm] and above
const int stopThreshold = 1; // pumping shall start at stopThreshold [cm] and below
int sensorValue = 0; // sensor reading integer
float tinggiAir = 0; // height of water
float sensorVoltage = 0; // voltage sensor
int nilaiMax = 686; // max value of sensor after fully drowning it in water
float panjangSensor = 4.0 ; // sensor's height in cm
enum StatusType {CHECKLEVEL, LEVELHIGH, PUMPING};
StatusType status = LEVELHIGH; // Let's start with LEVELHIGH to check level and set the display correctly
void setup() {
Serial.begin(115200);
lcd.begin();
Blynk.begin(auth, ssid, pass, "blynk.cloud", 80);
lcd.backlight();
pinMode(PIN_RELAY_1, OUTPUT);
pinMode(PIN_RELAY_2, OUTPUT);
digitalWrite(PIN_RELAY_1, LOW);
digitalWrite(PIN_RELAY_2, LOW);
lcd.setCursor(0, 0);
lcd.print("Water level");
lcd.setCursor(4, 1);
lcd.print("Monitoring");
delay(1000);
lcd.clear();
timer.setInterval(100L, wLevel);
}
void wLevel() {
sensorValue = analogRead(pinSensor);
tinggiAir = sensorValuepanjangSensor/nilaiMax;
sensorVoltage = sensorValue5.0/686;
}
void loop() {
Blynk.run();
timer.run();
handleStatus();
}
void handleStatus() {
switch (status) {
case CHECKLEVEL:
// Wait for level above threshold
if (tinggiAir >= startThreshold) { // if wlevel more than startThreshold [cm], then
status = LEVELHIGH;
Serial.println("LEVELHIGH");
}
break;
case LEVELHIGH:
levelIsHigh();
break;
case PUMPING:
if (tinggiAir < stopThreshold) { // if wlevel less than stopThreshold [cm] (use hysteresis!) then
levelIsLowAgain();
status = CHECKLEVEL;
Serial.println("CHECKLEVEL");
}
break;
}
displayValues();
}
void displayValues() {
static int oldSensorValue = -1; // variable untuk menampung nilai baca dari sensor dalam bentuk integer
float oldTinggiAir = -1; // variabel untuk menampung ketinggian air
float oldSensorVoltage = -1; // untuk menampung nilai ketinggian air
if (oldSensorValue != sensorValue ||
oldTinggiAir != tinggiAir ||
oldSensorVoltage != sensorVoltage) {
Serial.print("Sensor Value = ");
Serial.println(sensorValue);
Serial.print("Sensor Voltage = ");
Serial.println(sensorVoltage);
Serial.print("Tinggi Air = ");
Serial.println(tinggiAir);
Serial.println();
// Display ke LCD
lcd.setCursor(0, 0);
lcd.print("WLevel:");
lcd.print(tinggiAir);
lcd.setCursor(12, 0);
lcd.print("cm");
oldSensorValue = sensorValue;
oldTinggiAir = tinggiAir;
oldSensorVoltage = sensorVoltage;
Blynk.virtualWrite(V0, tinggiAir);
}
}
void levelIsHigh() {
digitalWrite(PIN_RELAY_1, HIGH);
digitalWrite(PIN_RELAY_2, LOW);
lcd.setCursor(0, 1);
lcd.print("F:OFF P:ON");
Blynk.logEvent("wlevel", "wLevel more than 2cm");
status = PUMPING;
Serial.println("PUMPING");
}
void levelIsLowAgain() {
digitalWrite(PIN_RELAY_1, LOW);
digitalWrite(PIN_RELAY_2, HIGH);
lcd.setCursor(0, 1);
lcd.print("F:ON P:OFF");
status = CHECKLEVEL;
Serial.println("CHECKLEVEL");
}