Power Factor Correction

Thread Starter

hgalbuzi

Joined Mar 4, 2013
4
i am working on a project titled Micro controller based Power factor Correction. My Current challenges are the code for zerocrossing detector and power factor calculation. am hoping on using capture Module (CCP) and interrupts and a PIC18F4550. attached is the circuit.
 

Attachments

kubeek

Joined Sep 20, 2005
5,795
Two things to that schematic, the current transformer needs a burden reistor in parallel according to its datasheet, and the relay needs a back emf protection diode.

Another thing is that you should be able to power your circuit from the TX2, that could save an external power supply.
 

ErnieM

Joined Apr 24, 2011
8,377
While you're getting your power off TX2 you should get ALL your power off TX2 and delete the power section off TX1. It doesn't work anyway when the motor is off.

I've never used the CCP module, thus I have no guidance there. I'm out.
 

JohnInTX

Joined Jun 26, 2012
4,787
I know the CCP. What language are you developing in? I defer to the other responders about the best way to do the hardware but if I understand your schematic, you want to measure the time between line zero crossing and that in the motor circuit?
 
Last edited:

Thread Starter

hgalbuzi

Joined Mar 4, 2013
4
if i may add, i want to use the two zero crossing detectors to sense current and voltage crossing, find the lag and use it to calculate for the power factor
 

JohnInTX

Joined Jun 26, 2012
4,787
You can measure the time (in Tcycs) between events on CCP1 (zero crossing) and CCP2 (lead-lag) by driving both from the same internal timer (TMR3) and enabling interrupts in sequence. The timer itself just free runs and does not have to be set to any initial value. The general sequence is:

Clear CCP2IE (not using it yet)
Clear CCP1IF (clear any pending capture IRQs)
Set CCP1IE (enable capture on the next edge)

At zero-crossing, CCP1IF will interrupt the processor AND capture the current TMR3 value in CCPR1H/L. Service CCP1IF by:
Clear CCP2IE
Set CCP2IF (enable capture IRQ of the next lead/lag edge).

At the lead-lag edge, CCP2IF will irq the processor AND capture TMR3 in CCPR2H/L.
Clear CCP2IE

Subtract CCPR1H/L from CCP2RH/L. If the value is negative, TMR3 rolled over between the captures and the result is the 2's comp of the time difference. Take the 2's comp in this case.

The final result is the number of Tcycs * the timer prescaler from which you can calculate the phase between the signals.

Re-enable CCP1IE for the next go-round

The main setup stuff is:
T3CON = r1pp0001 the bold sets both CCPs to use TMR3. pp is the prescaler setting.
CCPxCON = 000001001 capture every rising edge (change to 1000 for falling edge)
TMR3IE = 0 (no IRQ on overflow)
CCPxIE controlled by program/IRQ service

Other things:
TMR3 period must be long enough to span a line cycle plus a little.

The scheme requires that IRQ service happens in sequence and that the values are consumed before the next capture. Consider using the high priority IRQ to ensure prompt service. Note that even with the IRQs disabled, the capture will still happen. If you really can't get to it in time, turn clear each CCPxCON register to disable the capture until you are ready for the next one. You may miss some line cycles.

Consider the best way to use the result. You don't want to spend a lot of time or do a lot of math in the IRQ service routine. I do the subtraction and adjustment with a short inline assembler routine. You could also copy the captured values to holding registers, raise a flag in the IRQ that both are new and let the main routine do the math. A potential problem with that is if you get bogged down in getting the values, you might wind up getting a new zero crossing value captured while getting around to getting the values. You can resolve some of this with flags etc but its just nice to have a complete, usable value ready at all times.

Leads and lags are both positive results. <1/2 line cycle time is a lag, >1/2 is a lead.

You could avoid the subtraction by clearing TMR3 and leaving it off. Turn it on when the zero crossing happens as part of CCP1IF service. The value in CCP2RH/L on lead/lag is the actual time. Note that this method requires adjustment to the value to compensate for the time in Tcycs it takes to service the zero crossing IRQ and start the timing. If you know the time, you can preset TMR3 to that value (instead of clearing it). The problem with this is that you are at the mercy of the IRQ code generated by the compiler and that can change unexpectedly, throwing off your adjustment. I prefer the free running, two-capture method.

Dont forget to:
Check the compiler docs to see how they name the 16 bit (made of 2 separate 8 bit registers) to be sure you are getting the whole 16 bits.
Declare the result register as 'volatile' and disable the IRQs (GIE is OK for this short time) while reading it to avoid an IRQ update between reading the bytes. Read it once to a temp register and use it from there.
set RCON:IPEN to 1 to enable hi priority interrupts
set IPR1:CCP1IP and IPR2:CCP2IP to 1 to make those IRQs high priority.
Use whatever pragma is required to install the service routine at the high priority vector.
Check the interrupt enable flags CCP1IE and CCP2IE before checking CCPxIF to keep the sequence. BTW, its usually better to do this like:

Rich (BB code):
 if(CCP1IE)
   if(CCP1IF){
     service the IRQ
   }

if(CCP2IE)
   if(CCP2IF){
     service the IRQ
   }
than

Rich (BB code):
if(CCP1IE && CCP1IF)
  service the IRQ

if(CCP2IE && CCP2IF)
  service the IRQ
as the compiler can do simple bit tests/skips.

I've used some derivative of this technique many times for phaze detection, echo-ranging etc. but never did any digital PF correction stuff. I'm anxious to see how its done.

Have fun.
 
Last edited:
Top