// ============================================================
// Bijli Chor Hunter — Wokwi Simulation Version
// NMIMS MPSTME | B.Tech CSE Sem IV | AY 2025-26
// ============================================================
#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>
// WiFi Credentials (Wokwi default)
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// ThingSpeak Configuration
const char* apiKey = "B7F6M6LX19V0AHYU";
const char* server = "http://api.thingspeak.com/update";
// Timing Variables for ThingSpeak
unsigned long lastUpload = 0;
const unsigned long UPLOAD_INTERVAL = 15000; // 15 seconds
// ─── Pin Definitions ───
#define PIN_SOURCE 34 // Pot 1 wiper → simulates ACS712 Source
#define PIN_LOAD 35 // Pot 2 wiper → simulates ACS712 Load
#define PIN_VOLTAGE 32 // Pot 3 wiper → simulates ZMPT101B
#define LED_GREEN 2 // Normal state indicator
#define LED_YELLOW 4 // Line Fault indicator
#define LED_RED 5 // Power Theft indicator
#define BUZZER 18 // Active buzzer
#define PIN_THEFT_SWITCH 27
// ─── Calibration Constants ───
const float SENSITIVITY = 0.185; // ACS712-05B: 185mV/A
const float VCC = 3.3; // ESP32 ADC reference voltage
const float ADC_MAX = 4095.0; // 12-bit ADC
const float DELTA_THRESH = 0.5; // Theft threshold (Amps)
const float VOLT_THRESH = 180.0; // Fault voltage threshold (V)
const float VOLT_FACTOR = 218.5; // ZMPT101B calibration factor
const int SAMPLES = 500;
// ─── RMS Current Calculation ───
float getRMSCurrent(int pin) {
float sum = 0;
for (int i = 0; i < SAMPLES; i++) {
float voltage = (analogRead(pin) / ADC_MAX) * VCC;
float current = (voltage - (VCC / 2.0)) / SENSITIVITY;
sum += current * current;
}
return sqrt(sum / SAMPLES);
}
// ─── RMS Voltage Calculation ───
float getRMSVoltage(int pin) {
float sum = 0;
for (int i = 0; i < SAMPLES; i++) {
float v = (analogRead(pin) / ADC_MAX) * VCC;
sum += v * v;
}
return sqrt(sum / SAMPLES) * VOLT_FACTOR;
}
void setup() {
Serial.begin(115200);
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_YELLOW, OUTPUT);
pinMode(LED_RED, OUTPUT);
pinMode(BUZZER, OUTPUT);
pinMode(PIN_THEFT_SWITCH, INPUT_PULLUP);
// WiFi Connection Setup
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi Connected!");
Serial.println("=====================================");
Serial.println(" Bijli Chor Hunter - Wokwi Simulation");
Serial.println("=====================================");
}
void loop() {
// ─── Reset all outputs ───
digitalWrite(LED_GREEN, LOW);
digitalWrite(LED_YELLOW, LOW);
digitalWrite(LED_RED, LOW);
digitalWrite(BUZZER, LOW);
// ─── Read Sensors ───
float Is = getRMSCurrent(PIN_SOURCE);
float IL = getRMSCurrent(PIN_LOAD);
float V = getRMSVoltage(PIN_VOLTAGE);
// ─── MID-LINE THEFT SIMULATION ───
// If the switch is flipped, add 1.5A to the source reading
if (digitalRead(PIN_THEFT_SWITCH) == LOW) {
Is = Is + 1.5;
}
float deltaI = abs(Is - IL);
// ─── Detection Logic ───
int status = 0;
String stateName = "";
if (V < VOLT_THRESH && deltaI >= DELTA_THRESH) {
status = 3; stateName = "*** FAULT + THEFT ***";
digitalWrite(LED_RED, HIGH);
digitalWrite(LED_YELLOW, HIGH);
digitalWrite(BUZZER, HIGH);
} else if (V < VOLT_THRESH) {
status = 2; stateName = "!!! LINE FAULT !!!";
digitalWrite(LED_YELLOW, HIGH);
digitalWrite(BUZZER, HIGH);
} else if (deltaI >= DELTA_THRESH) {
status = 1; stateName = ">>> POWER THEFT <<<";
digitalWrite(LED_RED, HIGH);
digitalWrite(BUZZER, HIGH);
} else {
status = 0; stateName = "[ NORMAL ]";
digitalWrite(LED_GREEN, HIGH);
}
// ─── Serial Monitor Output ───
Serial.println("-------------------------------------");
Serial.printf("Is = %.3f A | IL = %.3f A | V = %.1f V\n", Is, IL, V);
Serial.printf("STATUS: %s\n", stateName.c_str());
// ─── ThingSpeak Upload (Non-blocking) ───
if (millis() - lastUpload >= UPLOAD_INTERVAL) {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
// Using String() conversion for reliability
String url = String(server) + "?api_key=" + String(apiKey)
+ "&field1=" + String(Is)
+ "&field2=" + String(IL)
+ "&field3=" + String(V)
+ "&field4=" + String(deltaI)
+ "&field5=" + String(status);
http.begin(url);
int httpCode = http.GET();
if (httpCode > 0) {
Serial.printf("ThingSpeak Update Successful (%d)\n", httpCode);
} else {
Serial.printf("ThingSpeak Error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
lastUpload = millis(); // Reset timer after upload attempt
} else {
Serial.println("WiFi Disconnected. Skipping Upload.");
}
}
delay(500); // Short delay to keep the loop responsive
}