#include <WiFi.h> // Library for Wi-Fi functionality on the ESP32.
#include <HTTPClient.h> // Library for HTTP requests.
#include "DHTesp.h" // Library for DHT sensors, specifically for DHT22 in this case.
#include <SPI.h> // Library for SPI communication (used by SD card).
#include <SD.h> // Library for reading from and writing to an SD card.
#include <Wire.h> // Library for I2C communication (used by the LCD).
#include <LiquidCrystal_I2C.h> // Library for controlling I2C-based LCD displays.
// Define pins
const int DHT_PIN = 25; // GPIO pin connected to the DHT22 data pin.
#define SD_CS 5 // Chip Select (CS) pin for SD card.
#define SD_CLK 18 // SPI Clock (SCK) pin for SD card.
#define SD_MISO 19 // Master In Slave Out (MISO) pin for SD card (data from SD to ESP32).
#define SD_MOSI 23 // Master Out Slave In (MOSI) pin for SD card (data from ESP32 to SD).
// LCD settings
#define I2C_ADDR 0x27 // I2C address of the LCD display.
#define LCD_COLUMNS 16 // Number of columns on the LCD.
#define LCD_LINES 2 // Number of lines on the LCD.
// Wi-Fi credentials
const char* ssid = "Wokwi-GUEST"; // Wi-Fi network name (SSID).
const char* password = ""; // Wi-Fi password (blank in this case).
const char* apiKey = "XJSMMIHV0QFH0VJT"; // ThingSpeak Write API Key.
const char* server = "api.thingspeak.com"; // ThingSpeak server address.
// Global objects
WiFiClient espClient; // Wi-Fi client for handling connections.
DHTesp dhtSensor; // Object for interfacing with the DHT22 sensor.
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES); // Object for controlling the LCD.
unsigned long lastMsg = 0; // Variable to store the timestamp of the last action.
#define MSG_BUFFER_SIZE 50 // Message buffer size (not used in this code).
float temp = 0; // Variable to store the temperature reading.
float hum = 0; // Variable to store the humidity reading.
bool sdInitialized = false; // Flag to indicate if the SD card was successfully initialized.
// Function to set up Wi-Fi connection
void setup_wifi() {
delay(10); // Short delay for initialization.
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid); // Print the Wi-Fi network name.
WiFi.mode(WIFI_STA); // Set the ESP32 to station mode.
WiFi.begin(ssid, password); // Connect to the Wi-Fi network.
while (WiFi.status() != WL_CONNECTED) { // Wait until the ESP32 connects.
delay(500);
Serial.print("."); // Print dots to indicate connection progress.
}
Serial.println("");
Serial.println("WiFi connected"); // Confirm Wi-Fi connection.
Serial.println("IP address: ");
Serial.println(WiFi.localIP()); // Print the assigned IP address.
}
// Setup function - runs once when the ESP32 is powered on or reset
void setup() {
pinMode(2, OUTPUT); // Initialize the built-in LED pin as an output.
Serial.begin(115200); // Start Serial communication at 115200 baud.
setup_wifi(); // Call the Wi-Fi setup function.
dhtSensor.setup(DHT_PIN, DHTesp::DHT22); // Initialize the DHT22 sensor.
lcd.init(); // Initialize the LCD.
lcd.backlight(); // Turn on the LCD backlight.
SPI.begin(SD_CLK, SD_MISO, SD_MOSI, SD_CS); // Begin SPI communication with the specified pins.
if (!SD.begin(SD_CS)) { // Try to initialize the SD card.
Serial.println("SD Card initialization failed!");
sdInitialized = false; // Set the SD card flag to false if initialization fails.
} else {
Serial.println("SD Card initialized.");
sdInitialized = true; // Set the SD card flag to true if initialization succeeds.
}
}
// Function to log data to the SD card
void logDataToSD(float temperature, float humidity) {
if (sdInitialized) { // Only log data if the SD card is initialized.
File logFile = SD.open("/datalog.csv", FILE_APPEND); // Open or create the log file in append mode.
if (logFile) {
logFile.print("Timestamp: ");
logFile.print(millis()); // Log the current time in milliseconds since the program started.
logFile.print(" ms, Temp: ");
logFile.print(temperature); // Log the temperature reading.
logFile.print(" °C, Humidity: ");
logFile.print(humidity); // Log the humidity reading.
logFile.println(" %");
logFile.close(); // Close the file after writing.
Serial.println("Data logged to SD card.");
} else {
Serial.println("Failed to open log file for writing."); // Error message if file can't be opened.
}
}
}
// Main loop - runs repeatedly after the setup function
void loop() {
unsigned long now = millis(); // Get the current time in milliseconds.
if (now - lastMsg > 2000) { // Check if 2 seconds (2000 ms) have passed since the last action.
lastMsg = now; // Update the timestamp of the last action.
TempAndHumidity data = dhtSensor.getTempAndHumidity(); // Get temperature and humidity from the DHT22 sensor.
if (isnan(data.temperature) || isnan(data.humidity)) { // Check for invalid readings.
Serial.println("Failed to read from DHT sensor!");
return; // Exit the loop if readings are invalid.
}
String tempStr = String(data.temperature, 2); // Convert temperature to a string with 2 decimal places.
String humStr = String(data.humidity, 1); // Convert humidity to a string with 1 decimal place.
// Print temperature and humidity to the Serial Monitor
Serial.print("Temperature: ");
Serial.println(tempStr);
Serial.print("Humidity: ");
Serial.println(humStr);
// Send data to ThingSpeak
if (WiFi.status() == WL_CONNECTED) { // Check if Wi-Fi is connected.
HTTPClient http; // Create an HTTP client object.
String url = String("http://") + server + "/update?api_key=" + apiKey + "&field1=" + tempStr + "&field2=" + humStr;
http.begin(url); // Begin the HTTP request.
int httpCode = http.GET(); // Send an HTTP GET request.
if (httpCode == 200 || httpCode == 201) { // Check for a successful response.
Serial.println("Data sent to ThingSpeak");
} else {
Serial.print("Error sending data: ");
Serial.println(httpCode); // Print the error code if the request fails.
}
http.end(); // End the HTTP request.
} else {
Serial.println("WiFi not connected!"); // Print an error if Wi-Fi is disconnected.
}
logDataToSD(data.temperature, data.humidity); // Log the sensor data to the SD card.
// Display the temperature and humidity on the LCD
lcd.setCursor(0, 0); // Set cursor to the first line, first column.
lcd.print("Temp: " + String(data.temperature, 1) + "\xDF" + "C"); // Display temperature.
lcd.setCursor(0, 1); // Set cursor to the second line, first column.
lcd.print("Humidity: " + String(data.humidity, 1) + "%"); // Display humidity.
}
}