# How to Measure AC Power Factor Using Arduino

20,032

9

47

Hi everyone! This is my third instructable, hope you find it informative :-) This will be an instructable on how to make a basic power factor measurement using an Arduino. Before we start theres a few things to bear in mind:

1. This will ONLY work with LINEAR loads (e.g inductive motors, transformers, solenoids)
2. This will NOT work with NON-LINEAR (e.g. CFL Bulbs, switch mode power supplies, LED's)
3. I am an electrical engineer and very competent when working with mains potential (i.e. 230V)

Warning! If you are not trained or do not know how to work correctly with mains voltage I suggest you don't proceed with that part of the instructable and I will show you a safe method of proving the circuit works.

This is a hardware solution to the problem of measuring PF in linear loads. This can be also be done purely through code including the ability to measure non-linear loads, which I will aim to cover in another instructable.

For the benefit of any beginners reading this, power factor is the ratio of true power to apparent power and can be calculated by finding the cosine of the phase angle between the supply voltage and current (see attached image from Google). This is significant in AC applications as "Apparent Power" (Volt-Amperes) can be easily calculated using Voltage multiplied by Current. However to get the real power or "True Power" (Watts) apparent power must be multiplied by the power factor to make a true measurement of power in Watts. This only applies to loads which have a significant inductive or capactive component (such as a motor). Purely resistive loads such as electric heaters or incandescent bulbs have a power factor of 1.0 (unity) and therefore True Power and Apparent Power are the same.

## Step 1: Circuit Design

Power factor can be calculated using an oscilloscope, by measuring the time difference between the voltage and current signal. These can be measured at any point in the wave as long as they are sampled in the same place. In this case it was logical to measure between zero crossing points (points in the wave where the voltage crossed the X-axis).

I designed the following circuit in Multisim. Assuming the current and voltage to the load are pure sinusoidal waveforms, the power factor can be measured. Each waveform is fed into a zero crossing detector (sometimes known as a sine to square wave converter) which is simply an 741 op-amp in comparator mode where the comparison voltage is 0V. When the sine wave is in the negative cycle a negative DC pulse is generated, and when the sine wave is positive a positive DC pulse is generated. The two square waves are then compared using an exclusive OR (XOR) logic gate, which will output a positive high DC pulse only when the square waves do not overlap, and 0V when they overlap. The output of the XOR gate is therefore time difference (delta t) between the two waves from the point they cross the zero point. This difference signal can then be timed by a microcontroller and converted to power factor using the following calculation (make sure your scientific calculator is in degrees not radians):

cos(phi) = f * dt * 360

Where:

cos(phi) - the power factor

f - The frequency of the measured supply

dt - delta t or time difference between the waves

360 - a constant used to give answer in degrees

In the pictures you will see three simulated oscilloscope traces for the circuit. The two input signals represent the current and the voltage to the load. I have given the second signal a phase difference of 18 Deg, to demostrate the theory. This gives a PF of approx 0.95.

## Step 2: Prototyping & Testing

For my prototype build I put the circuit design on a solderless breadboard. From the UA741CN datasheet and CD4070CN datasheet both IC's run off a 12-15 Vdc supply so I powered using two batteries to make a dual rail +12V ,0V ,-12V Volt power supply.

You can simulate a load by using a dual channel signal generator or function generator. I used this cheap and cheerful Chinese box to produce two 50 Hz sine waves 18 deg apart, and fed the signals into the circuit. You can see the resultant waveforms on an oscilloscope. In the pictures above you can see the two overlapping square waves (output from each op-amp), and the other three pictures are illustrating the output of the XOR gate. Notice how the width of the output pulse grows shorter with decreasing phase angle. Examples above show 90, 40, 0 Degrees.

## Step 3: Arduino Code

As mentioned above, the output from the measurement circuit is the time difference between the two input signals (i.e. the current and the voltage signal). The arduino code uses "pulseIn" to measure the length of the output pulse from the measurement circuit in nano seconds and uses it in the PF formula mentioned above.

The code starts by defining constants, mainly to make the code more organised and readable. Most importantly, C code (arduino code) works in radians not degrees, so a conversion from radians to degrees is needed to calculate angle's and PF's later on. One radian is approx. 57.29577951 degrees. The number 360 is also stored and the multiplication factor 1x10^-6 for converting nano Seconds into plain Seconds. Frequency is also defined at the start, if you are using anything other than 50Hz make sure this is updated at the start of the code.

Inside "void loop()" I've told the Arduino to calculate the angle based on the PF formula mentioned earlier. On my first iteration of this code, the code would return the correct angle and power factor, however between each correct result some erroneous low value also be returned in the serial console. I noticed this was was either every other reading or every four measurements. I placed an "if" statement inside a "for" loop to store the maximum value of every four consecutive readings. It does this by comparing the calculation against "angle_max" which is initially zero, and if it is bigger stores the new value inside "angle_max". This is repeated for the PF measurement. By doing this in a "for" loop it means the correct angle and pf are always returned, but if the measured angle changes (higher or lower), when "for" ends "angle_max" resets to zero for the next test, when "void loop()" repeats. There's a very good example of how this works on the Arduino website (https://www.arduino.cc/en/Tutorial/Calibration). The second "if" formula simply prevents any value higher than 360 being returned in the event of erroneous high being measured when the device under test is switched off.

## Step 4: The Acid Test!

Do not attempt the following unless you know how to work safely with AC mains voltage. If you are in doubt as to your safety, try simulating the input signals with a dual-channel waveform generator.

At the request of a follower, I've made a breadboard layout on Fritzing to give a better idea of the circuit and sampling/sensing circuit (I have attached the .fzz file and a .png diagram). The motor at the top represents the desk fan I used, and the induction coil represents the current transformer I wrapped around the Live conductor. I powered the 741 IC's using a two 12V batteries packs arranged to give +12 VDC, 0 VDC (ground), and -12 VDC. The CD4070 can also be powered directly from the Arduino's 5V power rail.

To prove the concept works in reality, the circuit was built on a solder less breadboard. From the pictures you can see the circuit arrangement. I have used a desk fan as my inductive load to test the concept. Between the 230V mains supply and the load is my sensing equipment. I have a step down transformer which transforms 230V directly to 5V to allow the voltage waveform to be sampled. A non-invasive current transformer clamped around the live conductor was used to sample the current waveform (right of the aluminium clad resistor). Note that you do not necessarily need to know the amplitude of the current or voltage, just the waveform for the op-amp to identify the zero crossing. The above pictures show the actual current and voltage waveforms from the fan, and the arduino serial console, which reports a PF of 0.41 and an angle of 65 Deg.

This working principal can be incorporated into a home made energy monitor to make true power measurements. If your competent you can try monitoring different inductive and resistive loads and determining their power factor. And there it is! a very simply method of measuring power factor.

## 47 Discussions

I am impressed after reading this wonderful instructable.. I am building a similar project by following the
instructions on your page. However, I am getting some weird readings. I am getting my angles as:
143, 153, 146 etc and my pf_max goes negative then. Of course, I can take just
the magnitude but just wanted to know if it’s possible?

I’m using this circuit for getting my
voltage: https://circuitdigest.com/microcontroller-projects/arduino-ac-voltmeter

And I have a https://www.maglab.ch/products/sct-t16/
(100A/333mV) CT, which I am feeding directly to my opamp.

And then taking output of these two and
feeding into my XOR gate. And then running your code on Arduino ide using a
Arduino Nano on pin D4.

Does this arrangement look right to you?
I would really appreciate your help.

Hello,

I really thank you a lot for your effort and your work and that you are still replying to the questions, you provided a multism schematic plus a fritzing schematic to try to make as clear as possible to us, I thank you again and I appreciate it so much but actually one thing did not make sense to me, please if you explain it:

in the fritzing schematic, there are two wires coming out of each op amp ic (pin4) and both of them are to be connected to ground, but they are connected to another line, the lower one, the one above it is the ground, so i really do not understand why we connected only these two pins to a line which is neither high or low, connecting them like this is connecting pin 4 of the first ic to pin 4 of the second one.

The same notice, about the two two red wires which are to be connected to the high rail.

I am waiting for your explaination and thanks a lot