PDA

View Full Version : working out power factor.

16th February 2011, 08:06
A friend of mine wants to build a box to measure power factor vectors in factories. He has asked me to help him with the programming. What I want to do first is to measure the time difference between the voltage and the current. I was thinking in using a timer on the pic. I really dont know how to do it any help will be appreciated. I have the pulse from the current and voltage. Its just a question of determining the delay between the two.

shantanu@india
16th February 2011, 14:32
Hi,
You need two zero crossing detectors , preferably constructed out of high slew rate op-amps/comparators.You might get circuits of ZCD's using logic gates/Schimtt triggers but they inherently suffer from a phase error between input & output & so is not recommended for precision phase measurement applications.

The output of the ZCD's have to be fed to a XOR gate to generate a pulse proportional to the phase difference of the incident waveforms.

Lastly a PIC can be used to measure the pulse-width & the data can be calibrated in terms of power factor.
The method just described was used by me many years ago to make a C.T phase angle error measuring instrument.

fanie
16th February 2011, 14:51
Hi Anton,

Haven't done it myself, but I think Shantanu is close there. You could probably measure the voltage hitting 0V - which should be no problem, and to measure the current going to hit the zero you can use a piezo electric current sensor or a piezo magnetic sensor with a linear output. You need to hold it close to a current carrying conductor to get a reading.

You would have to do a count from voltage going through zero, to going through zero, to zero again to get a 360 deg count. This count would then represent 360 degrees.

So if you count the voltage going through zero to the current going through zero you should have a count representing the degrees. The rest is simple math.

Stay away from inductive current sensors.

17th February 2011, 05:49
Fanie I have all the hardware. All I need is an explination on how to use one of the timers in the pic to measure the time between the two pulses. A bit of simple code would help.

fanie
17th February 2011, 06:15
Come now Anton

You can use the same plain code to do the 360 deg as well using the voltage only while counting.
You just go through zero twice to count a full 360 degrees. You can of course also just count from 0 to zero for 180 deg.

Poll the volt bit

if vin > 3 then redo
count = 0

now count while you wait for the current to go 0

count = count + 1
if vin > 3 then redo

To calculate the angle

Circle = BigCount / 360 ' counts per degree

Count = count * circle 'degrees between V and A

wastrix
17th February 2011, 07:12
Other ways to do it using interrupts could be:
1. Use the capture part of the CCP module and every time the interrupt occurs, subtract the CCPR1 value from the previous value to get the elapsed time.
2. Use external interrupt pins to start/stop/reset a timer on rising/falling edge of the zero-crossing indicator pulse.

In both cases, you would need to set the timer prescaler to get max resolution but make sure it doesn't expire before you get the next pulse. Obviously if you are measuring zero crossings only the waves cannot be more than 180 degrees out of phase (PF = 1), which means a 10ms max. period in a 50Hz system.

fanie
17th February 2011, 08:14
Yes William, the thing to watch out for is that the timer can do the count, depending on the clock speed. 50Hz or 20ms is quites slow. I always try to do my code so that the finer issues like the difference in clock speed between two pics still gives the same result. The one may count more than the next but the answer comes out the same.

17th February 2011, 13:34
2. Use external interrupt pins to start/stop/reset a timer on rising/falling edge of the zero-crossing indicator pulse.

Now this is what I want to do. I need some basic code please.

ohararp
17th February 2011, 20:13
This is some code I did for timing of a wheel sensor. I basically had a single interrupt per revolution of the wheel. I would then toggle on/off the timer to measure the time it would take for a revolution. If the timer overflowed I would track this

'************************************************* ******************************
INTSR: 'Interrupt Service Routine
If INT0IF = 1 Then
Toggle PORTB.3
Inc REVW 'Increment the internal pulse count - TOT DIST
Inc REVS 'Increment segment revs -SEG DIST
Inc REVCL'Increment Clock Revs - TIME
If ONOFF0 = 0 Then
Clear TIMER0 'Clear TIMER0
Clear TICKSH0
Clear TICKSL0
TMR0ON = 1 'Enable the Timer
ONOFF0 = 1
PRF_W = 0 'Wheel Speed Flag
ElseIf ONOFF0 = 1 Then
TMR0ON = 0 'Stop the Timer
TICKSL0.Byte0 = TIMER0.Byte0 'Read the Low Byte of Timer
TICKSL0.Byte1 = TIMER0.Byte1 'Read the Hi Byte of Timer
ONOFF0 = 0
PRF_W = 1 'Wheel Speed Flag
EndIf
Clear INT0IF 'Clear INT0 Flag (be ready for the next ISR.
EndIf
Context Restore
'************************************************* ******************************
TMRSR: 'Timer Service Routine
Context Save
If TMR0IF = 1 Then
Inc TICKSH0
Clear TMR0IF ' Clear the Timer0 interrupt flag.
EndIf
Context Restore

This second bit of code handled the math processing outside of the interrupts:

CALCWHEEL: 'Calculate the Time For 1 Rev of Roller (Sample Rev, Miss Rev,Sample Rev)
If PRF_W = 1 Then

TICKST0 = TICKSH0 * 65536 + TICKSL0
PPS0_RAW = 625000 / TICKST0 '1/(TICKST0 * 4 * 8 (PS) / 20E6 (XTAL)) = 1/uS

'Take Averages of Velocity to Eliminate Errors
If PPS0_RAW > 0 And PPS0_RAW < 255 Then 'Screen Crazy Values
SAMPLEVAL = PPS0_RAW 'Take a Sample
If SAMPLENUM = 4 Then
GoSub MEDIAN_SORT_FLOAT
PPS0_MED = SAMPLEVAL
SAMPLENUM = 255 'Reset the Index
EndIf
Inc SAMPLENUM 'Inc the Index
EndIf
VMPS = PPS0_MED * .1696 'PPS0*.1696
VMPH = VMPS * 2.2369 'Velocity Miles/Hour

CALCTIME: 'Calculate Time Elapsed during two revolutions add up for time
SEC0 = TICKST0 / 625000 * REVCL 'Time In Seconds * REVCL
SECT = SECT + SEC0
REVCLE = REVCL 'Store REVCL for Elevation Calc
REVCL = 0 'Clear REVCL - # of REVS since last calc

If SECT > 1 Then 'Section Time Greater 1 sec - Inc Second
Inc SECONDS
Inc SECONDS_ST 'Increment Seconds for Storing

If SECONDS_ST = 1 Then 'Seconds_St = 1 Store to SD
PRF_ST = 1
SECONDS_ST = 0
EndIf
PRF_T = 1
SECT = 0
EndIf

If SECONDS > 59 Then 'Seconds > 60 - Inc Minutes
Inc MINUTES
SECONDS = 0
EndIf

If MINUTES > 59 Then 'Minutes > 60 - Inc Hours
Inc HOURS
MINUTES = 0
EndIf

PRF_W = 0 'Clear Wheel Update Flag
PRF_F = 1 'Set Update Force Flag

EndIf

18th February 2011, 10:33
Thanks Ryan ur superstar will study it.

ohararp
18th February 2011, 17:59
PS. Here's all the config bits - with some extras that weren't implemented.

'INTERRUPT DECLARES
Symbol IPEN = RCON.7 'IPEN: Interrupt Priority Enable bit
Symbol GIEH = INTCON.7 'GIE/GIEH: High Priority Interrupt Enable bit
Symbol GIEL = INTCON.6 'PEIE/GIEL: Low Priority Interrupt Enable bit
'TIMER 0 DECLARES - WHEEL SPEED
Symbol TMR0IP = INTCON2.2 'TMR0 Overflow Interrupt Priority bit
Symbol TMR0IE = INTCON.5 'TMR0 Overflow Interrupt Enable bit
Symbol TMR0IF = INTCON.2 'TMR0 Overflow Interrupt Flag bit
Symbol TMR0ON = T0CON.7 'Timer0 On bit
Symbol T08BIT = T0CON.6 'Timer0 8/16 bit Control Bit
Symbol TMR0CS = T0CON.5 'Timer 0 Clock Source Select
Symbol PSA = T0CON.3 'Timer0 Prescale ON/OFF
Dim TIMER0 As TMR0L.Word
T08BIT = 0 '(1 - 8BIT 0 - 16BIT)
TMR0CS = 0 '(1 = Transition on T0CKI 0 - CLK0)
PSA = 0 'Enable Timer0 Prescaler(1 - Off 0 - On)
T0CON.2 = 0 '111 = 1:256 Prescale value
T0CON.1 = 1 '110 = 1:128 Prescale value
T0CON.0 = 0 '101 = 1:64 Prescale value
'100 = 1:32 Prescale value
'011 = 1:16 Prescale value
'010 = 1:8 Prescale value
'001 = 1:4 Prescale value
'000 = 1:2 Prescale value
'TIMER1 DELCARES - HR
Symbol TMR1IP = IPR1.0 'TMR1 Overflow Interrupt Priority bit
Symbol TMR1IE = PIE1.0 'TMR1 Overflow Interrupt Enable bit
Symbol TMR1IF = PIR1.0 'TMR1 Overflow Interrupt Flag bit
Symbol TMR1ON = T1CON.0 'Timer1 On bit
Symbol TMR1CS = T1CON.1 'Timer1 Clock Source (Internal)
Dim TIMER1 As TMR1L.Word
TMR1CS = 0 '(1 - External Clock 0 - Internal Clock)
T1CON.5 = 1 '|11 = 1:8 Prescale value
T1CON.4 = 1 '|10 = 1:4 Prescale value
'|01 = 1:2 Prescale value
'|00 = 1:1 Prescale value
'TIMER3 DELCARES - Cadence
Symbol TMR3IP = IPR2.1 'TMR3 Overflow Interrupt Priority bit
Symbol TMR3IE = PIE2.1 'TMR3 Overflow Interrupt Enable bit
Symbol TMR3IF = PIR2.1 'TMR3 Overflow Interrupt Flag bit
Symbol TMR3ON = T3CON.0 'Timer3 On bit
Symbol TMR3CS = T3CON.1 'Timer3 Clock Source (TMR1)
Dim TIMER3 As TMR3L.Word
TMR3CS = 0 '(1 - External Clock 0 - Internal Clock)
T3CON.5 = 1 '|11 = 1:8 Prescale value
T3CON.4 = 1 '|10 = 1:4 Prescale value
'|01 = 1:2 Prescale value
'|00 = 1:1 Prescale value
'INTERRUPT 0 DECLARES - Wheel Speed
Symbol INT0IP = INTCON3.6 'External Interrupt Priority Bit
Symbol INTEDG0 = INTCON2.6 'External Interrupt Edge selection Rise
Symbol INT0IE = INTCON.4 'External Interrupt Enable Bit
Symbol INT0IF = INTCON.1 'External Interrupt Flag
'INTERRUPT 1 DECLARES - HR
Symbol INT1IP = INTCON3.6 'External Interrupt Priority Bit
Symbol INTEDG1 = INTCON2.5 'External Interrupt Edge selection Rise
Symbol INT1IE = INTCON3.3 'External Interupt Enable Bit
Symbol INT1IF = INTCON3.0 'External Interrupt Flag
'INTERRUPT 2 DECLARES - Crank
Symbol INT2IP = INTCON3.7 'External Interrupt Priority Bit
Symbol INTEDG2 = INTCON2.4 'External Interrupt Edge selection Rise
Symbol INT2IE = INTCON3.4 'External Interupt Enable Bit
Symbol INT2IF = INTCON3.1 'External Interrupt Flag
'SET DECLARE VARIABLES
TRISB = %0000111 'Set RB2 RB1 RB0 to inputs
'Interrupt Priority - Global
IPEN = 1 'Enable priority interrupts.
GIEH = 0 'Disable High Priority Interrupts
GIEL = 0 'Disable Low Priority Interrupts
'Interrupt Edge
INTEDG0 = 1 'Set External Interrupt Edge to rising edge
INTEDG1 = 1 'Set External Interrupt Edge to rising edge
INTEDG2 = 1 'Set External Interrupt Edge to rising edge
'Interrupt Priority - Local
INT0IP = 1 'Set INT0 - RB0 as a High priority interrupt
INT1IP = 1 'Set INT1 - RB1 as a High priority Interrupt
INT2IP = 1 'Set INT2 - RB2 as a High priority Interrupt
'Clear Interrupt Flag
INT0IF = 0 'Clear RB0 INT Flag
INT1IF = 0 'Clear RB1 INT Flag
INT2IF = 0 'Clear RB2 INT Flag
'Enable External Interrupt
INT0IE = 1 'Enable External RB0 Interrupt
INT1IE = 0 'Enable External RB1 Interrupt
INT2IE = 0 'Enable External RB2 Interrupt
'Timer Interrupt Priority Low
TMR0IP = 0 'Set Timer0 as a low priority interrupt source
TMR1IP = 0 'Set Timer1 as a low priority interrupt source
TMR3IP = 0 'Set Timer3 as a low priority interrupt source
'Clear Timer Interrupt Flag
TMR0IF = 0 'Clear the Timer0 interrupt flag
TMR1IF = 0 'Clear the Timer1 interrupt flag
TMR3IF = 0 'Clear the Timer3 interrupt flag
'Enable Timer Interrupts
TMR0IE = 1 'Enable Timer0 interrupts
TMR1IE = 0 'Enable Timer1 interrupts
TMR3IE = 0 'Enable Timer3 interrupts
'Clear Timers
TIMER0 = 0 'Clear Timer0
TIMER1 = 0 'Clear Timer1
TIMER3 = 0 'Clear Timer3
'Ensure Timers are OFF
TMR0ON = 0 'Timer0 OFF
TMR1ON = 0 'Timer1 OFF
TMR3ON = 0 'Timer3 OFF
'Timer1 and Timer 3
'************************************************* ******************************
On_Interrupt INTSR 'RB0/1/2 INTERRUPT SERVICE ROUTINE
On_Low_Interrupt TMRSR 'TIMER0/1/3 Overflow Interrupt