#include <WiFi.
h>
#include <WiFiClient.h>
#include <WiFiAP.h>
const char *ssid = "play";
const char *password = "play1234";
WiFiServer server(80);
#include <ArduinoJson.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
WiFiClient client;
#define OUTPUT_1_PIN 27
#define OUTPUT_2_PIN 26
#define OUTPUT_3_PIN 25
#define OUTPUT_4_PIN 33
#define PUSH_SWITCH_1 13
#define PUSH_SWITCH_2 15
#define PUSH_SWITCH_3 14
#define PUSH_SWITCH_4 12
#define CURRENT_SENSOR_PIN 34
#define VOLTAGE_SENSOR_PIN 35
#define VOLTAGE_DIVIDER_RATIO 100.0
#define BASE_WATT_VOLTAGE 0.2
#define WATT_INCREMENT_PER_VOLT 0.9
#define ALERT_UNIT_THRESHOLD 10.0
#define NOMINAL_VOLTAGE 220.0
LiquidCrystal_I2C lcd(0x27, 16, 2);
bool outputStates[4] = {false, false, false, false};
bool lastSwitchStates[4] = {false, false, false, false};
float currentReading = 0.0;
float voltageReading = 0.0;
float powerReading = 0.0;
float unitConsumed = 1.0;
float totalUnits = 1.0;
unsigned long lastTime = 0;
bool alertShown = false;
bool clientConnected = false;
String alert = "";
#define UNIT_ADDR 0
#define TOTAL_UNITS_ADDR 4
void setup() {
[Link](115200);
pinMode(OUTPUT_1_PIN, OUTPUT);
pinMode(OUTPUT_2_PIN, OUTPUT);
pinMode(OUTPUT_3_PIN, OUTPUT);
pinMode(OUTPUT_4_PIN, OUTPUT);
pinMode(PUSH_SWITCH_1, INPUT_PULLUP);
pinMode(PUSH_SWITCH_2, INPUT_PULLUP);
pinMode(PUSH_SWITCH_3, INPUT_PULLUP);
pinMode(PUSH_SWITCH_4, INPUT_PULLUP);
digitalWrite(OUTPUT_1_PIN, HIGH);
digitalWrite(OUTPUT_2_PIN, HIGH);
digitalWrite(OUTPUT_3_PIN, HIGH);
digitalWrite(OUTPUT_4_PIN, HIGH);
[Link]();
[Link]();
[Link]();
[Link](0, 0);
[Link]("Smart Meter");
[Link](0, 1);
[Link]("Initializing...");
[Link](512);
loadData();
setupAccessPoint();
updateDisplay();
}
void setupAccessPoint() {
[Link](ssid, password);
IPAddress myIP = [Link]();
[Link]("AP IP address: ");
[Link](myIP);
[Link]();
[Link]();
[Link](0, 0);
[Link]("WiFi AP Ready");
[Link](0, 1);
[Link]("SSID: play");
delay(3000);
}
void loop() {
handleSocketConnection();
if (millis() - lastTime >= 1000) {
readSensors();
calculatePower();
calculateCurrent();
calculateUnits();
checkAlert();
updateDisplay();
sendDataToClient();
lastTime = millis();
handlePushSwitches();
}
}
void handleSocketConnection() {
if (!clientConnected) {
client = [Link]();
if (client) {
[Link]("New client connected");
clientConnected = true;
[Link](true);
[Link]();
[Link](0, 0);
[Link]("Client Connected");
delay(2000);
}
} else {
if (![Link]()) {
[Link]("Client disconnected");
clientConnected = false;
[Link]();
[Link]();
[Link](0, 0);
[Link]("Client Disconnected");
delay(2000);
} else {
handleClientCommands();
}
}
}
void handleClientCommands() {
if ([Link]()) {
String command = [Link]('\n');
[Link]();
if ([Link]() > 0) {
[Link]("Received command: " + command);
if ([Link]("TOGGLE:")) {
int output = [Link](7).toInt();
if (output >= 0 && output < 4) {
toggleOutput(output);
sendResponse("OK");
} else {
sendResponse("ERROR: Invalid output");
}
} else if (command == "RESET") {
resetUnits();
sendResponse("OK");
} else if (command == "GET_DATA") {
sendDataToClient();
} else if (command == "CALIBRATE") {
calibrateVoltage();
sendResponse("Calibration complete - check Serial Monitor");
} else {
sendResponse("ERROR: Unknown command");
}
}
}
}
void sendResponse(String response) {
if (clientConnected && [Link]()) {
[Link](response);
[Link]();
}
}
void sendDataToClient() {
if (clientConnected && [Link]()) {
StaticJsonDocument<200> doc;
doc["voltage"] = voltageReading;
doc["current"] = currentReading;
doc["power"] = powerReading;
doc["unitConsumed"] = unitConsumed;
doc["totalUnits"] = totalUnits;
doc["output1"] = outputStates[0];
doc["output2"] = outputStates[1];
doc["output3"] = outputStates[2];
doc["output4"] = outputStates[3];
doc["alert"] = alert;
String jsonString;
serializeJson(doc, jsonString);
[Link]("DATA:" + jsonString);
[Link]();
}
}
void handlePushSwitches() {
int switchPins[4] = {PUSH_SWITCH_1, PUSH_SWITCH_2, PUSH_SWITCH_3, PUSH_SWITCH_4};
int outputPins[4] = {OUTPUT_1_PIN, OUTPUT_2_PIN, OUTPUT_3_PIN, OUTPUT_4_PIN};
for (int i = 0; i < 4; i++) {
bool currentSwitchState = !digitalRead(switchPins[i]);
if (currentSwitchState && !lastSwitchStates[i]) {
toggleOutput(i);
[Link]("Output ");
[Link](i + 1);
[Link](": ");
[Link](outputStates[i] ? "ON" : "OFF");
}
lastSwitchStates[i] = currentSwitchState;
}
}
void toggleOutput(int output) {
if (output >= 0 && output < 4) {
outputStates[output] = !outputStates[output];
int outputPins[4] = {OUTPUT_1_PIN, OUTPUT_2_PIN, OUTPUT_3_PIN, OUTPUT_4_PIN};
digitalWrite(outputPins[output], !outputStates[output]);
}
}
float voltageReadings[10] = {0};
int voltageIndex = 0;
float powerReadings[5] = {0};
int powerIndex = 0;
void readSensors() {
int voltageRaw = 0;
for (int i = 0; i < 5; i++) {
voltageRaw += analogRead(VOLTAGE_SENSOR_PIN);
delayMicroseconds(100);
}
voltageRaw = voltageRaw / 5;
float voltage = (voltageRaw / 12.08);
voltageReadings[voltageIndex] = voltage;
voltageIndex = (voltageIndex + 1) % 10;
float sum = 0;
for (int i = 0; i < 10; i++) {
sum += voltageReadings[i];
}
voltageReading = sum / 10.0;
if (voltageReading < 5.0) {
voltageReading = 0.0;
}
static int debugCounter = 0;
debugCounter++;
if (debugCounter >= 10) {
[Link]("Raw ADC: ");
[Link](voltageRaw);
[Link](", ADC Voltage: ");
[Link](voltage, 2);
[Link]("V, AC RMS: ");
[Link](voltageReading, 1);
[Link]("V");
debugCounter = 0;
}
}
void calculatePower() {
int temppowerReading = 0;
if ((analogRead(CURRENT_SENSOR_PIN) == 0)) {
if ((outputStates[0] == true) || (outputStates[1] == true) || (outputStates[2]
== true) || (outputStates[3] == true)) {
powerReading = 100.0;
} else {
powerReading = 0.0;
}
} else if ((analogRead(CURRENT_SENSOR_PIN) < 1500) &&
(analogRead(CURRENT_SENSOR_PIN) > 500)) {
powerReading = (analogRead(CURRENT_SENSOR_PIN) + 144) / 6.82;
} else if ((analogRead(CURRENT_SENSOR_PIN) > 1500) &&
(analogRead(CURRENT_SENSOR_PIN) < 2500)) {
powerReading = (analogRead(CURRENT_SENSOR_PIN)) / 8.73;
} else if ((analogRead(CURRENT_SENSOR_PIN) > 2500)) {
powerReading = (analogRead(CURRENT_SENSOR_PIN)) / 9.77;
} else {
powerReading = 0.0;
}
if (powerReading < 2.0) {
powerReading = 0.0;
}
if (powerReading > 450) {
outputStates[0] = false;
outputStates[1] = false;
outputStates[2] = false;
outputStates[3] = false;
digitalWrite(OUTPUT_1_PIN, HIGH);
digitalWrite(OUTPUT_2_PIN, HIGH);
digitalWrite(OUTPUT_3_PIN, HIGH);
digitalWrite(OUTPUT_4_PIN, HIGH);
overloadScreen();
alert = "OVER LOAD";
sendDataToClient();
delay(4000);
alert = "";
}
}
void overloadScreen() {
[Link]();
[Link](0, 0);
[Link](" Alert! ");
[Link](0, 1);
[Link](" OVER LOAD ");
}
void calculateCurrent() {
if (voltageReading > 0) {
currentReading = powerReading / voltageReading;
} else {
currentReading = 0.0;
}
if (currentReading > 100.0) currentReading = 100.0;
if (currentReading < 0.0) currentReading = 0.0;
}
void calculateUnits() {
float energyThisSecond = (powerReading / 1000);
[Link](energyThisSecond);
unitConsumed = unitConsumed + energyThisSecond;
[Link](unitConsumed);
totalUnits = totalUnits + energyThisSecond;
static int saveCounter = 0;
saveCounter++;
if (saveCounter >= 30) {
saveData();
saveCounter = 0;
}
}
void checkAlert() {
if (unitConsumed >= ALERT_UNIT_THRESHOLD && !alertShown) {
showAlert();
alert = "Unit limit exceeded";
sendDataToClient();
alertShown = true;
}
}
void showAlert() {
[Link]();
[Link](0, 0);
[Link]("ALERT!");
[Link](0, 1);
[Link]("Unit: ");
[Link](unitConsumed, 3);
[Link](" kWh");
delay(3000);
}
void updateDisplay() {
[Link]();
[Link](0, 0);
[Link]("V:");
[Link](voltageReading, 1);
[Link]("VAC I:");
[Link](currentReading, 2);
[Link]("A");
[Link](0, 1);
[Link]("P:");
[Link](powerReading, 0);
[Link]("W U:");
[Link](unitConsumed, 3);
}
void resetUnits() {
unitConsumed = 0.0;
alertShown = false;
saveData();
alert = "";
[Link]("Units reset");
}
void loadData() {
[Link](UNIT_ADDR, unitConsumed);
[Link](TOTAL_UNITS_ADDR, totalUnits);
if (isnan(unitConsumed)) {
unitConsumed = 0;
}
if (isnan(totalUnits)) {
totalUnits = 0;
}
}
void saveData() {
[Link](UNIT_ADDR, unitConsumed);
[Link](TOTAL_UNITS_ADDR, totalUnits);
[Link]();
}
void calibrateVoltage() {
[Link]("=== Voltage Calibration for Pakistan AC (220V) ===");
[Link]("Connect 220V AC and check readings");
[Link]("Expected: ADC ~2.2V should show ~220V AC");
for (int i = 0; i < 10; i++) {
int voltageRaw = analogRead(VOLTAGE_SENSOR_PIN);
float voltage = (voltageRaw / 4095.0) * 3.3 * VOLTAGE_DIVIDER_RATIO;
float voltageRMS = voltage / 1.414;
[Link]("Sample ");
[Link](i + 1);
[Link](": Raw ADC = ");
[Link](voltageRaw);
[Link](", ADC Voltage = ");
[Link](voltage, 2);
[Link]("V, AC RMS = ");
[Link](voltageRMS, 1);
[Link]("V");
delay(1000);
}
[Link]("=== Calibration Complete ===");
[Link]("For 220V AC, ADC should read ~2.2V");
[Link]("If incorrect, adjust VOLTAGE_DIVIDER_RATIO");
}