Power Factor Calulation of R & RL Load

Hello Guys,

I have to make a Power Analyzer Using Arduino in which I have to show Power, Voltage, Current & Power Factor at different loads.

Now, I have designed a Voltage Sensor using this tutorial

and purchased current sensor ACS-712(20A).

I have build a program to calculate apparent power and average power but it is giving me the same value therefore, when it comes to PF it always shows 0.99 or 1.0 either on Resistive(Bulb, Energy Saver) or RL load(AC single phase motor, Fan, etc). How to resolve this issue??

To calculate the Power Factor I am using this theory:

rather than zero crossing detector.

I have attached the program. Just to clarify that in this program I have done RS-485 Modbus communication with PLC.

I have also attached the Serial Communication and HMI screen shots to make it clear to you.

#define ADC_PIN A0
#define ADCI_PIN A2
#define SAMPLING 1000

#include <modbus.h>
#include <modbusDevice.h>
#include <modbusRegBank.h>
#include <modbusSlave.h>
modbusDevice regBank;
modbusSlave slave;

#define RS485TxEnablePin 2
#define RS485Baud 9600
#define RS485Format SERIAL_8E1

float Ianalog=0,adc_max,adc_min,adc_vpp,vout,value,prev;

//Variable Decleration For RMS & Inst 
float Iinst,Vinst;
double Isq,Vsq;
double Iavg,Vavg;
double Irms,Vrms;
double Prms,Pinst,PF;
double b = 0;
float VoltLevel = 3.72;

void setup()
  //Assign the modbus device ID.  


  //Add Analog Input registers to the register bank

//Add Analog Output registers to the register bank
  slave._device = &regBank;  

void loop()
  int a = 0;
   for(int cnt=0;cnt<SAMPLING;cnt++)
        //Caluclation For Instantaneous Current
          Ianalog = analogRead(A2);
          if(Ianalog > adc_max)
            adc_max = Ianalog;
          if(Ianalog < adc_min)
            adc_min = Ianalog;
          Iinst = abs((((adc_max-adc_min)/10023))*20*7.727-0.04);
          Pinst += ((5.0/1023.0)*analogRead(A0)*(220/VoltLevel))*Iinst;
        //Caluclation For Sum Of Square Current
        Isq += sq( Iinst);        
        //Caluclation For Instantaneous Voltage
        vout  = (5.0/1023.0)*analogRead(A0);
        Vinst = (vout*220)/VoltLevel;
        //Caluclation For Sum Of Square Voltage
        Vsq += sq(Vinst);        
        //Caluclation For Instantaneous Power                                                                   
        //Serial.println(String ("Pinst = ")+Vinst + " * " + Iinst + " = "+Vinst*Iinst);
        //Caluclation For RMS Current
        Iavg = Isq/SAMPLING;
        Irms = sqrt(Iavg);
        //Caluclation For RMS Voltage
        Vavg = Vsq/SAMPLING;
        Vrms = sqrt(Vavg);

        //Caluclation For RMS Power
        Prms = Vrms*Irms;

        //Caluclation For Inst Power
        Pinst = Pinst/SAMPLING;
        //False Current Reading
        if (Prms < 18 && Pinst < 18)
          Prms = 0;
          Pinst = 0;
        //Caluclation For Power Factor
        PF = Pinst/Prms;

        if(PF == 1)
        PF = 0;
        if (b>2)
        Serial.println("Energy Analyzer");
        Serial.println(String("Instantaneous Voltage = ")+ Vinst + " Vac");
        Serial.println(String("Instantaneous Current = ")+ Iinst + " Iac");
        Serial.println(String("Average Voltage = ")+ Vavg + " Vac");
        Serial.println(String("Average Current = ")+ Iavg + " Iac");
        Serial.println(String("RMS Voltage = ")+ Vrms + " Vac");
        Serial.println(String("RMS Current = ")+ Irms + " Amp");
        Serial.println(String("Average Power P = ")+ Pinst + " Watt");
        Serial.println(String("Apparent Power S = ")+ Prms + " VA");
        Serial.println(String("Power Factor PF = ")+ PF + " ");
        double Intiger=0,fract=0;
        double Intiger1=0,fract1=0;
        double Intiger2=0,fract2=0;
        double Intiger3=0,fract3=0;
        //fract = 0;Intiger=0;
        //fract= modf (Vrms, &Intiger);
        //fract = fract*100;
        regBank.set(30001, Vrms); //from 0 - 1023
        //regBank.set(30002, (word) fract); //from 0 - 1023
        fract= modf (Irms, &Intiger);
        fract = fract*100;
        regBank.set(30003, Intiger); //from 0 - 1023
        regBank.set(30005, fract); //from 0 - 1023

        fract2= modf (Prms, &Intiger2);
        fract2 = fract2*100;
        regBank.set(30007,Intiger2); //from 0 - 1023
        regBank.set(30009,fract2); //from 0 - 1023

        fract3= modf (PF, &Intiger3);
        fract3 = fract3*100;
        regBank.set(30011,Intiger3); //from 0 - 1023
        regBank.set(30013,fract3); //from 0 - 1023

      Vsq = 0;
      Isq = 0;
      Pinst = 0;

         * abs(((((adc_max-adc_min)/2)*(20*1.74))/1023)-0.05);   
         * /2 = mean
         * *20/1023 = 0.01955
         * -0.05 = callibration

Power_Analyzer.ino (4.82 KB)

How long does an analogRead() take? This delay can explain the 0.99 power factor with a resistive load. I also wonder why the voltage is sampled twice, once for the calculation and once for the monitor output.

I didn't dig deeper into the calculations, perhaps motors produce unexpected values as loads. Check with a scope?

Instantaneous power divided by rms power is not power factor. You absolutely need to measure phase and hence zero crossing to calculate power factor. I repectfully submit you should study and understand the concept of power factor before you try to calculate it from unrelated data points.

Hi, Welcome to the forum.

Can you please tell us your electronics, programming, Arduino, hardware experience?

Have you googled arduino reading power factor

Thanks.. Tom.. :)

How would I make zero crossing of current and voltage for Power factor , because I have made using Op-amp but it didn't work . So, do you have any circuit or any idea to calculate Power Factor.

Hi, Did you read post #3 and look at google?

Can you please tell us your electronics, programming, Arduino, hardware experience?

Thanks.. Tom... :)


Thank for your reply! Yes I did, and as you asked about my esperience, I am an electronic engineer and I have worked on PIC and Arduino Micro Controller, and developed many undergraduate projects.

Is there an issue in sensor interfacing or proper calculation of these sensors. Therefore, I am uploading the value of voltage sensor.

Kindly check the program and the output as well, whereas I ahve also attached the schematic of voltage sensor as well.

#define ADC_PIN A0

//Variable Declaration
int VoltRaw,VoltLevel=3.72,SAMPLING=200;
float VoltConv=0;
void setup()

void loop()
   Serial.println("200 samples");
   for(int cnt=0;cnt<SAMPLING;cnt++)
        //Values Of RAW value of voltage A0       
          VoltRaw = analogRead(A0);
          Serial.println(String("RAW Value = ")+ VoltRaw);

        //Convt into voltage
          VoltConv = (5.0/1023.0)*(VoltRaw)*(220/VoltLevel);  
          Serial.println(String("Converted Voltage = ")+ VoltConv); 

For the sampling

period of time interval of 20 ms, the instantaneous current

and voltage were multiplied to obtain the instantaneous

power. The total number of samples of instantaneous

power obtained was then average by the total number of

sample collected in 20 ms.

from your attached method, ask yourself how many samples in 20mS are you working on? what would mr nyquist think of your sampling effort ?

Moderator edit: personal insult removed

Dear racpi.

Thanks for your reply.

I couldn't understand you properly. Could you please elaborate?

I am answering what I understand from your reply is, I have used the above research paper, but in the program I have made more samples than 20ms.

Without knowing what your input AC REALLY is we cannot make any judgements on your figures.

The addition of the 10uF capacitor means you are no longer sampling the AC waveform, the input to the UNO analog input will be a voltage representing the Peak Voltage of the AC input.
The zener is 4.7V?
You are probably only getting 3.72V because of the impedance of the circuit and the 0.6V drop across the diode.

I'm not sure why you want 200 samples of a continuous DC input.

I would be very careful of having my controller connected directly to 230Vac mains.

I am an electronic engineer and I have worked on PIC and Arduino Micro Controller, and developed many undergraduate projects.

I would recommend you get some electrical engineering lessons, I'm surprised that an electronics engineer knows so little about true and reactive power and how to handle mains voltage.

Tom... :slight_smile:

Hi, The YouTube you refered us to, is to measure Vpeak and calculate Vrms, NOT to sample the AC waveform.

Sorry but its amazing what they give away in CornFlakes packets these days.

Tom... :)

Hi Tom,

Your are absolutely right. But I have not graduated yet I am in 7 semester.

Sir, I just want to know please guide me for power factor.

MZohaib: Hi Tom,

Your are absolutely right. But I have not graduated yet I am in 7 semester.

Sir, I just want to know please guide me for power factor.

You have at your disposal a University loaded with experience and information. Go and show your lecturers/tutors what you are doing, they should be willing to help you learn, thats their job. They can show you in better ways than we can as to how to aquire what you need. Tom... :)

I am an electronic engineer

A more accurate statement would be "I am a student of electronics engineering, but do not yet have a good understanding of power factor in AC circuits".

The Arduino forum is not the place to learn about power factor. However, the Arduino can be used to measure it. When you get to that point, let us know and we will be happy to help.