#include <WiFi.h>
#include "ThingSpeak.h" #include "DHTesp.h"
// Pin definitions
const int SOIL_MOISTURE_PIN = 34; // Analog input for soil moisture const int SPRINKLER_CONTROL_PIN = 5; // Relay / pump control
const int DHT_PIN = 15; // DHT22 data pin DHTesp dhtSensor;
// Thresholds for hysteresis control
int MOISTURE_THRESHOLD_LOW = 15; // Turn ON sprinkler if soil moisture < low
int MOISTURE_THRESHOLD_HIGH = 55; // Turn OFF sprinkler if soil moisture > high
bool sprinklerOn = false;
// Wi-Fi and ThingSpeak configuration const char* WIFI_NAME = "Wokwi-GUEST"; const char* WIFI_PASSWORD = "";
unsigned long myChannelNumber = 3091681; // ThingSpeak channel ID const char* myApiKey = "UB1HS9KHJ1MLRTKS"; // ThingSpeak write API key
WiFiClient client; void setup() {
Serial.begin(115200);
pinMode(SPRINKLER_CONTROL_PIN, OUTPUT);
digitalWrite(SPRINKLER_CONTROL_PIN, LOW); // Ensure sprinkler OFF initially
dhtSensor.setup(DHT_PIN, DHTesp::DHT22); // Initialize DHT22 sensor
// Connect to Wi-Fi
Serial.print("Connecting to Wi-Fi: "); Serial.println(WIFI_NAME); WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_NAME, WIFI_PASSWORD);
unsigned long start = millis();
while (WiFi.status() != WL_CONNECTED && millis() - start < 20000) { delay(500); Serial.print(".");
}
Serial.println(WiFi.status() == WL_CONNECTED ? "\nWi-Fi connected" : "\nWi-Fi FAILED");
ThingSpeak.begin(client); // Initialize ThingSpeak
}
// Function to read soil moisture and convert to percentage
float readSoilMoisturePercent(int samples = 8, int delayMs = 20) {
long sum = 0;
for (int i = 0; i < samples; ++i) {
sum += analogRead(SOIL_MOISTURE_PIN); delay(delayMs);
}
float percent = (sum / (float)samples) / 4095.0 * 100.0; return constrain(percent, 0, 100); // Clamp between 0-100%
}
void loop() {
float soilMoisturePct = readSoilMoisturePercent(10, 10);
// Read temperature and humidity
TempAndHumidity data = dhtSensor.getTempAndHumidity(); float temperature = data.temperature;
float humidity = data.humidity;
// Sprinkler control with hysteresis
if (soilMoisturePct < MOISTURE_THRESHOLD_LOW) sprinklerOn = true;
else if (soilMoisturePct > MOISTURE_THRESHOLD_HIGH) sprinklerOn = false;
digitalWrite(SPRINKLER_CONTROL_PIN, sprinklerOn ? HIGH : LOW); // Drive relay
// Serial output for monitoring
Serial.print("Soil Moisture: "); Serial.print(soilMoisturePct, 1);
Serial.println("%");
if (isnan(temperature) || isnan(humidity)) Serial.println("DHT read failed!"); else {
Serial.print("Temp: "); Serial.print(temperature, 2); Serial.println(" °C");
Serial.print("Humidity: "); Serial.print(humidity, 1); Serial.println(" %");
}
Serial.print("Sprinkler: "); Serial.println(sprinklerOn ? "ON" : "OFF");
// Send data to ThingSpeak
if (WiFi.status() == WL_CONNECTED) { ThingSpeak.setField(1, soilMoisturePct);
if (!isnan(temperature)) ThingSpeak.setField(2, temperature); if (!isnan(humidity)) ThingSpeak.setField(3, humidity); ThingSpeak.setField(4, sprinklerOn ? 1 : 0);
int resp = ThingSpeak.writeFields(myChannelNumber, myApiKey);
Serial.println(resp == 200 ? "ThingSpeak write OK (200)" : "ThingSpeak write failed. HTTP code: " + String(resp));
} else Serial.println("Skipping ThingSpeak write (Wi-Fi not connected).");
Serial.println(" ");
delay(15000); // ThingSpeak rate limit
}