In Alternating Current (AC) electrical system, wave patterns are involved where values are oscillate with time. Today we would like to talk about Phase Angle or Phase Shift. Phase shift is a small difference of oscillation time between two waves pattern. It is a delay between two waves that have same period or frequency. Phase shift is expressed in positive or negative angle which is within -180 to 180 degree and we called it Phase Angle.
Phase shift can be applied between Voltage and Current wave of a particular electrical system. It is often applied by metering system to obtain the quality of the loads / generator. By knowing the phase angle between the Voltage and Current waves, terms such as Power Factor, Real Power, Apparent Power and Reactive Power can be defined.
Phase shift can also be used between Voltage and Voltage wave in a 3-Phase system. It is an important electrical parameter to determine the phase sequence for 3 phase system. Each of the voltage phase is co-relate with adjacent phases by 120 degree phase angle according to right rotation angle. By messing up the phase sequence, there might be issues with your 3-phase loads especially with loads using motor or compressor operation.
For the phase angle comparison, the first wave is taken as a reference to the other. The wave that always taken as reference is always the voltage wave as current wave is always altered based on the applied load. You can also compare between 2 or even 3 voltage waves for a 3-phase system.
Warning ! You are now dealing with high power source ! We assumed that you have the basic electrical knowledge and know what you are dealing with. You may need guidance from experienced guys if you are new to electrical work. Safety and Precaution must be always have in mind. We shall not be responsible for anything happening to you.
The 2 common methods
There are 2 methods to determine the phase angle. The first method is by measuring the time difference to reach peak value (or 0 value) between both waves while using the same starting time or point. This method is direct and simpler method to obtain phase angle. This method is measured based on 2 reference point only (the starting point and peak value point) and it is suitable for pure wave and distorted or high disturbance wave. This method required to measure the period of wave in order to determine the angle value. This post will be using this method for calculation.
The second method is going through calculation by comparing values between averaged instantaneous value and product of RMS values. Phase angle is related to power factor which can be obtained by dividing averaged instantaneous of product values (multiplication of every instantaneous value of wave A and B and average them) and RMS product values (multiplication of RMS wave A and RMS wave B). It is more complicated compared to the previous method as many calculation is involved. This method is more like an average value as each segment of wave also involved for phase angle calculation. Wave frequency or period is not required over a large quantity of sample readings. This method may not be accurate on highly disordered wave or have a lot of electrical noises. We will reserve this method for other post : how to measure AC Power with Arduino. You can check it out here.
Arduino UNO (compatible board)
If you still not yet own an Arduino Micro-controller Board, you can get it cheap at our affiliate link here !!!
Arduino has the ability to measure AC voltage or AC current using analog input pin. For Arduino UNO, there are 6 analog input pins (A0-A5) where you can use one of the pins. Arduino NANO has 8 pins while Arduino MEGA has 16 input pins. The analog input pins will map input voltages between 0 and 5V into integer values between 0 and 1023 with resolution of 4.9mV per unit (5.00V / 1024 units). In order to measure phase angle, 2 Analog input pins are required.
Single Phase AC Voltage Module
This module is equipped with ZMPT101B high-precision voltage transformer and op amp circuit. It can measures AC voltage within 250V. The corresponding output signal can be adjusted using the trimmer potentiometer. You can grab this module at our affiliate link here !!!
Hall-Effect Split-Core HSTS016L AC current sensor module.
This Hall-Effect Split Core Sensor can measure AC current and do not need to make re-wiring or adjustment of existing wiring unlike ACS712 current module. The model ranges from 10A up to 200A. You can get it via our affiliate link here !!! The output voltage of this sensor is 2.5V +/- 0.625V with decent accuracy. I highly recommend this sensor for measuring AC current.
ACS712 Current Sensor Module
This is a AC or DC current sensor rated at 5A, 20A and 30A which are suitable to most applications. You may get them by our affiliate link here !!! The 5A module has the resolution of 185mV/ampere, 20A module has 100mV/ampere while 30A module has the resolution of 66mV/ampere.
float vAnalogRead; float iAnalogRead; int voltageInputPin = A2; // Analog input pin for voltage sensor int currentInputPin = A3; // Analog input pin for current sensor int currentOffset = 0; // key in value for current offset setting int voltageOffset = 0; // key in value for voltage offset setting float virtualMagnification = 5; // to increase the magnification of current value in display void setup() { Serial.begin(9600); } void loop() { vAnalogRead = analogRead(voltageInputPin) - 512 + voltageOffset; iAnalogRead = virtualMagnification*(analogRead(currentInputPin) - 512) + currentOffset; Serial.print(vAnalogRead); Serial.print(" "); Serial.println(iAnalogRead); delay(300); }middle point for both waves should be technically at 512 (analog value) and it fluctuates within 0 to 1023 by default. However, I have amended the code so that the waves are oscillate at middle point 0 value between 512 and -512 for easier calculation later. Before going further, calibration are needed before the measurement as some modules might have different deviation error. You may go to individual sensor post for more info.
How the signal being processed
Before going further, let us begin with initial calibration for both sensors. We need to minimize any potential deviation error or inaccuracy as much as possible. The sensors are very sensitive, make sure to use tight connectors and cable terminals. We need calibrate the analog value for both sensor. When no value detected, both should be at middle of oscillation which is exactly at 0 value.
This calibrations can be done manually by keying the relevant values in the code or automatically if you have the LCD Display shield by pressing the SELECT Button in the LCD Display Shield and wait for about 5 seconds. Of cause you need to have the shield in order to work. You may purchase at our affiliate link here !!!
The code has few stages to make sure it when through the whole stages throughout the wave pattern to prevent miscalculation. The code uses AnalogInput1 (Wave A) as reference. It first determine the entry point to start recording time. The point is where the wave cross over or below 0 value for voltage sensor (wave A). The starting time are the same for all 3 measurement parameters (wave A, wave B and frequency of wave A).
When Wave A more than 0, it keep checking and recording the current time. The time recording is based on whether the recording analog value larger than previous measured value. If at the peak where current recording value no longer larger than previous value, recording time stops and it will be the last recording time. The same applies to wave B which separate time recording and stops at peak value. The time taken from starting point to peak value for wave A is estimate at 75% of the whole period wave (but I’m not using this simple estimation). The time difference taken between wave A and wave B to reach peak is actually the phase shift time which phase angle can be calculated.
When the Wave A back to 0, the time recording for period or frequency is stopped. Period is the time difference between starting point and end point. At the same time, the current time is set as starting time for the next cycle of reading set and the process repeated until 50 cycles (for 50Hz) or 60 cycles (for 60 Hz)
LCD Display Shield
This is a shield that allows the output value of your Arduino board to be displayed on the screen. Since it is a shield, you can just stack it on Arduino board without the need of extra wiring for the LCD Display. You can get the LCD Display board at our affiliate link here !!!.
The good news is you do not need to manually calibrate the offset settings if you got the LCD Display Shield with you. Below we have attached the code that utilizes the button function that could automatically calibrate by itself when you pressed the SELECT Button. You may download from the end of this page below.
UNI-T Multimeter is a good quality with decent price. We have been using UNI-T multimeter for years has not been any issue. We were using UT33C model. You can get yours at our affiliate link here !!!
Hardware Connection
You may need to find a way to fit the AC sensor cable into the Arduino pin. The sensor cable that I purchased came with pre-soldered at the tip, making it easy to go into the Arduino pins. Open the Split Core current module and there will show an arrow symbol which signify the way of current flow. Once everything ready, make sure the split core is closed tightly.
Make sure underneath Voltage sensor does not have exposed conductor or metal plates which may cause you accidental short circuit at the terminal of the module. You need to get the low current fast blown fuse for voltage sensor cable while MCB or fuse of sufficient current rating based on your load to protect against any potential short circuit and fire risk.
In order to connect wiring between Arduino board and module, you need the dupont line cables male to female. You can get it at our affiliate link here !!!
You need the connector that can secure cables and isolate from accidental touch. Get the fast connector at our affiliate link here !!!
You need a fuse to protect your safety and cables!! You can get it here !!
Screw Shield / Expansion Shield
When there are a lot of wiring around especially more than 1 sensor, sharing pins will be difficult as existing pins (ground and 5V) are limited. This shield provides a lot of convenient terminals for each of the input and output pins. The shield can be mounted directly on top of the Arduino Uno board or in between the shields which made it very convenient to use. You can get it at our affiliate link here !!!
Datalogger Shield
If you plan to record the data in a proper way, you may consider this Datalogger Shield. It allows your arduino to record your data in SD Card. Datalogger shield is often installed together with LCD Display shield. Please find it at our affiliate link here !!! For more about this Datalogger Shield, kindly visit our post here.
Software Codes
The final step would be adding source code onto Arduino board. I assume you have installed the Arduino Software. If you have not installed the software, the link here can bring you to the official download site. Once you have downloaded the software, you may download the code file (.ino) for this application below (right click save link).
There is 2 source codes file attached which are source code with and without LCD display shield function. If you don’t have LCD Display shield with you, kindly choose the code that is without LCD Display Shield but you have to manually calibrate and key in the 2 offset values. However, I still highly recommend that you get a LCD Display Shield.
With LCD Display Shield, once the code is uploaded to the Arduino board, the current value will be shown on the LCD Display. We have added the auto calibrate function, once the SELECT button is pressed, the value returns to exact zero point. You only do calibration when no current and voltage in measurement. You may have to wait about 5 seconds long until all values are re-calibrated. If first press is not satisfied, you may repeat by pressing it again.
// Phase Angle By Solarduino // 0- General int decimalPrecision = 2; //1 - Phase Angle, Frequency and Power Factor measurement int expectedFrequency = 50; int analogInputPin1PA = A2; int analogInputPin2PA = A3; float voltageAnalogOffset =0; float currentAnalogOffset =0; unsigned long startMicrosPA; unsigned long vCurrentMicrosPA; unsigned long iCurrentMicrosPA; unsigned long periodMicrosPA; float vAnalogValue =0; float iAnalogValue =0; float previousValueV =0; float previousValueI =0; float previousphaseAngleSample=0; float phaseAngleSample =0; float phaseAngleAccumulate =0; float periodSample=0; float periodSampleAccumulate = 0; float phaseDifference =0; float phaseAngle =0; float frequency = 0; float voltagePhaseAngle=0; float currentPhaseAngle=0; float averagePeriod =0; int sampleCount = 0; int a = 3; float powerFactor; // 1.1 - Phase Angle Offset float currentOffsetRead =0; float currentOffsetLastSample =0; float currentOffsetSampleCount=0; float voltageOffsetRead =0; float voltageOffsetLastSample =0; float voltageOffsetSampleCount=0; // 2 - LCD Display #include<LiquidCrystal.h> LiquidCrystal LCD(8,9,4,5,6,7); void setup() { // 0- General Serial.begin(9600); // 2 - LCD Display LCD.begin(16,2); LCD.setCursor(0,0); } void loop() { // 0- General // 0.1- Button Function int buttonRead; buttonRead = analogRead (0); //Right button is pressed if (buttonRead < 60) { LCD.setCursor(0,0); LCD.print ("PRESS <SELECT> "); } // Up button is pressed else if (buttonRead < 200) { LCD.setCursor(0,0); LCD.print ("PRESS <SELECT> "); } // Down button is pressed else if (buttonRead < 400) { LCD.setCursor(0,0); LCD.print ("PRESS <SELECT> "); } // Left button is pressed else if (buttonRead < 600) { LCD.setCursor(0,0); LCD.print ("PRESS <SELECT> "); } //Select button is pressed else if (buttonRead < 800) { currentOffsetRead = 1; voltageOffsetRead = 1; LCD.setCursor(0,0); LCD.print ("INITIALIZING..... "); LCD.setCursor(0,1); LCD.print ("WAIT 5 SEC ..... "); } // 1 - Phase Angle, Frequency and Power Factor measurement vAnalogValue = analogRead(analogInputPin1PA)-512 + voltageAnalogOffset; iAnalogValue = analogRead(analogInputPin2PA)-512 + currentAnalogOffset; if((vAnalogValue>0) && a == 3) { a=0; } if((vAnalogValue<=0) && a ==0) { startMicrosPA = micros(); a=1; } if((vAnalogValue>0) && a ==1) { a = 2; previousValueV = 0; previousValueI = 0; } if((vAnalogValue > previousValueV ) && a==2) { previousValueV = vAnalogValue ; vCurrentMicrosPA = micros(); } if((iAnalogValue > previousValueI) && a==2) { previousValueI = iAnalogValue ; iCurrentMicrosPA = micros(); } if((vAnalogValue <=0) && a==2) { periodMicrosPA = micros(); periodSample = periodMicrosPA - startMicrosPA; periodSampleAccumulate = periodSampleAccumulate + periodSample; voltagePhaseAngle = vCurrentMicrosPA - startMicrosPA; currentPhaseAngle = iCurrentMicrosPA - startMicrosPA; phaseAngleSample = currentPhaseAngle - voltagePhaseAngle; if(phaseAngleSample>=100) { previousphaseAngleSample = phaseAngleSample; } if(phaseAngleSample<100) { phaseAngleSample = previousphaseAngleSample; } phaseAngleAccumulate = phaseAngleAccumulate + phaseAngleSample; sampleCount = sampleCount + 1; startMicrosPA = periodMicrosPA; a=1; previousValueV = 0; previousValueI = 0; } if(sampleCount == expectedFrequency) { averagePeriod = periodSampleAccumulate/sampleCount; frequency = 1000000 / averagePeriod; phaseDifference = phaseAngleAccumulate / sampleCount; phaseAngle = ((phaseDifference*360) / averagePeriod); powerFactor = cos(phaseAngle*0.017453292); Serial.print("Phase Angle :"); Serial.print(phaseAngle,decimalPrecision); Serial.print("° "); Serial.print("Frequency :"); Serial.print(frequency,decimalPrecision); Serial.print("Hz "); Serial.print("Power Factor :"); Serial.println(powerFactor,decimalPrecision); sampleCount = 0; periodSampleAccumulate = 0; phaseAngleAccumulate =0; // 2 - LCD Display LCD.setCursor(0,0); LCD.print("P. Angle ="); LCD.print(phaseAngle,decimalPrecision); LCD.print((char)223); LCD.print(" "); LCD.setCursor(0,1); LCD.print(frequency,decimalPrecision); LCD.print("Hz "); LCD.print(powerFactor,decimalPrecision); LCD.print("PF "); } // 1.1 - Phase Angle Offset if( voltageOffsetRead == 1) { voltageAnalogOffset = 0; if(millis()>= voltageOffsetLastSample + 1) { voltageOffsetSampleCount = voltageOffsetSampleCount + 1; voltageOffsetLastSample = millis(); } if(voltageOffsetSampleCount == 1500) { vAnalogValue = analogRead(analogInputPin1PA)-512 + voltageAnalogOffset; voltageAnalogOffset = -1*(vAnalogValue); voltageOffsetRead = 0; voltageOffsetSampleCount = 0; } } if( currentOffsetRead == 1) { currentAnalogOffset = 0; if(millis()>= currentOffsetLastSample + 1) { currentOffsetSampleCount = currentOffsetSampleCount + 1; currentOffsetLastSample = millis(); } if(currentOffsetSampleCount == 1500) { iAnalogValue = analogRead(analogInputPin2PA)-512 + currentAnalogOffset; currentAnalogOffset = -1*(iAnalogValue); currentOffsetRead = 0; currentOffsetSampleCount = 0; } } }
Before we end, we would like to give gratitude to you for taking the time to read the post. We would need readers like you to support us in order to keep growing. You can support us in the following ways :
Donate & Fund Raising
If you like my work, please send me a donation to encourage me to do more. Thanks
Aliexpress Affiliate
We are the member of Aliexpress affiliate marketing. Do support us by clicking the affiliate product links if you do wish to purchase them.
Like and Share
If you like our post, we need your support to like and share our posts or videos so that it can reach more and more people like you !!
Result – In Serial Monitor
Result – In LCD Display
For Arduino Code Files, Remember to Right Click > Save Link As … You may alter the internal code as you wish. Happy coding !!