Measuring audio phase shift through a circuit with a PIC - Page 2


Closed Thread
Page 2 of 2 FirstFirst 12
Results 41 to 50 of 50
  1. #41
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by languer View Post
    So on the picture and data on post#15 things were looking honky-dory (you were measuring at least down to 161 counts on CMP2). Your new posts state that now CMP2 will not go below 336. Basic question; what changed?

    Apologies...I've only just seen your question from a day or so ago - firstly that's very sharp of you to pick up on that detail

    What changed?

    I wish I knew....when it looked hunky dory...I didn't probe to deeply (I guess the - at the time - relief overcame me & I was a bit premature saying all was well!), I sort of put it to one side...a couple of nights later I came back to it & couldn't get the darned count down.

    I've not changed the circuit....and have only window dressed the code (I can't genuinely say what I might have benn window dressed - but it will have been minimal!), but early indications here since getting home is that it might be related to the amount of text I'm squirting out with the HSEROUT command (which I queried myself the other night...and acetronics spotted earlier today!)

    I only had a slim window of opprtunity before domestic commitments kicked in....but when 1000Hz (a nice round number to work with) was fed into comp1 I saw the count drop from 5,000 to something like 4600 when I put an Hserout in amongst the count storing! So is it related to amount of debug text I wonder?

    I'm using Paul's excellent idea of keeping it simple & plagiarising the simple code he kindly provided (less his one typo! ) ...first step is to get a good solid Comp 1 derived timer count for 1000Hz (which @20Mhz should be 5000 - and indeed it is using paul's code )...I'll then augment from there (ie bring comp2 into play)
    Last edited by HankMcSpank; - 29th September 2010 at 19:35.

  2. #42
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default

    Ok, success (of sorts)

    By keeping it simple, this code works (many thanks to Paul, whose code sample I used, albeit in McSpank-esque form here)...

    Code:
    PIR2.5 = 0    'Clear the Comp1 interrupt flag
    Comp1Time = 0
    
    Main_Loop:
            WHILE PIR2.5 = 0       
            GOTO Main_Loop
            WEND
            TMR1H = 0                    
            TMR1L = 0
            PIR2.5 = 0
            Comp1_count:
            WHILE PIR2.5 = 0
            goto Comp1_count
            wend 
            Comp1Time.Highbyte = TMR1H  
            Comp1Time.Lowbyte = TMR1L
            TMR1H = 0                    
            TMR1L = 0
            PIR2.6 = 0
            'HSEROUT [dec Comp1Time,13, 10]  
            Comp2_count:
            WHILE PIR2.6 = 0
            goto Comp2_count
            wend
            Comp2Time.Highbyte = TMR1H  
            Comp2Time.Lowbyte = TMR1L
            TMR1H = 0                    
            TMR1L = 0
            HSEROUT ["C1=",dec Comp1Time,9,"C2=", dec comp2time, 13, 10]
            PIR2.5 = 0
            goto Main_Loop
    ie the C2 count decrements nice & smoothly (& below 336 - yay!) & totally in line with the amount of phase lag....

    (green trace is comp1 - non lagged, yellow trace is into comp2 & lagged a miniscule amout)



    .....I can get all the way down to 13-14(ish) below which the C2 count gets very jittery (ie successive counts eg 5, 11, 6, 12, 5, - you can see some 19s in that stream above)....but a comp2 count of 13 @1kHz is granular enough for me (accuracy to within 0.936 degrees @1kHz). I'm elated...*BUT*

    Quite clearly my original way is causing some issues (p& almost certainly to do with my poor sequence &/or coding), so if this way of doing it works, how can I integrate it into my main program?

    My first attempt just now failed...

    Here's the screen output...

    C1=4909 C2=13
    C1=4903 C2=13
    C1=4909 C2=13
    C1=4909 C2=13
    hello
    C1=4903 C2=13
    C1=4909 C2=13


    ie that C1 count has dropped?!! (even though the incoming frequency has remained at 1Khz)

    here's what I did (disclaimer: I didn't know how to get the main body of program to 'jump' to to the interrupt handler when Comp1 interrupted, so I deferred back to DT's method as the initial 'trigger')...

    Code:
    Comp1Time       var  word    ' used to amalgamate TMR1 High & Low Bytes.
    Comp2Time       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
        endm
        INT_CREATE               ; Creates the interrupt processor
    ENDASM
    
    T1CON.0= 1  'start timer
    
    Comp1Time = 0 'clear down Comp1Time, prior to starting.
    comp2Time = 0  'clear down Comp2Time, prior to starting
    
    @ INT_ENABLE  CMP1_INT     ; enable Comparator 1 interrupts
    PIR2.5 = 0    'Clear the Comp1 interrupt flag
    Comp1Time = 0
    Comp2Time = 0
    
    'Main body of Code****************************************************************
    
    Main:
    hserout ["hello", 13, 10]
    pause 20
    goto Main
    
    END
    
    '**********************Comp1 interrupt handler*********************************************************
    Comp1_Int:
    Comp1_Loop:
            WHILE PIR2.5 = 0       
            GOTO Comp1_Loop
            WEND
            TMR1H = 0                    
            TMR1L = 0
            PIR2.5 = 0
            Comp1_count:
            WHILE PIR2.5 = 0
            goto Comp1_count
            wend 
            Comp1Time.Highbyte = TMR1H  
            Comp1Time.Lowbyte = TMR1L
            TMR1H = 0                    
            TMR1L = 0
            PIR2.6 = 0
            'HSEROUT [dec Comp1Time,13, 10]  
            Comp2_count:
            WHILE PIR2.6 = 0
            goto Comp2_count
            wend
            Comp2Time.Highbyte = TMR1H  
            Comp2Time.Lowbyte = TMR1L
            TMR1H = 0                    
            TMR1L = 0
            HSEROUT ["C1=",dec Comp1Time,9,"C2=", dec comp2time, 13, 10]
            PIR2.5 = 0
            
    @ INT_RETURN
    Last edited by HankMcSpank; - 29th September 2010 at 22:25.

  3. #43
    Join Date
    Jul 2003
    Location
    USA - Arizona
    Posts
    156


    Did you find this post helpful? Yes | No

    Default

    This is most excellent.

    You may have already corrected this, but on the original code the analog inputs for the comparators are not enabled (ANSEL.6 and ANSEL.7). Minor thing, but shouldn't hurt to follow the datasheet.

    I do agree with other suggestions, since the inputs are already digital there is not need to use the comparators. But to use the IOC (interrupt-on-change) you would most likely need to go for PORTA or PORTB (which have individual IOC bits for each input).

    General suggestion for interrupt use: keep everything short; do only the absolute minimum inside the interrupt routine.

    Even though the use of the HW USART (HSEROUT) is a plus, you should still try to do this outside the interrupt routine. Do the timer stuff inside the interrupt (i.e. clear and set timer, etc). Make a flag that tells you the interrupt "fired"; and in the main loop manipulate the data to be sent out (and send it out). I think the CCP module maybe a much better candidate for what you are doing (duh, except you would need a PIC with two CCP modules - never mind).
    Last edited by languer; - 29th September 2010 at 22:15.

  4. #44
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by languer View Post
    You may have already corrected this, but on the original code the analog inputs for the comparators are not enabled (ANSEL.6 and ANSEL.7). Minor thing, but shouldn't hurt to follow the datasheet.
    I had thought the ANSEL turned on/off the AtoD for a given pin - certainly my comparators have been working with the corresponding ANSEL deselected? I had a similar discussion with Melanie & she considered them digital....

    http://www.picbasic.co.uk/forum/show...1127#post81127 extract here....

    Quote Originally Posted by Melanie View Post
    Whether you consider a Comparator OUTPUT as analog I suppose is up to you. I consider Comparators INPUT as ANALOG but technically their OUTPUT is DIGITAL since it can only be a High or a Low. RC4 is the OUTPUT for Comparator 2. If you are using Comparator 2, you DON'T want to set that pin to ANALOG (because ANALOG refers really only to INPUTS), but you want DIGITAL OUTPUT.
    Since then I've assumed digital & therefore deselected the analog!!


    Quote Originally Posted by languer View Post
    I do agree with other suggestions, since the inputs are already digital there is not need to use the comparators. But to use the IOC (interrupt-on-change) you would most likely need to go for PORTA or PORTB (which have individual IOC bits for each input).
    I already use IOC (for switching) in the program that this melarkey is destined for - in my blissfully naive planet of "don't understand", for now, I'd prefer to keep the two interrupt variants apart! (for fear of IOC contention)

    Quote Originally Posted by languer View Post
    General suggestion for interrupt use: keep everything short; do only the absolute minimum inside the interrupt routine.
    I would agree with that, but what I've found is that unless I do stuff inside the routine, then the counts go to pot! (that's not to say I shouldn't strive to do such stuff outside the routine, but as of yet, I'm having the most success keeping it 'controlled' where I know where/when it's going to be used!

    Quote Originally Posted by languer View Post
    Even though the use of the HW USART (HSEROUT) is a plus, you should still try to do this outside the interrupt routine. Do the timer stuff inside the interrupt (i.e. clear and set timer, etc). Make a flag that tells you the interrupt "fired"; and in the main loop manipulate the data to be sent out (and send it out). I think the CCP module maybe a much better candidate for what you are doing.
    I'd love to get that HSEROUT outside....but I think therein lies the possible original problem?

    It would be nice to slowly build the picture up to see when the trouble occurs, but to do that I need some clever person to tell me how I can 'trigger' the code that 'works' above into action while the main program is running?
    Last edited by HankMcSpank; - 29th September 2010 at 22:31.

  5. #45
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default

    Ok, this seems to work (ie it allows a 'main body' of program to run, with an interrupt handler)....

    Code:
    Comp1Time       var  word    
    Comp2Time       var  word
    phase_shift     var  word
    c               var  word
    dummy           var word
    
    
    T1CON.0= 1  'start timer
    
    Comp1Time = 0 'clear down Comp1Time, prior to starting.
    comp2Time = 0  'clear down Comp2Time, prior to starting
    
    PIR2.5 = 0    'Clear the Comp1 interrupt flag
    
    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
        endm
        INT_CREATE               ; Creates the interrupt processor
    ENDASM
    
    T1CON.0= 1  'start timer
    
    Comp1Time = 0 'clear down Comp1Time, prior to starting.
    comp2Time = 0  'clear down Comp2Time, prior to starting
    
    @ INT_ENABLE  CMP1_INT     ; enable Comparator 1 interrupts
    
    Top:
            c = 3600
            dummy = comp2time * c  
            phase_shift  = DIV32 comp1time
            HSEROUT ["  C1=",dec Comp1Time,9,"  C2=", dec comp2time,9, "phase_shift=", dec phase_shift/10,".",dec phase_shift//10, 13, 10]
            goto top
    
    Comp1_Int:
            PIR2.5 = 0
        Loop1:
            WHILE PIR2.5 = 0       
            GOTO Loop1
            WEND
            TMR1H = 0                    
            TMR1L = 0
            PIR2.5 = 0
            
            Comp1_count:
            WHILE PIR2.5 = 0
            goto Comp1_count
            wend 
            Comp1Time.Highbyte = TMR1H  
            Comp1Time.Lowbyte = TMR1L+2
            TMR1H = 0                    
            TMR1L = 0
            PIR2.6 = 0
            'HSEROUT [dec Comp1Time,13, 10]
                
            Comp2_count:
            WHILE PIR2.6 = 0
            goto Comp2_count
            wend
            Comp2Time.Highbyte = TMR1H  
            Comp2Time.Lowbyte = TMR1L+6
            TMR1H = 0                    
            TMR1L = 0
            if comp2time> comp1time-23 then comp2time = 0
            'HSEROUT ["C1=",dec Comp1Time,9,"C2=", dec comp2time, 13, 10]
            PIR2.5 = 0
    @ INT_RETURN
    The actual final phase calculation jitters about a bit (but I suspect that down to the somewhat jittery quality of my audio input signal into the PIC comparators)...



    Now I'm sure there are more efficient ways of doing the above - but for now, it work s& I'm chuffed!

    The actual final phase calculation jitters about a bit (but I suspect that down to the somewhat jittery quality of my audio input signal into the PIC comparators!)...




    Listen guys - a great collaborative effort there - I can't thank you all enough....hopefully this gives a bit of closure to a long & painful saga!
    Last edited by HankMcSpank; - 30th September 2010 at 00:25.

  6. #46
    Join Date
    Feb 2010
    Location
    USA, New England
    Posts
    164


    Did you find this post helpful? Yes | No

    Default

    Hi Hank,

    One more suggestion...

    It takes a long time (relatively speaking) to send out your serial string. In PBP Ints, I'm pretty sure the interrupt is not responded to until the HSEROUT line is finished. So if code space isn't a particular issue at this time, try changing
    Code:
    HSEROUT ["  C1=",dec Comp1Time,9,"  C2=", dec comp2time,9, "phase_shift=", dec phase_shift/10,".",dec phase_shift//10, 13, 10]
    to (get ready for it...)
    Code:
    HSEROUT [" "]
    HSEROUT ["C"]
    HSEROUT ["1"]
    HSEROUT ["="]
    HSEROUT [dec Comp1Time]
    HSEROUT [9]
    HSEROUT [" "]
    HSEROUT ["C"]
    HSEROUT ["2"]
    HSEROUT ["="]
    HSEROUT [dec comp2time]
    HSEROUT [9]
    HSEROUT ["p"]
    HSEROUT ["h"]
    HSEROUT ["a"]
    HSEROUT ["s"]
    HSEROUT ["e"]
    HSEROUT ["_'}
    HSEROUT ["s"]
    HSEROUT ["h"]
    HSEROUT ["i"]
    HSEROUT ["f"]
    HSEROUT ["t"]
    HSEROUT ["="]
    HSEROUT ["dec phase_shift/10]
    HSEROUT ["."]
    HSEROUT [dec phase_shift//10]
    HSEROUT [13]
    HSEROUT [10]
    Or/and shorten what you are sending....

    Best Regards,
    Paul

  7. #47
    Join Date
    Jul 2003
    Location
    USA - Arizona
    Posts
    156


    Did you find this post helpful? Yes | No

    Default

    This is an excellent work, and very easy to follow and read through. You should consider placing this in the Wiki or Project section.

    In a sort of backwards way, I had one of those aha moments out of this thread.

    I had thought the ANSEL turned on/off the AtoD for a given pin - certainly my comparators have been working with the corresponding ANSEL deselected? I had a similar discussion with Melanie & she considered them digital....
    This is absolutely true for the outputs (i.e. comparator output) as they will be either high or low. This is, however, not true for the inputs (i.e. comparator input) as your are using their analog nature to compare (in your case) against a reference (this is also alluded to on the post you mention);which is what I was referring to (ANSEL.6 and ANSEL.7). In summary, comparator outputs are digital, comparator inputs are analog.

    This is what was nagging me; something does not look correct, yet it behaves correctly (maybe). Then came the aha moment. You run the analog signal through the schmidt triggers effectively converting it from analog to digital. Then you feed the signal into the comparator. So why do you even need a comparator? You really don't, BUT, for your system you really need some sort of comparator (not an analog one, a digital one so you can trigger on its change of state). And, perhaps unbeknownst to you, that's what you created. By letting the comparator input pins be digital, you created a digital comparator (sort of like a logic gate) - very cool.

    With that said, you probably could save the schmidt triggers and run the analog waveforms straight to the comparator (they would have to be conditioned / buffered before hitting the comparator). But you have the concept working, so I would not change it now.

    Again, very nice job.

  8. #48
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by languer View Post
    This is an excellent work, and very easy to follow and read through.

    With that said, you probably could save the schmidt triggers and run the analog waveforms straight to the comparator (they would have to be conditioned / buffered before hitting the comparator). But you have the concept working, so I would not change it now.

    Again, very nice job.
    Thanks...& as it goes I'm pleased how the contributions rolled in - all had value...( and also gave me a 'second wind' so to speak) .

    In the end I do take the analogue sine waves, square them up by amplifiyng it a *lot* (my circuit will have a couple of unused opamp stages, so I figured it would save component space by using those vs Schmitts) ...then push it into the PIC comparators (so no schmitts were harmed in the making of this thread anymore).

    It works, but I'm not sure how robust the resulting comparator triggering will be under certain circumstances - early on in the thread there were defintiely some severe phase outcome errors when the analog signals into the comparators were not of the same magnitude ...obvious in retrospect, but when you're getting wrapped up with all manner of new learning experiences blah blah (I now need to spend a bit more quality time, trying different permutations)

    My last workin g code I posted (late last night)....it all works, biut I'm sure seasoned programmers wince at the way I'm using DT's stuff - not sure one little bit if that's an acceptable practise. For example, where I setup the interrupts....

    Code:
    ASM
    INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag?
            INT_Handler   CMP1_INT,  _Comp1_Int,   PBP,  yes
        endm
        INT_CREATE               ; Creates the interrupt processor
    ENDASM
    the last two columns...are they right? (Hank makes a mental note -hmm, really must get around to learning programming properly, rather than winging/kludging/pleading whenever a need arrives ...and that includes interrupts!)

    Being an onld electronics type, I too initially related a PIC's comparator inputs to being analog devices...and to tell you the truth I'm still not sure if from a PIC perspective, whether its comparator inputs are analog or digital...I just roll with what works...and deselecting ANSEL for the pins involved works! (perhaps someone can chime in what the true definition of ANSEL funtion is - ie is it purely related to the AtoD functionality or does it mean 'analogue' in general?)


    PS tks Paul for the stuff about HSerout - & whilst that 'tip' is somewhat ugly on the eye, it all makes complete sense!
    Last edited by HankMcSpank; - 30th September 2010 at 19:17.

  9. #49
    Join Date
    Jul 2003
    Location
    USA - Arizona
    Posts
    156


    Did you find this post helpful? Yes | No

    Default ANSEL controls analog/digital state of input, not to what function is routed to

    perhaps someone can chime in what the true definition of ANSEL funtion is - ie is it purely related to the AtoD functionality or does it mean 'analogue' in general?
    I thought I answered this in the previous post. In any case, ANSEL controls whether the respective PIC inputs are set to analog or digital. It does not care about the ADC. Other registers allow you to decide whether the respective analog input is used for the ADC or the Comparator, or ...

    In your case you lucked out because even though you did not set the inputs to analog, you had already squared up the inputs to make them sort of digital.

  10. #50
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by languer View Post
    I thought I answered this in the previous post. .
    Apologies, I'd picked up (misread), that there was still a degree of uncertainty!

    Quote Originally Posted by languer View Post
    In your case you lucked out because even though you did not set the inputs to analog, you had already squared up the inputs to make them sort of digital.
    That sums it up nicely - got it! (that said, what you're saying would suggest, it wouldn't be the comparator' Internal VREF deciding the 'flip/trigger point', but the PIC's internal high low digital detection circuitry? (ie when is a '1' a 1' and when is it a '0')

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