Measuring audio phase shift through a circuit with a PIC


Closed Thread
Results 1 to 40 of 50

Hybrid View

  1. #1
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default

    Many thanks...I'll study your post in detail tonight (after I've got the kids off to bed!)

    I wasn't expecting anyone to analyse my code - I only offered it up in case someone wants to get an overall vibe for my approach. Equally, I wouldn't want anyone to write it for me (else I'll never learn) - I seek exactly what you've brought to the table....ideas wrt general approach from those that have trodden similar paths! (the detail, I'll try & work out myself!)

    thanks once again.

  2. #2
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default

    Hi Jerson,

    Ok, had a bit of time to try & get my head around your method. I'd like to break each of you sentences down a little....

    A 16 bit timer is free running all the time. No start/stop sequences. Comparator interrupts too are always enabled. No need to start/stop them.
    I'm struggling with why you're letting them free run?

    The comparators first - they're gonna be generating a crazy amount of interrupts (to my simple brain, I actually wonder how the code will have time to do anythig else?! lol). Imagine a 1.4khz signal at the comparator pin - that's gonna be an interrupt every 700 us, but wait, there's the other signal presented at the other comparator pin (ie the one I want to measure the phase lag of) & it's generating interrupts too - so that's two interrupts arriving every 700us?!! (potentially the comparator might need to handle much higher frequencies...as high as 5Khz ....my mind boggles at the interrupt rate).The more I ponder this one (I'm into my 3rd night on this & nowhere near a result!), I do woder if there should be some other hardware I shopuld bring into play - to front end some of the work (I was looking at parrallax propellors - http://www.parallax.com/Portals/0/Im...lerBlock-L.jpg .....something like that architecture lends it self more to what I'm trying to do here?!)

    Now I'm inexperienced & that might not tax the PIC one iota, but bearing in mind my program already uses other interrupts (Interrupt on Change, INT_PIN etc), and it's to my mind my program is getting a bit interrupt busy!

    Ok, next (wrt allowing the timer to roll over) - I just can't get this clear in my head...

    Remember Timer always counts up and rolls over, so CurrTimer nearly always is > PrevTimer. On rollover, the result of CurrTimer-PrevTimer is still valid since the bits are limited to a word size. So, 1000-500 is still same as 465-65500 (+ 1) when you do the 16 bit subtract.
    I'm sure this is becuase I've not grasped the intracacies!

    If you reference my schematic above, once again - I'm measuring two signals for phase lag - what happens if if the first signal comes in before the timer rolls over, but by the time the lagged signal come in, the timer has rolled over?

    How does the maths work out for that scenario?

    Ok, to your code ideas for me to using...

    On comp1 interrupt
    FreqCount = CurrTimer - PrevTimer ' timer ticks between 2 edges of the same input give time proportional to the frequency
    Bearing in mind the source signal is a guitar - the frequency is forever moving (with periods where it's static), so I can't grasp how a moving target so to speak will work with that code approach?

    PrevTimer = CurrTimer ' This is the new reference for phase measurement
    This is about the one line I can grasp (!) - ie we need to put a stake in the ground to start timing until the second (phase lagged) signal arrives.

    On comp2 interrupt
    PhaseCount = CurrTimer - PrevTimer ' gives the time between non shifted and shifted waves
    Again, what if the phase has moved (becuase the incoming frequency changed) - couldn't you have a situation where the current Timer hasn't rolled over, but the previous timer (with the stored value) did?

    BTW - I really do appreciate you taking the time to explain to a dunderbrain like me!
    Last edited by HankMcSpank; - 12th September 2010 at 01:25.

  3. #3
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    967


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by HankMcSpank View Post
    Hi Jerson,
    I'm struggling with why you're letting them free run?
    Look at it a bit like you look at a stopwatch. I use the timer as a lap counter. I could choose to start / stop the timer, but it might increase the time spent in the interrupt a bit.

    The comparators first - they're gonna be generating a crazy amount of interrupts (to my simple brain, I actually wonder how the code will have time to do anythig else?! lol). Imagine a 1.4khz signal at the comparator pin - that's gonna be an interrupt every 700 us, but wait, there's the other signal presented at the other comparator pin (ie the one I want to measure the phase lag of) & it's generating interrupts too - so that's two interrupts arriving every 700us?!! (potentially the comparator might need to handle much higher frequencies...as high as 5Khz ....my mind boggles at the interrupt rate).
    Yes, you are right about the interrupts hogging all the time your processor has. But, you could always run the processor at say 20Mhz, makes it 5 times as fast than the default 4MHz. 5 times more that can be done. I've used this technique at 50Hz to check phase lag on mains signals.

    If you reference my schematic above, once again - I'm measuring two signals for phase lag - what happens if if the first signal comes in before the timer rolls over, but by the time the lagged signal come in, the timer has rolled over?

    How does the maths work out for that scenario?
    Ok, in the case of rollover, let us assume the first reading was 65500. Assume a phase shift of 500 counts. The new value is 66000. After rounding to 16 bits, you get 464 (66000-65536). So, current reading 464 - previous reading 65500 will give you your phase counts as 464-65500 = 01F4 in 16 bits (use the F5/F6 buttons on calc to see the Hex/Dec values). So, for an error of 1 count, you still get the same phase diff.

    Bearing in mind the source signal is a guitar - the frequency is forever moving (with periods where it's static), so I can't grasp how a moving target so to speak will work with that code approach?
    A phase diff measurement is just that. How you process it after you've found it out is up to you. I can suggest you put the phase count readings through a low pass filter to smooth out the variations.

    This is about the one line I can grasp (!) - ie we need to put a stake in the ground to start timing until the second (phase lagged) signal arrives.
    Precisely. That is what I am doing when I keep track of the last zero crossing of the first input. Comp1 interrupt. That is your pole in the ground.

    Again, what if the phase has moved (becuase the incoming frequency changed) - couldn't you have a situation where the current Timer hasn't rolled over, but the previous timer (with the stored value) did?
    It is possible in the real world scenario. For this, you can use an overflow mechanism to weed out this case. Any number bigger than expected range indicates the signal has died out.

    BTW - I really do appreciate you taking the time to explain to a dunderbrain like me!
    I am glad to help out as I was once in your shoes

  4. #4
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by Jerson View Post
    Ok, in the case of rollover, let us assume the first reading was 65500. Assume a phase shift of 500 counts. The new value is 66000. After rounding to 16 bits, you get 464 (66000-65536). So, current reading 464 - previous reading 65500 will give you your phase counts as 464-65500 = 01F4 in 16 bits (use the F5/F6 buttons on calc to see the Hex/Dec values). So, for an error of 1 count, you still get the same phase diff.
    But how do you know the timer has rolled over or not? (ie using you analagy how are you counting laps & intra laps)

    For example, the frequency might change & therefore you get a a first reading count of 460 (vs 65500 in your example). So how do you know if a reading of 464 relates to the frequency changing massively, or is a result of the timer rolling over? (surely you have to track overflows too? I tried this, but the PIC baulked when I programmed it with my code! Too many interrupts arriving close together possibly?)

  5. #5
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    967


    Did you find this post helpful? Yes | No

    Default

    Yes, you need to track overflows in your code - too low frequency. Of course, the same may not be true for the phase. Tracking the overflow needs to be done. I did not have to use such a thing since my frequency in was fixed at 50Hz. However, I can propose, you could use the timer start/stop method and track the timer overflow to indicate a very low frequency or too large values of time coming in.

    Possible implementation
    Comp1 int
    if T1 has overflowed, you have yourself an error condition here. Freq Too Low
    FreqCounts = T1
    T1 = 0

    Comp2 int
    PhaseCounts = T1

    Again, the 'stick in the mud' is T1 being set to 0. But, here, you get your freqcounts and phasecounts directly.!!!

    The time from one zero crossing (T1=0) to the next zero crossing on the same Comparator is the frequency counts. Read this, check for overflow and Set T1 = 0.

    The time from the zero crossing of Comp1 to the zero crossing of Comp2 is the phase counts.

    Oh, and you need to run your PIC at 20MHz just so you have more time in your ISRs. A helpful suggestion would be to write your ISR in ASM no matter how difficult it seems; PBP adds overhead to the code you write and its better to exit the ISR as quickly as you can to let other blocks of code to run.
    Last edited by Jerson; - 13th September 2010 at 01:58.

  6. #6
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default

    Thanks Jerson....I'll study that later (it's 2.15am here in Lodnon!)

    Actually, this looks like it might have some signs of doing what I want...

    Code:
    'Comparator1 Interrupt handler+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++        
    Comp1_Int:
    @ INT_DISABLE  CMP1_INT
            Comp1Time.Lowbyte = TMR1L 'puts the timer's low byte in MyTime's lower 8 bits 
            Comp1Time.Highbyte = TMR1H 'puts the timer's high byte in MyTime's upper 8 bits
            TMR1H = 0 'Set the high part of the timer value to 0
            TMR1L = 0 'Set the low part of the timer value to 0
    @ INT_ENABLE  CMP2_INT
            'Comp1Time =Comp1Time +4 
            'dummy = b * c       '5,000,000 
            'frequency = div32 Comp1time
            'frequency =frequency/2
            'HSEROUT ["mytime = ", dec mytime,9, dec frequency/10,".",dec frequency//10,"Hz",13, 10]
              
    @ INT_RETURN
    
    'Comparator2 Interrupt handler+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    Comp2_Int:
    @ INT_DISABLE  CMP2_INT
            Comp2Time.Lowbyte = TMR1L 'puts the timer's low byte in MyTime's lower 8 bits 
            Comp2Time.Highbyte = TMR1H 'puts the timer's high byte in MyTime's upper 8 bits
            TMR1H = 0 'Set the high part of the timer value to 0
            TMR1L = 0 'Set the low part of the timer value to 0  
    @ INT_ENABLE  CMP1_INT   
    @ INT_RETURN
    What's getting me bogged down is something as simple as setting my config correct for a 20Mhz external resonator. (the first time I've used an external clock)

    I'm putting a 1Khz test signal into comparator1 input pin- the handler it's registering 2500 timer1 'counts' between successive compartor1 interrupts - that doesn't seem correct for a 20Mhz external clock?

    at 1Khz, the actual physical time between interrupts should be 1ms - & I'm seeiing a count of 2500 for comparator 1 interrupts.....

    therefore 1ms divided by 2500 is 0.0000004 seconds ....or in frequency is 2500000Hz (2.5Mhz - that's not 20Mhz???).

    here's my settings...

    Code:
    @ __CONFIG _FCMEN_OFF & _HS_OSC & _WDT_OFF & _MCLRE_OFF & _CP_OFF & _IESO_OFF & _BOR_OFF & _PWRTE_OFF
    
    DEFINE OSC 20        ' set Oscillator at 20Mhz.
    OSCCON.0 = 0
    what am I setting wrong? (I'm using MPASM assembler)

  7. #7
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    967


    Did you find this post helpful? Yes | No

    Default

    Hi Hank

    Is it possible you got your T1 prescaler(T1CON) set to 1:8 ? That will explain the counts you see. 20e6 / 8 / 1000 = 2500 counts. You haven't mentioned which pic you use.

    I've never used a resonator on my circuits, but, you could try with HS / XT options. Most likely the XT might work.

    Regards

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts