/*
* ESP32 Smart Energy Monitor with Manual Relay Control
* Reconfigured with new requirements:
* - ESP32 as main controller
* - GSM module for SMS messaging (simulated)
* - Relay module to control bulb/load
* - Pushbuttons for manual relay ON/OFF control
* - 16x2 LCD (I2C) for real-time display
* - Potentiometers to simulate voltage & current sensors
* - Real-time power calculation (P = V * I)
*
* HARDWARE CONFIGURATION:
* - ESP32: Main microcontroller
* - LCD 16x2 I2C: SDA=Pin21, SCL=Pin22
* - Relay Module: Control=Pin2
* - Button ON (Green): Pin4 (with pull-up)
* - Button OFF (Red): Pin5 (with pull-up)
* - Voltage Potentiometer: Pin36 (ADC1_CH0)
* - Current Potentiometer: Pin39 (ADC1_CH3)
* - GSM Module: TX0/RX0 (simulated with OLED)
* - Bulb/Load: Connected through relay NO contact
*/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Pin Definitions
#define RELAY_PIN 2 // Relay control pin
#define BUTTON_ON_PIN 4 // Green button for relay ON
#define BUTTON_OFF_PIN 5 // Red button for relay OFF
#define VOLTAGE_POT_PIN 36 // Potentiometer for voltage simulation
#define CURRENT_POT_PIN 39 // Potentiometer for current simulation
// LCD Configuration (I2C)
LiquidCrystal_I2C lcd(0x27, 16, 2);
// System Variables
bool relayState = false;
float voltage = 0.0;
float current = 0.0;
float power = 0.0;
float energy = 0.0;
unsigned long lastTime = 0;
unsigned long lastDisplayUpdate = 0;
unsigned long lastGsmUpdate = 0;
int gsmMessageCount = 0;
// Button states for debouncing
bool lastButtonOnState = HIGH;
bool lastButtonOffState = HIGH;
unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 50;
void setup() {
Serial.begin(115200);
// Initialize pins
pinMode(RELAY_PIN, OUTPUT);
pinMode(BUTTON_ON_PIN, INPUT_PULLUP);
pinMode(BUTTON_OFF_PIN, INPUT_PULLUP);
// Initialize relay to OFF state
digitalWrite(RELAY_PIN, LOW);
relayState = false;
// Initialize LCD
lcd.init();
lcd.backlight();
lcd.clear();
// Welcome message
lcd.setCursor(0, 0);
lcd.print("ESP32 Energy");
lcd.setCursor(0, 1);
lcd.print("Monitor v2.0");
delay(2000);
// Initialize GSM simulation
Serial.println("=== ESP32 Smart Energy Monitor Started ===");
Serial.println("Initializing GSM module...");
Serial.println("AT");
Serial.println("OK");
Serial.println("AT+CPIN?");
Serial.println("+CPIN: READY");
Serial.println("GSM module initialized (simulated)");
Serial.println("\n=== COMPONENT MAPPING ===");
Serial.println("- ESP32: Main Controller");
Serial.println("- LCD 16x2: SDA=21, SCL=22 (I2C)");
Serial.println("- Relay Module: Control Pin 2");
Serial.println("- Button ON (Green): Pin 4");
Serial.println("- Button OFF (Red): Pin 5");
Serial.println("- Voltage Sensor (Pot): Pin 36");
Serial.println("- Current Sensor (Pot): Pin 39");
Serial.println("- GSM Module: UART0 (Simulated)");
Serial.println("- Bulb/Load: Through Relay NO contact");
Serial.println("\n=== SYSTEM READY ===");
lastTime = millis();
}
void loop() {
unsigned long currentTime = millis();
// Handle button presses with debouncing
handleButtons();
// Read sensor values (potentiometers simulate voltage and current sensors)
readSensors();
// Calculate power (P = V * I)
power = voltage * current;
// Calculate energy accumulation (simple integration)
if (currentTime - lastTime >= 1000) { // Every second
float timeHours = (currentTime - lastTime) / 3600000.0; // Convert ms to hours
energy += power * timeHours; // kWh
lastTime = currentTime;
}
// Update LCD display every 500ms
if (currentTime - lastDisplayUpdate >= 500) {
updateLCDDisplay();
lastDisplayUpdate = currentTime;
}
// Send GSM messages every 30 seconds
if (currentTime - lastGsmUpdate >= 30000) {
sendGsmMessage();
lastGsmUpdate = currentTime;
}
// Print serial data every 2 seconds
static unsigned long lastSerialPrint = 0;
if (currentTime - lastSerialPrint >= 2000) {
printSerialData();
lastSerialPrint = currentTime;
}
}
void handleButtons() {
bool currentButtonOnState = digitalRead(BUTTON_ON_PIN);
bool currentButtonOffState = digitalRead(BUTTON_OFF_PIN);
// Button ON pressed (LOW = pressed due to pull-up)
if (currentButtonOnState == LOW && lastButtonOnState == HIGH) {
if (millis() - lastDebounceTime > debounceDelay) {
turnRelayOn();
lastDebounceTime = millis();
}
}
// Button OFF pressed
if (currentButtonOffState == LOW && lastButtonOffState == HIGH) {
if (millis() - lastDebounceTime > debounceDelay) {
turnRelayOff();
lastDebounceTime = millis();
}
}
lastButtonOnState = currentButtonOnState;
lastButtonOffState = currentButtonOffState;
}
void turnRelayOn() {
digitalWrite(RELAY_PIN, HIGH);
relayState = true;
Serial.println(">>> RELAY ON - Load Connected <<<");
// Send GSM notification
Serial.println("\n=== GSM MESSAGE SENT ===");
Serial.println("TO: +1234567890");
Serial.println("MSG: Load turned ON manually. Power monitoring active.");
Serial.println("STATUS: Message sent successfully");
Serial.println("========================\n");
}
void turnRelayOff() {
digitalWrite(RELAY_PIN, LOW);
relayState = false;
Serial.println(">>> RELAY OFF - Load Disconnected <<<");
// Send GSM notification
Serial.println("\n=== GSM MESSAGE SENT ===");
Serial.println("TO: +1234567890");
Serial.println("MSG: Load turned OFF manually. Standby mode active.");
Serial.println("STATUS: Message sent successfully");
Serial.println("========================\n");
}
void readSensors() {
// Read potentiometer values (0-4095 for ESP32 ADC)
int voltageRaw = analogRead(VOLTAGE_POT_PIN);
int currentRaw = analogRead(CURRENT_POT_PIN);
// Convert to realistic voltage values (180V to 250V)
voltage = map(voltageRaw, 0, 4095, 180, 250);
// Convert to realistic current values (0A to 20A)
current = map(currentRaw, 0, 4095, 0, 2000) / 100.0;
// If relay is OFF, current should be minimal
if (!relayState) {
current = current * 0.1; // 10% of reading for standby current
}
}
void updateLCDDisplay() {
lcd.clear();
// First line: Voltage and Current
lcd.setCursor(0, 0);
lcd.print("V:");
lcd.print(voltage, 0);
lcd.print("V I:");
lcd.print(current, 1);
lcd.print("A");
// Second line: Power and Relay status
lcd.setCursor(0, 1);
lcd.print("P:");
lcd.print(power, 0);
lcd.print("W ");
if (relayState) {
lcd.print("[ON]");
} else {
lcd.print("[OFF]");
}
}
void sendGsmMessage() {
gsmMessageCount++;
Serial.println("\n=== GSM STATUS MESSAGE ===");
Serial.println("AT+CMGS=\"+1234567890\"");
Serial.print("MSG #");
Serial.print(gsmMessageCount);
Serial.print(": System Status - V:");
Serial.print(voltage, 1);
Serial.print("V, I:");
Serial.print(current, 1);
Serial.print("A, P:");
Serial.print(power, 1);
Serial.print("W, Load:");
Serial.print(relayState ? "ON" : "OFF");
Serial.print(", Energy:");
Serial.print(energy, 3);
Serial.println("kWh");
Serial.println("+CMGS: OK");
Serial.println("=========================\n");
}
void printSerialData() {
Serial.print("Time: ");
Serial.print(millis() / 1000);
Serial.print("s | Voltage: ");
Serial.print(voltage, 1);
Serial.print("V | Current: ");
Serial.print(current, 1);
Serial.print("A | Power: ");
Serial.print(power, 1);
Serial.print("W | Energy: ");
Serial.print(energy, 4);
Serial.print("kWh | Relay: ");
Serial.println(relayState ? "ON" : "OFF");
}