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?
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.
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)...
ie the C2 count decrements nice & smoothly (& below 336 - yay!) & totally in line with the amount of phase lag....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
(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.
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.
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....
Since then I've assumed digital & therefore deselected the analog!!
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)
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!
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.
Ok, this seems to work (ie it allows a 'main body' of program to run, with an interrupt handler)....
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)...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
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.
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
to (get ready for it...)Code:HSEROUT [" C1=",dec Comp1Time,9," C2=", dec comp2time,9, "phase_shift=", dec phase_shift/10,".",dec phase_shift//10, 13, 10]
Or/and shorten what you are sending....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]
Best Regards,
Paul
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.
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.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 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.
Bookmarks