#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <SD.h>
#include <SPI.h>
// Pin Definitions
#define DHT_PIN 27
#define SOIL_MOISTURE_PIN 34
#define LDR_PIN 35
#define DHT_TYPE DHT22
#define SD_CS_PIN 5
#define SCK_PIN 18
#define MISO_PIN 19
#define MOSI_PIN 23
// LCD Setup (I2C address 0x27, 16 columns, 2 rows)
LiquidCrystal_I2C lcd(0x27, 16, 2);
// ThingSpeak API
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* apiKey = "MOM8Y14M2UKMYHEC";
const char* server = "http://api.thingspeak.com";
// DHT Setup
DHT dht(DHT_PIN, DHT_TYPE);
// Timer for alternating display
unsigned long lastDisplayUpdate = 0;
int displayState = 0; // 0 = Temp + Moisture, 1 = Light Level
void setup() {
Serial.begin(115200);
dht.begin();
// Initialize LCD
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Initializing...");
// Initialize SD Card
Serial.println("Initializing SD card...");
SPI.begin(SCK_PIN, MISO_PIN, MOSI_PIN, SD_CS_PIN);
if (!SD.begin(SD_CS_PIN)) {
Serial.println("SD Card initialization failed! Check wiring and SD card.");
lcd.setCursor(0, 1);
lcd.print("SD Init Failed!");
} else {
Serial.println("SD Card initialized successfully.");
lcd.setCursor(0, 1);
lcd.print("SD Ready!");
delay(2000);
}
// Connect to Wi-Fi
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Connecting WiFi...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to Wi-Fi...");
}
Serial.println("Connected to Wi-Fi!");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("WiFi Connected");
delay(2000);
}
void loop() {
// Read Sensor Values
float temperature = dht.readTemperature();
int soilMoistureValue = analogRead(SOIL_MOISTURE_PIN);
int lightLevel = analogRead(LDR_PIN);
// Validate Sensor Readings
if (isnan(temperature)) {
Serial.println("Failed to read temperature from DHT sensor!");
lcd.setCursor(0, 1);
lcd.print("Temp Read Err!");
return;
}
// Map Values to Percentage
int soilMoisturePercent = map(soilMoistureValue, 500, 3000, 0, 100);
soilMoisturePercent = constrain(soilMoisturePercent, 0, 100);
int lightPercent = map(lightLevel, 0, 4095, 0, 100);
// Print Readings to Serial Monitor
Serial.println("Temperature: " + String(temperature) + " °C");
Serial.println("Soil Moisture: " + String(soilMoisturePercent) + "%");
Serial.println("Light Level: " + String(lightPercent) + "%");
// Alternate LCD Display every 5 seconds
if (millis() - lastDisplayUpdate > 5000) {
lastDisplayUpdate = millis();
if (displayState == 0) {
// Show Temperature and Soil Moisture
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Temp: " + String(temperature) + "C");
lcd.setCursor(0, 1);
lcd.print("Moist: " + String(soilMoisturePercent) + "%");
displayState = 1;
} else {
// Show Light Level
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Light Level:");
lcd.setCursor(0, 1);
lcd.print(String(lightPercent) + "%");
displayState = 0;
}
}
// Log Data to SD Card
File dataFile = SD.open("/data.txt", FILE_APPEND);
if (dataFile) {
dataFile.print("Temperature: ");
dataFile.print(temperature);
dataFile.print(" C, Soil Moisture: ");
dataFile.print(soilMoisturePercent);
dataFile.print("%, Light Level: ");
dataFile.print(lightPercent);
dataFile.println("%");
dataFile.close();
Serial.println("Data logged to SD card.");
} else {
Serial.println("Failed to write to SD card!");
lcd.setCursor(0, 1);
lcd.print("SD Write Fail!");
}
// Send Data to ThingSpeak
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
String url = String(server) + "/update?api_key=" + apiKey +
"&field1=" + String(temperature) +
"&field2=" + String(soilMoisturePercent) +
"&field3=" + String(lightPercent);
http.begin(url);
int httpResponseCode = http.GET();
if (httpResponseCode > 0) {
Serial.println("Data sent to ThingSpeak!");
} else {
Serial.println("Failed to send data. Error: " + String(httpResponseCode));
}
http.end();
} else {
Serial.println("Wi-Fi disconnected!");
}
delay(15000);
}