#define BLYNK_TEMPLATE_ID "TMPL3tWGV5GYY"
#define BLYNK_TEMPLATE_NAME "smart soil nutrition monitoring system"
#define BLYNK_AUTH_TOKEN "yqqdMzsDClzTtQamlqBFw8raXJH1-iFL"

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "DHT.h"
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <Stepper.h>

// WiFi credentials
char ssid[] = "Wokwi-GUEST";    // Replace with your WiFi SSID
char pass[] = ""; // Replace with your WiFi Password

#define DHTPIN 21 // DHT22 data pin
#define DHTTYPE DHT22

#define BUZZER_PIN 18
#define MOTOR_PIN 19
#define WIND_SENSOR_PIN 34
#define STEP_PIN 26
#define DIR_PIN 27
#define ENABLE_PIN 25

DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal_I2C lcd(0x27, 16, 2); // LCD address and dimensions
const int stepsPerRevolution = 200; // Number of steps per revolution for your motor
Stepper myStepper(stepsPerRevolution, STEP_PIN, DIR_PIN); // Initialize the stepper library on the pins you are using

void setup() {
  Serial.begin(115200);
  dht.begin();
  lcd.init();
  lcd.backlight();

  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(MOTOR_PIN, OUTPUT);
  pinMode(WIND_SENSOR_PIN, INPUT);
  pinMode(ENABLE_PIN, OUTPUT);
  digitalWrite(ENABLE_PIN, LOW); // Enable the driver
  
  lcd.setCursor(0, 0);
  lcd.print("Soil Health");

  // Connect to WiFi
  Serial.println("Connecting to WiFi");
  WiFi.disconnect(true);  // Reset the WiFi module
  delay(1000);
  WiFi.begin(ssid, pass);

  unsigned long startAttemptTime = millis();
  
  while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < 10000) { // Timeout after 10 seconds
    delay(500);
    Serial.print(".");
  }
  
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("\nFailed to connect to WiFi");
    lcd.setCursor(0, 1);
    lcd.print("WiFi Failed");
    return;
  }

  Serial.println("\nConnected to WiFi");
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());

  // Connect to Blynk
  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);

  // Wait for Blynk connection
  while (!Blynk.connected()) {
    delay(500);
    Serial.print(".");
  }

  if (Blynk.connected()) {
    Serial.println("\nConnected to Blynk");
  } else {
    Serial.println("\nFailed to connect to Blynk");
    lcd.setCursor(0, 1);
    lcd.print("Blynk Failed");
    return;
  }

  // Test message to ensure setup runs
  Serial.println("Setup complete");
}

void loop() {
  // Run Blynk
  Blynk.run();

  // Read temperature and humidity from DHT22
  float humidity = dht.readHumidity();
  float temperature = dht.readTemperature();
  
  // Check if any reads failed
  if (isnan(humidity) || isnan(temperature)) {
    Serial.println("Failed to read from DHT sensor!");
    lcd.setCursor(0, 1);
    lcd.print("DHT Error");
    return;
  }

  // Print temperature and humidity to Serial Monitor for debugging
  Serial.print("Temperature: ");
  Serial.print(temperature);
  Serial.print("C, Humidity: ");
  Serial.print(humidity);
  Serial.println("%");

  // Read wind speed from potentiometer
  int windSpeedRaw = analogRead(WIND_SENSOR_PIN);
  float windSpeed = map(windSpeedRaw, 0, 4095, 0, 100); // Example conversion, adjust as needed
  
  // Print wind speed to Serial Monitor for debugging
  Serial.print("Wind Speed Raw: ");
  Serial.print(windSpeedRaw);
  Serial.print(", Wind Speed: ");
  Serial.print(windSpeed);
  Serial.println(" m/s");

  // Display data on LCD
  lcd.setCursor(0, 0);
  lcd.print("Temp: ");
  lcd.print(temperature);
  lcd.print("C ");
  lcd.setCursor(0, 1);
  lcd.print("Hum: ");
  lcd.print(humidity);
  lcd.print("%");

  lcd.setCursor(8, 1);
  lcd.print("Wind: ");
  lcd.print(windSpeed);
  lcd.print("m/s");

  // Control buzzer and motor based on sensor data
  if (temperature > 30.0) { // Example condition for high temperature
    digitalWrite(BUZZER_PIN, HIGH);
  } else {
    digitalWrite(BUZZER_PIN, LOW);
  }

  if (humidity < 20.0) { // Example condition for low humidity
    digitalWrite(MOTOR_PIN, HIGH);
  } else {
    digitalWrite(MOTOR_PIN, LOW);
  }

  // Control stepper motor speed based on wind speed
  int motorSpeed = map(windSpeedRaw, 0, 4095, 0, 1000); // Example mapping, adjust as needed
  myStepper.setSpeed(motorSpeed);
  myStepper.step(stepsPerRevolution / 100); // Rotate stepper motor

  delay(2000); // Delay between readings
}
A4988