#define BLYNK_TEMPLATE_ID "TMPL69q_w3zyk"
#define BLYNK_TEMPLATE_NAME "Water level and Humidity"
#define BLYNK_AUTH_TOKEN "Hgg9gXwNkoZNdRx39HdW06z2vOWsEEBD"
#define BLYNK_PRINT Serial
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include "DHTesp.h"
#include <LiquidCrystal_I2C.h>
#include <Stepper.h>
char auth[] = BLYNK_AUTH_TOKEN;
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
#define PIN_TRIG 13
#define PIN_ECHO 12
#define I2C_ADDR 0x27
#define LCD_COLUMNS 16
#define LCD_LINES 2
#define RELAY_MDL1 23
#define RELAY_MDL2 14
const int DHT_PIN = 15;
const int ENABLE_PIN_SMD1 = 4;
const int STEP_PIN_SMD1 = 18;
const int DIR_PIN_SMD1 = 19;
const int STEPS_REVOLUTION_SMD1 = 200;
const int ENABLE_PIN_SMD2 = 25;
const int STEP_PIN_SMD2 = 26;
const int DIR_PIN_SMD2 = 27;
const int STEPS_REVOLUTION_SMD2 = 200;
BlynkTimer timer;
DHTesp dhtSensor;
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
Stepper stepper1(STEPS_REVOLUTION_SMD1, STEP_PIN_SMD1, DIR_PIN_SMD1);
bool isMotor1On = false;
Stepper stepper2(STEPS_REVOLUTION_SMD2, STEP_PIN_SMD2, DIR_PIN_SMD2);
bool isMotor2On = false;
bool humidityPumpState = false;
bool waterLevelPumpState = false;
BLYNK_WRITE(V2) {
humidityPumpState = param.asInt();
}
BLYNK_WRITE(V3) {
waterLevelPumpState = param.asInt();
void setup() {
Serial.begin(115200);
//Blynk connection
Blynk.begin(auth, ssid, pass);
// Initialize DHT Sensor using library
dhtSensor.setup(DHT_PIN, DHTesp::DHT22);
// Initialize Ultrasonic Sensor
pinMode(PIN_TRIG, OUTPUT);
pinMode(PIN_ECHO, INPUT);
// Initialize LCD
lcd.init();
lcd.backlight();
lcd.clear();
// Initialize relay module right
pinMode(RELAY_MDL1, OUTPUT);
// Initialize relay module Left
pinMode(RELAY_MDL2, OUTPUT);
// Set pump states to OFF
humidityPumpState = false;
waterLevelPumpState = false;
// Initialize A4988 Stepper Motor Driver Right
stepper1.setSpeed(400);
stepper1.step(8);
// Initialize A4988 Stepper Motor Driver Left
stepper2.setSpeed(400);
stepper2.step(8);
}
void loop() {
//Humidity measurement & read result :
TempAndHumidity data = dhtSensor.getTempAndHumidity();
Serial.println("Kelembapan : " + String(data.humidity, 1) + "%");
Blynk.virtualWrite(V0, data.humidity);
//Humidity Alert
if (data.humidity <= 39) {
digitalWrite(RELAY_MDL1, LOW);
Serial.println("Kelembapan Tanah Kering");
} else if (data.humidity >= 40 && data.humidity <= 60) {
digitalWrite(RELAY_MDL1, HIGH);
Serial.println("Kelembapan Tanah Ideal");
} else {
digitalWrite(RELAY_MDL1, LOW);
Serial.println("Kelembapan Tanah Terlalu Basah");
}
// Start water level measurement:
digitalWrite(PIN_TRIG, HIGH);
delayMicroseconds(10);
digitalWrite(PIN_TRIG, LOW);
// Read water level result:
int duration = pulseIn(PIN_ECHO, HIGH);
Serial.print("Ketinggian air: ");
int waterLevel = duration / 58;
Serial.print(waterLevel);
Serial.println(" cm");
Blynk.virtualWrite(V1, waterLevel);
//Water Level Alert
if (waterLevel >= 4 && waterLevel <= 8) {
digitalWrite(RELAY_MDL2, HIGH);
Serial.println("Ketinggian air optimal");
} else {
digitalWrite(RELAY_MDL2, LOW);
Serial.println("Ketinggian air tidak optimal");
}
//LCD Output Humidity & Water Level
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Humiditas:" + String(data.humidity, 1) + "% ");
lcd.setCursor(0, 1);
lcd.print("Tinggi air:" + String(waterLevel) + "cm");
Serial.println("---");
// Humidity Pump Control
if (humidityPumpState) {
if (!isMotor1On) {
stepper1.step(808);
isMotor1On = true;
}
} else {
if (isMotor1On) {
stepper1.step(-808);
isMotor1On = false;
}
}
// Water Level Pump Control
if (waterLevelPumpState) {
if (!isMotor2On) {
stepper2.step(808);
isMotor2On = true;
}
} else {
if (isMotor2On) {
stepper2.step(-808);
isMotor2On = false;
}
}
delay(2000);
Blynk.run();
timer.run();
}