Measuring audio phase shift through a circuit with a PIC
Need a sanity check here.
I'd like to measure the phase shift through an audio circuit at different test frequencies, therefore to measure this with a PIC.
In principle it's fairly simple - ie time a an audio signal for one complete cycle, store the result, immediately start timing how long until the output signal gets to the same point (ie use a comparator for both signals). Do some maths with the resulting times...this will yield the phase shift in degrees.
I've setup something along these lines.
(the input to my audio circuit is fed into the PIC comparator1, the output of my audio circuit feeds comparator2. Also timer1 is mapped to comparator 1, an timer2 is mapped to comparator 2 from a 'clock counting' perspective)
++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++
enable comparator1 interrupts
when comparator1 interrupts, start timer1 running
when comparator1 interrupts again, do the following....
stop timer1 running & store the 'count' (this gives a clock pulse 'count' for the arriving frequency, but since I'm only after phase shift...which is a time based measurement, I don't calculate the frequency)
clear timer2
start timer2
enable comparator2 interrupts
Ok, now when comparator2 interrupts, stop timer2 & store the count
My problem is that I can't seem to get the count of timer2 up in count value (no matter what I do with the prescalers) .
For example I know the phase of the input vs output for my circuit 180 degrees out of phase (I can see this on my scope - it's a simple inverting opamp setup to test this all out), but I'm getting readings like this...
comp1=2434 comp2=151
comp1=2432 comp2=151
comp1=2431 comp2=151
comp1=2431 comp2=151
comp1=2433 comp2=151
comp1=2432 comp2=151
comp1=2433 comp2=151
comp1=2432 comp2=151
Now for a signal that is 180 degrees out phase, I reckon comparator 2 should interrupt 'in or around' half the time that timer1 counted.
Is my methodology wrong, is is my code wrong?
(the prescalers prob aren't right below, but my issue is that no matter what I set the prescalers to, the second timer2 count (ie the inverted signal) never get's anythere near 50% of timer1)
Code:
@ __CONFIG _FCMEN_OFF & _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _CP_OFF & _IESO_OFF & _BOR_OFF & _PWRTE_OFF
'***********************************************************************************************
'16F690 Pin Connections....
' PIN# NAME USE & CONNECTION
' 1 Vdd +5VDC power supply
' 7 RC3 C12IN3- (external comparator1 input)
' 14 RC2 C12IN3- (external comparator2 input)
' 20 Vss Ground
'*************************************************************************************
DEFINE OSC 8 ' set Oscillator at 8Mhz.
DEFINE NO_CLRWDT 1
DEFINE HSER_SPBRG 25 'HSEROUT Stuff.
DEFINE HSER_TXSTA 24h 'HSEROUT Stuff.
DEFINE HSER_CLROERR 1 'HSEROUT Stuff.
txsta = %10100100 'setup the tx register
RCSTA.7 = 1 ' Enable RB7 for TX USART
INTCON.0 = 0 ' clears the RABIF Flag (to 0), COULD be 1 on reset (unique to F690)
ANSEL = 0 'disable AtoD.
ANSELH = 0 'disable AtoD.
'Turn on & Set up Comparator 1
CM1CON0 = %10100111 'Comparator1 On
VRCON = %0000001 'turn on internal reference
'Turn on & Set up Comparator 2
CM2CON0 = %10100110 'turn on comparator 2.
Comp1Time var word ' used to amalgamate TMR1 High & Low Bytes.
Frequency var word 'used to convert the count to frequency.
Comp2Time VAR WORD
PHASE var word
INCLUDE "DT_INTS-14.bas" ' Base Interrupt System PO90OOO9
INCLUDE "ReEnterPBP.bas" ' Include if using PBP interrupts
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler CMP1_INT, _Comp1_Int, PBP, yes
INT_Handler CMP2_INT, _Comp2_Int, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
T1CON = $10 ;
T1CON.0=0 'stop tmr1
TMR1H = 0 'Set the high part of the timer1 value to 0
TMR1L = 0 'Set the low part of the timer1 value to 0
@ INT_ENABLE CMP1_INT ; enable Comparator 1 interrupts
t2con = %00000000010 ' tmr2 prescaler 16
TMR2 = 0 'Set the high part of the timer2 value to 0
Comp1Time = 0 'clear down Comp1Time, prior to starting.
comp2Time = 0 'clear down Comp2Time, prior to starting
'Main body of Code*********************************************************************************************
Main:
HSEROUT ["comp1=", dec Comp1Time,9, "comp2=", dec comp2Time,13, 10]
pause 10
goto Main
end
'Comparator1 Interrupt Handler+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comp1_Int:
if T1CON.0= 0 then 'if timer1 is not running then...
TMR1H = 0 'Set the high part of the timer value to 0
TMR1L = 0 'Set the low part of the timer value to 0
T1CON.0= 1 'start timer
else 'therefore if it is running, stop the timer & calculate the number of 'clock' counts between comparator interrupts....
T1CON.0= 0 'stop tmr1
TMR2 = 0 'clear tmr2
T2CON.2= 1 'start tmr2
@ INT_ENABLE CMP2_INT
Comp1Time.Lowbyte = TMR1L 'puts the timer's low byte in Comp1Time's lower 8 bits
Comp1Time.Highbyte = TMR1H 'puts the timer's high byte in Comp1Time's upper 8 bits
endif
@ INT_RETURN
'Comparator2 Interrupt Handler+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comp2_Int:
@ INT_DISABLE CMP2_INT
T2CON.2= 0 'stop timer2
Comp2Time = tmr2
@ INT_RETURN