#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>

char ssid[] = "Wokwi-GUEST";    
char pass[] = ""; 

#define DHTPIN 21 
#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); 
const int stepsPerRevolution = 200; 
Stepper myStepper(stepsPerRevolution, STEP_PIN, DIR_PIN); 

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); 
  
  lcd.setCursor(0, 0);
  lcd.print("Soil Health");

  Serial.println("Connecting to WiFi");
  WiFi.disconnect(true);  
  delay(1000);
  WiFi.begin(ssid, pass);

  unsigned long startAttemptTime = millis();
  
  while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < 10000) { 
    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());

  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);

  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;
  }

  Serial.println("Setup complete");
}

void loop() {
  Blynk.run();

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

  Serial.print("Temperature: ");
  Serial.print(temperature);
  Serial.print("C, Humidity: ");
  Serial.print(humidity);
  Serial.println("%");

  int windSpeedRaw = analogRead(WIND_SENSOR_PIN);
  float windSpeed = map(windSpeedRaw, 0, 4095, 0, 100); 
  
  Serial.print("Wind Speed Raw: ");
  Serial.print(windSpeedRaw);
  Serial.print(", Wind Speed: ");
  Serial.print(windSpeed);
  Serial.println(" m/s");

  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");

  if (temperature > 30.0) { 
    digitalWrite(BUZZER_PIN, HIGH);
  } else {
    digitalWrite(BUZZER_PIN, LOW);
  }

  if (humidity < 20.0) { 
    digitalWrite(MOTOR_PIN, HIGH);
  } else {
    digitalWrite(MOTOR_PIN, LOW);
  }

  int motorSpeed = map(windSpeedRaw, 0, 4095, 0, 1000); 
  myStepper.setSpeed(motorSpeed);
  myStepper.step(stepsPerRevolution / 100); 

  delay(2000); 
}
A4988