PDA

View Full Version : Comparator - tracking the high low condition more robustly.



HankMcSpank
- 4th February 2011, 10:09
I've set a PIC Internal comparator up to interrupt when a signal goes below a preset VRef level.

Here's what happens in the interrupt routine...

(in the code below, 'above_threshold' is a variable to monitor whether comparator is above or below the preset Vref threshold)



Comp1_Int:
@ INT_DISABLE CMP1_INT
If above_threshold = 1 then ;
above_threshold = 0
else
above_threshold = 1
endif

@ INT_ENABLE CMP1_INT
@ INT_RETURN


Essentially it's toggling between a 1 or a 0 each time the comparator interrupts. (btw: please excuse the n00b type coding - is there a more elegant way to toggle a variable?)

Have I got the jist of how this should be approached? I'm actually now thinking as I've typed this out, that maybe the comparator only trips/interrupts in one direction?

It seems to be working, but occasionally it gets 180 degrees out of sync ...ie if the signal is above threshold it's variable is a 0 (wrong!) & if below it's a 1 (also wrong!)

How can I make this routine more robust?

HenrikOlsson
- 4th February 2011, 11:18
Hi,
I've never actually used the comparators but I'm looking at its section in the 18F25K22 datasheet and it says that the interrupt flag is set each time the output changes state - in other words you'll get an interrupt on rising and falling edge of comparator output.

However, as far as I can see, you need to read (or write) the CMxCON0 register in the ISR in order to clear the mismatch condition, much like you commonly need to do with the interrupt on change feature. It looks like you're not doing that.

You might want to actually read the output of the comparator in order to know - for sure - if you're over or under you threshold. The comparator output is available as bit6 in the CM1CON0 register (for comparator 1).

One way to "toggle" a bit is Above_Threshold = !Above_Threshold where the exclamation mark means "not".

/Henrik.

HankMcSpank
- 4th February 2011, 12:00
Hi Henrik,

Many thanks for the tips.

I've had a look at the 16f690 datasheet, & you're completely right - it seems that bit 6 of the CM1CON0 register reflects the logic level output of comparator 1.

Therefore I'm thinking something like this will work...



Comp1_Int:
If CM1CON0.6 = 0 then above_threshold = 0
If CM1CON0.6 = 1 then above_threshold = 1

@ INT_RETURN


...that should keep my variable in total sync with the comparator1 output logic level?

HenrikOlsson
- 4th February 2011, 12:23
Or simply Above_Threshold = CM1CON0.6 or you may not even need a "mirror" of the output, instead of using Above_Threshold in your main application simply use CM1CON0.6 directly.

On the other hand, if all the interrupt is really doing is to "copy" the state of the comparator output then there's really no need to use the interrupt at all - simply read the comparator output directly in your code.

If you want you can even create an alias, like:
Above_Threshold VAR CM1CON0.6

Now, when you use Above_Threshold in your program you are actually reading the comparator output.

/Henrik.

HankMcSpank
- 4th February 2011, 13:01
Thanks Henrik.

the reason I'm using an interrupt, is that I eventually want things to kick in as soon as the comparator changes state....so I will now begin expanding the interrupt routine to include other stuff.

cncmachineguy
- 4th February 2011, 14:46
[QUOTE=HankMcSpank;98799]


If above_threshold = 1 then;
above_threshold = 0
else
above_threshold = 1
endif

(btw: please excuse the n00b type coding - is there a more elegant way to toggle a variable?)
QUOTE]

Above code could be this:


above_threshold = above_threshold ^1