Hi Fanman,
Here is a little code that uses an interrupt to start a timer and measure the period of a sine wave. It is written for a PIC18F1220.
You could do something similar, but you would start 2 timers. One to measure the period of the sinewave, and another to time from the start of the sine wave till your other pulse. Then calculating the phase angle would be quite easy. If you use the "PIC Timer Calculator" this makes using the timers fairly easy.Code:define OSC 20 'channel 0 analog all others digital TRISA = 255 ADCON0 = %00000001 'Vref = Vss Vdd, turn on A/D ADCON1 = %11111110 'Only Channel 0 analog ADCON2 = %10001010 'Right justified, 2 TAD, TOSC/32 (for 20MHz) INCLUDE "DT_INTS-18.bas" ' Base Interrupt System INCLUDE "ReEnterPBP-18.bas" ' Include if using PBP interrupts badweld var portb.3 prim var portb.0 prim1 var portb.1 bren var portb.2 thy3 var portb.6 thy2 var portb.5 thy1 var portb.4 input badweld input prim input bren high thy3 high thy2 high thy1 input prim1 angletime var word temp var word period var word period1 var word period2 var word period3 var word period4 var word sixtydeg var word thirtydeg var word multiplier var word decimal1 var word decimal2 var word adresult var word x var byte 'for next loop variable rot var bit 'rotation 1 = forward 0 = reverse zeroflag var bit 'flag set to 1 at zero crossing pause 1000 'give time for supply to settle gosub rotation 'set up timer T0CON = %00000000 '1/2 prescale fosc/4 not running TMR0H = 0 ;Clear registers TMR0L = 0 ASM INT_LIST macro ; IntSource, Label, Type, ResetFlag? INT_Handler INT0_INT, _ZERO, PBP, yes endm INT_CREATE ; Creates the interrupt processor ENDASM @ INT_ENABLE INT0_INT ; enable external (INT) interrupts goto cycle '-------Interrupt Service Routine------------------ ZERO: @ bcf T0CON,TMR0ON ; Switch off timer period.lowbyte = TMR0L 'Record Result period.highbyte = TMR0H @ clrf TMR0H ; Reset registers to zero @ clrf TMR0L @ bsf T0CON,TMR0ON ;Start timer period1 = period2 'Move values up the stack period2 = period3 period3 = period4 period4 = (period / 5) 'Put new reading at bottom of stack period = (period1 + period2 + period3 + period4) / 2 'scale period value in micro seconds sixtydeg = period / 6 thirtydeg = sixtydeg / 2 multiplier = (period / 4) / 859 decimal1 = (period / 4) // 859 DIg 0 decimal2 = (period / 4) // 859 dig 1 zeroflag = 1 'Set zero crossing flag
I would suggest using the interrupt for timing the period, and starting both timers, and just use PBP to stop the second timer, and do the maths etc.
The input is a H11L1 opto isolator, resistor, and diode in series across the mains. I am measuring 3 phase at 415 volts, I use 33K 14W resistor. The input goes high roughly 500uS before actual zero crossing, but this can be compensated for in the maths.
Bob...




Bookmarks