Cirkit Designer LogoCirkit DesignerYour all-in-one circuit design IDE Launch Cirkit Designer App

ESP32-Based Smart Plant Monitoring System with Wi-Fi Control

View and Edit Project In Cirkit DesignerImage of ESP32-Based Smart Plant Monitoring System with Wi-Fi Control

Circuit Documentation

Summary

The circuit is designed to monitor environmental parameters for plant growth, including temperature, humidity, soil moisture, and motion detection. It uses an ESP32 microcontroller as the central processing unit, interfacing with various sensors and output devices. The system can be controlled and monitored remotely via the Blynk platform.

Component List

Wiring Details

ESP32 - Expansion Board

I2C LCD 16x2 Screen

DHT22

Humidity YL-69

PIR/Motion Sensor

Relay module 1 channel

Pushbutton

Water pump

2x 18650

Documented Code

// Define Blynk template ID and Name
#define BLYNK_TEMPLATE_ID "TMPL6rlQf3Kxk"
#define BLYNK_TEMPLATE_NAME "plant monitoring sistem"

/* Connections
Relay: GPIO23
Btn:   GPIO27
Soil:  GPIO36 (VP)
PIR:   GPIO18
SDA:   GPIO21
SCL:   GPIO22
Temp:  GPIO19
*/

// Include the library files
#include <LiquidCrystal_I2C.h>
#define BLYNK_PRINT Serial
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#include <DHT.h>

// Initialize the LCD display
LiquidCrystal_I2C lcd(0x3F, 16, 2);

char auth[] = "YourAuthToken";  // Enter your Blynk Auth token
char ssid[] = "YourNetworkName";  // Enter your WIFI SSID
char pass[] = "YourPassword";  // Enter your WIFI Password

DHT dht(19, DHT22);  // (DHT sensor pin, sensor type) GPIO19 DHT22 Temperature Sensor
BlynkTimer timer;

// Define component pins
#define soil 36  // GPIO36 (VP) for Soil Moisture Sensor
#define PIR 18   // GPIO18 for PIR Motion Sensor
int PIR_ToggleValue;

void checkPhysicalButton();
int relay1State = LOW;
int pushButton1State = HIGH;
#define RELAY_PIN_1 23       // GPIO23 for Relay
#define PUSH_BUTTON_1 27     // GPIO27 for Button
#define VPIN_BUTTON_1 V12 

// Create three variables for pressure
double T, P;
char status;

void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);  // Initialize the LCD with 16 columns and 2 rows
  lcd.backlight();
  pinMode(PIR, INPUT);

  pinMode(RELAY_PIN_1, OUTPUT);
  digitalWrite(RELAY_PIN_1, LOW);
  pinMode(PUSH_BUTTON_1, INPUT_PULLUP);
  digitalWrite(RELAY_PIN_1, relay1State);

  Blynk.begin(auth, ssid, pass, "blynk.cloud", 80);
  dht.begin();

  lcd.setCursor(0, 0);
  lcd.print("  Initializing  ");
  for (int a = 5; a <= 10; a++) {
    lcd.setCursor(a, 1);
    lcd.print(".");
    delay(500);
  }
  lcd.clear();
  lcd.setCursor(11, 1);
  lcd.print("W:OFF");
  
  // Call the function
  timer.setInterval(100L, soilMoistureSensor);
  timer.setInterval(100L, DHT22sensor);
  timer.setInterval(500L, checkPhysicalButton);
}

// Get the DHT22 sensor values
void DHT22sensor() {
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  if (isnan(h) || isnan(t)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  Blynk.virtualWrite(V0, t);
  Blynk.virtualWrite(V1, h);

  lcd.setCursor(0, 0);
  lcd.print("T:");
  lcd.print(t);

  lcd.setCursor(8, 0);
  lcd.print("H:");
  lcd.print(h);
}

// Get the soil moisture values
void soilMoistureSensor() {
  int value = analogRead(soil);
  value = map(value, 0, 4095, 0, 100);  // ESP32 has a 12-bit ADC
  value = (value - 100) * -1;

  Blynk.virtualWrite(V3, value);
  lcd.setCursor(0, 1);
  lcd.print("S:");
  lcd.print(value);
  lcd.print(" ");
}

// Get the PIR sensor values
void PIRsensor() {
  bool value = digitalRead(PIR);
  if (value) {
    Blynk.logEvent("pirmotion", "WARNING! Motion Detected!"); // Enter your Event Name
    WidgetLED LED(V5);
    LED.on();
  } else {
    WidgetLED LED(V5);
    LED.off();
  }
}

BLYNK_WRITE(V6)
{
 PIR_ToggleValue = param.asInt();  
}

BLYNK_CONNECTED() {
  // Request the latest state from the server
  Blynk.syncVirtual(VPIN_BUTTON_1);
}

BLYNK_WRITE(VPIN_BUTTON_1) {
  relay1State = param.asInt();
  digitalWrite(RELAY_PIN_1, relay1State);
}

void checkPhysicalButton() {
  if (digitalRead(PUSH_BUTTON_1) == LOW) {
    // pushButton1State is used to avoid sequential toggles
    if (pushButton1State != LOW) {
      // Toggle Relay state
      relay1State = !relay1State;
      digitalWrite(RELAY_PIN_1