Hello, I am working on a project that calculates the power factor of a 120Vac - 60Hz network. I have had problems with the fast Fourier transform and the calculation of the phase shift of the voltage and current signals using the atan2 function. I obtain the voltage signal with a voltage divider along with a DC voltage so that the ESP32 can read the negative values of the wave. I obtain the current signal with a current transformer along with a voltage divider and an operational amplifier in voltage follower mode. Help me with the program.
#include <arduinoFFT.h>
const uint16_t samples = 128; // Este valor DEBE ser siempre una potencia de 2
const double samplingFrequency = 15360; // Hz, se puede aumentar en ESP32. 7680
unsigned int sampling_period_us;
unsigned long microseconds;
void setup() {
Serial.begin(115200);
analogReadResolution(12);
sampling_period_us = round(1000000 * (1.0 / samplingFrequency));
}
//-------------------------------------------------
double vRealA[samples];
double vImagA[samples];
double cRealA[samples];
double cImagA[samples];
ArduinoFFT<double> FFTvoltajeA = ArduinoFFT<double>(vRealA, vImagA, samples, samplingFrequency);
ArduinoFFT<double> FFTcorrienteA = ArduinoFFT<double>(cRealA, cImagA, samples, samplingFrequency);
//-------------------------------------------------
void loop() {
//bool señalI_1_cruzó = false;
float I_1 = senal_C_1();
float Irms_1 = get_C_1();
Serial.print("Irms_1: ");
Serial.println(Irms_1);
float V_1 = senal_V_1();
float Vrms_1 = get_V_1();
Serial.print("Vrms_1: ");
Serial.println(Vrms_1);
microseconds = micros();
for (int i = 0; i < samples; i++)
{
vRealA[i] = senal_V_1();
vImagA[i] = 0;
cRealA[i] = senal_C_1();
cImagA[i] = 0;
while (micros() - microseconds < sampling_period_us) {
// bucle vacío
}
microseconds += sampling_period_us;
}
FFTvoltajeA.windowing(FFTWindow::Hamming, FFTDirection::Forward);
FFTvoltajeA.compute(FFTDirection::Forward);
//FFTvoltajeA.complexToMagnitude();
double peakvoltajeA = FFTvoltajeA.majorPeak(vRealA, samples, samplingFrequency);
//Serial.print ("peakvoltajeA: ");
//Serial.println (peakvoltajeA);
FFTcorrienteA.windowing(FFTWindow::Hamming, FFTDirection::Forward);
FFTcorrienteA.compute(FFTDirection::Forward);
//FFTcorrienteA.complexToMagnitude();
double peakcorrienteA = FFTcorrienteA.majorPeak(cRealA, samples, samplingFrequency);
// Encontrar el índice de la frecuencia fundamental
float f_fundamental = 60.0; // Ajusta a tu frecuencia
int indiceFundamental = round(peakvoltajeA * samples / samplingFrequency);
float fasevoltajeA = atan2(vImagA[indiceFundamental], vRealA[indiceFundamental]);
float fasecorrienteA = atan2(cImagA[indiceFundamental], cRealA[indiceFundamental]);
float desfaseA = fasevoltajeA - fasecorrienteA;
float FP_A = cos(desfaseA);
Serial.println(FP_A);
//delay(sampling_period_us);
}
//---------------------------------------------------------------
int C_prom_1 (int n1){
long sumaC_1 = 0;
for(int i1 = 0; i1<n1; i1++){
sumaC_1 = sumaC_1 + analogRead(34);
}
return (sumaC_1/n1);
}
float senal_C_1(){
float senalC_1 = C_prom_1(10)*(3.3/4095.0)-1.46; //1.46
float senal_scale_C_1 = senalC_1 *22.5; //22.5
return (senal_scale_C_1);
}
float get_C_1(){
float corriente_1 = 0;
float sumatoriaC_1 = 0;
float Irms_1 = 0;
long tiempoC_1 = millis();
int N1 = 0;
while(millis() - tiempoC_1 < 16.6){
corriente_1 = senal_C_1();
sumatoriaC_1 = sumatoriaC_1 + sq(corriente_1);
N1 = N1 + 1;
delay (1);
}
Irms_1 = sqrt(sumatoriaC_1/N1);
return (Irms_1);
}
//------------------------------------------------------------
//---------------------------------------------------------------
//---------------------------------------------------------------
int V_prom_1 (int m1){
long sumaV_1 = 0;
for(int l1 = 0; l1<m1; l1++){
sumaV_1 = sumaV_1 + analogRead(32);
}
return (sumaV_1/m1);
}
float senal_V_1(){
float senalV_1 = V_prom_1(10)*(3.3/4095.0)-1.48; //10
float senal_scale_V_1 = senalV_1 * 127; //160 - 127
return (senal_scale_V_1);
}
float get_V_1(){
float voltaje_1 = 0;
float sumatoriaV_1 = 0;
float Vrms_1 = 0;
long tiempoV_1 = millis();
int M1 = 0;
while(millis() - tiempoV_1 < 16.6){
voltaje_1 = senal_V_1();
sumatoriaV_1 = sumatoriaV_1 + sq(voltaje_1);
M1 = M1 + 1;
delay (1);
}
Vrms_1 = sqrt(sumatoriaV_1/M1);
return (Vrms_1);
}