#include <PZEM004Tv30.h>
#include <arduinoFFT.h>
#define NUM_SAMPLES 128
#define SAMPLING_FREQUENCY 1000
double vReal[NUM_SAMPLES];
double vImag[NUM_SAMPLES];
ArduinoFFT<double> FFT = ArduinoFFT<double>(vReal, vImag, NUM_SAMPLES, SAMPLING_FREQUENCY);
#define RX_PIN 16
#define TX_PIN 17
PZEM004Tv30 pzem(Serial2,RX_PIN, TX_PIN);
unsigned long lastCheck = 0;
unsigned long checkInterval = 1000;
float prevVoltage = 0, prevCurrent = 0;
#define VOLTAGE_THRESHOLD 20.0
#define CURRENT_THRESHOLD 0.1
#define POWER_THRESHOLD 10.0
float voltageThreshold = 10.0;
float currentThreshold = 0.5;
float nominalVoltage = 220.0;
float thresholdPercentage = 5.0;
float inrushCurrent = 0;
const float inrushThreshold = 10.0;
void setup() {
Serial.begin(115200);
}
void loop() {
if (millis() - lastCheck >= checkInterval) {
lastCheck = millis();
checkForFaults();
}
}
void checkForFaults() {
float voltage = pzem.voltage();
float current = pzem.current();
float power = pzem.power();
float frequency = pzem.frequency();
float pf = pzem.pf(); // Power factor
Neutralloss( voltage, current, power);
PhaseLoss(voltage);
ArcFault( voltage, current);
PowerFactor(pf);
VoltageVariation(voltage);
InrushCurrent(current);
sendReport(voltage, current, power, frequency, pf);
}
void Neutralloss(float voltage, float current, float power) {
if (voltage < VOLTAGE_THRESHOLD || current < CURRENT_THRESHOLD || power < POWER_THRESHOLD) {
Serial.println("Neutral loss detected!");
}
}
void PhaseLoss(float voltage) {
if (voltage < VOLTAGE_THRESHOLD+160.0) {
Serial.println("Phase loss detected!");
}
}
void ArcFault(float voltage, float current) {
if (abs(voltage - prevVoltage) > voltageThreshold || abs(current - prevCurrent) > currentThreshold) {
Serial.println("Warning: Possible Arc Fault Detected!");
}
prevVoltage = voltage;
prevCurrent = current;
}
void checkHarmonics(float current) {
// Sample current waveform and run FFT analysis
for (int i = 0; i < NUM_SAMPLES; i++) {
vReal[i] = current; // Replace with actual sampled current value
vImag[i] = 0; // Clear imaginary part for FFT
// Sample delay to match the desired sampling rate
}
// Perform FFT on the sampled data
FFT.windowing(vReal, NUM_SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
FFT.compute(vReal, vImag, NUM_SAMPLES, FFT_FORWARD);
FFT.complexToMagnitude(vReal, vImag, NUM_SAMPLES);
// Analyze FFT result to detect harmonics
for (int i = 1; i < (NUM_SAMPLES / 2); i++) {
float frequency = i * (SAMPLING_FREQUENCY / NUM_SAMPLES);
if (vReal[i] > 0.1) { // Adjust threshold for harmonic detection
Serial.print("Harmonic detected at frequency: ");
Serial.print(frequency);
Serial.print(" Hz with magnitude: ");
Serial.println(vReal[i]);
// Send alert if abnormal harmonics detected (for example, if harmonic magnitude exceeds a threshold)
if (frequency != 50 && vReal[i] > 0.3) { // Example condition for alert
Serial.println("Warning: Abnormal harmonic detected!");
}
}
}
}
void PowerFactor(float pf) {
if (pf < 0.8) {
Serial.println("Low Power Factor Detected");
}
}
void VoltageVariation(float voltage) {
float lowerLimit = nominalVoltage * (1 - thresholdPercentage / 100.0);
float upperLimit = nominalVoltage * (1 + thresholdPercentage / 100.0);
// Detect voltage variation
if (voltage < lowerLimit) {
Serial.println("Warning: Voltage drop detected!");
}
else if (voltage > upperLimit) {
Serial.println("Warning: Voltage rise detected!");
}
else {
Serial.println("Voltage is within the acceptable range.");
}
}
void InrushCurrent(float current) {
if (current > inrushThreshold) {
inrushCurrent = current;
Serial.print("Inrush Current Detected: ");
Serial.println(inrushCurrent, 3);
}
}
void sendReport(float voltage, float current, float power, float frequency, float pf) {
Serial.println("Periodic Report");
Serial.print("Voltage: "); Serial.println(voltage);
Serial.print("Current: "); Serial.println(current);
Serial.print("Power: "); Serial.println(power);
Serial.print("Frequency: "); Serial.println(frequency);
Serial.print("Power Factor: "); Serial.println(pf);
}