#include "DHTesp.h"
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>
#include <WiFi.h>
#include <OneWire.h>
#include "ThingSpeak.h"
#define DHT_SENSOR_PIN 15
#define TEMP_SENSOR_PIN 4
#define MOISTURE_SENSOR_PIN 5
#define BUTTON_PIN 2
#define MOISTURE_ANALOG_PIN 33
#define PUMP_PIN 12
#define ALERT_BUZZER_PIN 13
OneWire oneWireInterface(TEMP_SENSOR_PIN); // Initialize oneWire communication for DS18B20 sensor
DallasTemperature temperatureSensor(&oneWireInterface);
LiquidCrystal_I2C lcdDisplay(0x27, 16, 2); // LCD setup
DHTesp dht22Sensor;
WiFiClient wifiClient;
// Sensor data variables
float airTemperature;
float airHumidity;
float soilTemperature;
// ThingSpeak settings
unsigned long channelID = 1974516;
const char* writeAPIKey = "FPK1MESWX9ONBY8F";
// Timing variables
unsigned long lastCloudUpdateTime = 0;
unsigned long cloudUpdateInterval = 15000;
unsigned long lastLCDUpdateTime = 0;
unsigned long lcdUpdateInterval = 2000;
int currentLCDView = 0;
bool cloudUpdateSuccess = false;
// Soil moisture calibration
const int dryReading = 590;
const int wetReading = 300;
int soilMoistureRawValue;
int soilMoisturePercentage;
const int moistureThreshold = 60;
bool isSoilDry = false;
String systemStatus = "";
// Wi-Fi configuration
const char* wifiSSID = "Wokwi-GUEST";
const char* wifiPassword = "";
void setup() {
Serial.begin(115200);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(PUMP_PIN, OUTPUT);
pinMode(ALERT_BUZZER_PIN, OUTPUT);
lcdDisplay.init();
lcdDisplay.backlight();
dht22Sensor.setup(DHT_SENSOR_PIN, DHTesp::DHT22);
temperatureSensor.begin(); // Initialize DS18B20 sensor
WiFi.begin(wifiSSID, wifiPassword);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(".");
lcdDisplay.setCursor(0, 0);
lcdDisplay.print("Connecting WiFi");
}
Serial.println("\nWiFi connected");
lcdDisplay.clear();
lcdDisplay.setCursor(0, 0);
lcdDisplay.print("WiFi Connected");
delay(500);
ThingSpeak.begin(wifiClient); // Initialize ThingSpeak
}
void loop() {
readSensors();
controlPumpAndBuzzer();
updateLCDDisplay();
updateCloudData();
}
void readSensors() {
// Read from DHT22
TempAndHumidity dhtData = dht22Sensor.getTempAndHumidity();
airTemperature = dhtData.temperature;
airHumidity = dhtData.humidity;
// Read from Dallas Temperature Sensor
temperatureSensor.requestTemperatures();
soilTemperature = temperatureSensor.getTempCByIndex(0);
// Read from soil moisture sensor
soilMoistureRawValue = analogRead(MOISTURE_ANALOG_PIN);
soilMoisturePercentage = map(soilMoistureRawValue, dryReading, wetReading, 0, 100);
soilMoisturePercentage = constrain(soilMoisturePercentage, 0, 100);
}
void controlPumpAndBuzzer() {
if (soilMoisturePercentage < moistureThreshold) {
digitalWrite(PUMP_PIN, HIGH);
digitalWrite(ALERT_BUZZER_PIN, HIGH);
isSoilDry = true;
} else {
digitalWrite(PUMP_PIN, LOW);
digitalWrite(ALERT_BUZZER_PIN, LOW);
isSoilDry = false;
}
}
void updateLCDDisplay() {
if ((millis() - lastLCDUpdateTime) >= lcdUpdateInterval || digitalRead(BUTTON_PIN) == LOW) {
if (digitalRead(BUTTON_PIN) == LOW) {
currentLCDView = (currentLCDView + 1) % 4;
}
lcdDisplay.clear();
switch (currentLCDView) {
case 0:
displayAirData();
break;
case 1:
displaySoilData();
break;
case 2:
displayPumpStatus();
break;
case 3:
displayCloudStatus();
break;
}
lastLCDUpdateTime = millis();
}
}
void displayAirData() {
lcdDisplay.setCursor(0, 0);
lcdDisplay.print("Air Temp: ");
lcdDisplay.print(airTemperature, 1);
lcdDisplay.print("C");
lcdDisplay.setCursor(0, 1);
lcdDisplay.print("Humidity: ");
lcdDisplay.print(airHumidity, 1);
lcdDisplay.print("%");
}
void displaySoilData() {
lcdDisplay.setCursor(0, 0);
lcdDisplay.print("Soil Temp: ");
lcdDisplay.print(soilTemperature, 1);
lcdDisplay.print("C");
lcdDisplay.setCursor(0, 1);
lcdDisplay.print("Moisture: ");
lcdDisplay.print(soilMoisturePercentage);
lcdDisplay.print("%");
}
void displayPumpStatus() {
lcdDisplay.setCursor(0, 0);
lcdDisplay.print("Soil is ");
lcdDisplay.print(isSoilDry ? "DRY" : "WET");
lcdDisplay.setCursor(0, 1);
lcdDisplay.print("Pump: ");
lcdDisplay.print(isSoilDry ? "ON" : "OFF");
}
void displayCloudStatus() {
lcdDisplay.setCursor(0, 0);
lcdDisplay.print("Cloud Update");
lcdDisplay.setCursor(0, 1);
lcdDisplay.print(cloudUpdateSuccess ? "Success" : "Failed");
}
void updateCloudData() {
if ((millis() - lastCloudUpdateTime) >= cloudUpdateInterval) {
ThingSpeak.setField(1, airHumidity);
ThingSpeak.setField(2, airTemperature);
ThingSpeak.setField(3, soilMoisturePercentage);
systemStatus = (soilMoisturePercentage < moistureThreshold) ? "Soil Dry!" : "Soil OK!";
ThingSpeak.setStatus(systemStatus);
int responseCode = ThingSpeak.writeFields(channelID, writeAPIKey);
cloudUpdateSuccess = (responseCode == 200);
if (!cloudUpdateSuccess) {
lcdDisplay.setCursor(0, 0);
lcdDisplay.print("Cloud Error: ");
lcdDisplay.setCursor(0, 1);
lcdDisplay.print(responseCode);
delay(1000);
}
lastCloudUpdateTime = millis();
}
}