Instant Interrupts for rotary encoder
I want to use Darrel Taylor's interrupts for an application with 16F677 and PBP V2.47 to read steps with a
mechanical encoder with detent -Bourns ECW1JB24-B00024. I only have RA0 and RA3 available for reading outputs A and
B and I could use MC14490 for cleaning/debouncing A, B mechanical outputs if really necessary. I pretend to use
basic Ioannis idea seen at message -New approach to Rotary Encoder- I need to say I am a newcomer to assembler
language. My idea is to set 2 different interrupts: A associated with port RA0 and B with port RA3 to simplify
encoder reading. The basic idea is while one interrupt is on the other is disabled
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler RAC_INT, _ENCODERA, PBP, yes
INT_Handler RAC_INT, _ENCODERB, PBP, yes
INT_CREATE ; Creates the interrupt processor
ENDASM
@ INT_ENABLE RAC_INT ; enable external RA interrupts
OPTION_REG.6=0 ;Int on falling edge. Is it possible?
IOCA.0=1 ;Enable INT A0
IOCA.3=1 ;Enable INT A3
'---[INT - interrupt handlers]---------------------------------------------------
ENCODERA:
IOCA.3=0 ;Disable INT A3
Pause 1 ;Avoid RA0 reading during bouncing
If PORTA.0=0 then
Counter=Counter+1
lcdout $fe,$c0,#Counter
Endif
while PORTA.0=0 or PORTA.3=0:Pause 1:wend ' while RA=0 standby + debounce time
IOCA.3=1 ;Enable INT A3
@ INT_ENABLE RAC_INT ; enable interrupts Is it necessary?
@ INT_RETURN
ENCODERB:
IOCA.0=0 ;Disable INT A0
Pause 1 ;Avoid RA3 reading during bouncing
If PORTA.3=0 then
Counter=Counter-1
lcdout $fe,$c0,#Counter
Endif
while PORTA.0=0 or PORTA.3=0:pause 1:wend ' while RA=0 standby + debounce time
IOCA.0=1 ;Enable INT A0
@ INT_ENABLE RAC_INT ; enable interrupts Is it necessary?
@ INT_RETURN
'-------------------------------------------------------
'Main program
'-------------------------------------------------------
-Is it OK to set interrupts the way I do, outside assembler block and after @INT_ENABLE RAC_INT sentence?
-Is it possible to disable for example INT A3 while inside INT A0 with IOCA register?
-Is the sentence @ INT_ENABLE RAC_INT OK for enable both interrupts? or IOCA register can do the same?
-Francesc
Re: Instant Interrupts for rotary encoder
Quote:
OPTION_REG.6=0 ;Int on falling edge. Is it possible?
no this option is for INT/int
having
Quote:
INT_Handler RAC_INT, _ENCODERA, PBP, yes
INT_Handler RAC_INT, _ENCODERB, PBP, yes
won't really work as there is only one rac_int ,you only need one isr for it
your isr needs to
1 determine state of enca and encb
2 compare this state to the previous (old_state)
3 determine if the move is forward ,backwards or invalid (bounce) and inc or dec the counter as req
4 save the current state to "old_state"
5 clear the rac interrupt flag (the auto flag clear does not always work for rac int)
having pauses and lcd outputs in isr will lead to tears , make isr's as short as possible is best practice
after thought
add capacitors to ground across the enca/b pins (try 0.1 uf) to minimise contact bounce
Re: Instant Interrupts for rotary encoder
As Richard says, you only need one interrupt. On interupt edge, read the inputB from the encoder . If it's hi then being turned c/w, if lo then being turned ac/w ( or the other way round) Suck it and see.
Also good advice from Richard re caps on both inputs to ground.
You can almost discount switch bounce, int will ignore following spikes and inputB switch will have settled. Only problem is if interupt input is still bouncing after you reenable ints. I added a test for no change on inputB.
George
Re: Instant Interrupts for rotary encoder
Quote:
Originally Posted by
towlerg
...You can almost discount switch bounce, int will ignore following spikes and inputB switch will have settled. Only problem is if interupt input is still bouncing after you reenable ints. I added a test for no change on inputB.
George
At 64MHz I couldn't ignore the jitter. I don't remember what cap configuration I used, but it took me quite a while through trial and error to come up with an acceptable transition (regret not having documented work on that project - of course it got put on the shelf and I moved on to something else and undid all my prototyping boards).
Robert
Re: Instant Interrupts for rotary encoder
I saw this article on "re" decoding. http://letsmakerobots.com/node/24031
and gave it a spin on a 16f684 @8mhz , the full quadrature decoding works perfectly and contact bounce has been eliminated on my cheap and nasty 10 for a dollar ebay specials. these had previously defied efforts to eliminate occasional miscounting and direction reversals.
Re: Instant Interrupts for rotary encoder
That interesting but I repeat, int on A, on interupt read B, if it is c/w if 1 it is ac/w it is 0 (or the other way round). Caps on A and B to gnd, 10k pullup on A and B to Vcc. Bobs your uncle.
Any contact bounce on A will be disrequarded because your interupt routine won't have reenabled ints yet and B will be read dead in the middle of its cycle.
George
Re: Instant Interrupts for rotary encoder
I hadn't thought of disabling interrupts momentarily, excellent idea. A short timer could control the interval as well.
My PIC was dedicated so I just looped and checked the state of the pins.
Robert
Re: Instant Interrupts for rotary encoder
Hi guys,
Quote:
That interesting but I repeat, int on A, on interupt read B, if it is c/w if 1 it is ac/w it is 0 (or the other way round).
I may be stating the obvious but if you trip the interrupt off of the rising edge of one channel you're effectively dividing the resolution of the encoder by 4. To get the full resolution you need to count all edges of the quadrature cycle.
There are two types of encoders with detents typically used as front-panel controls. One have a full quadrature cycle per detent and using the "interrupt on rising edge of one channel" method can work with these but what you think might be noise on the signal could (and probably is) the second rising edge on the A-signal within the same quadrature cycle. The divide by 4 "issue" doesn't really apply here because you basically can't position the encoder between two detents. Another possible issue though is that when the encoder "clicks" from one detent to another a full quadrature cycle is output. If the interrupt latency is "highish" the firmware might not actually "catch" channel B quick enough. Catching it at the wrong time results in it counting the wrong way.
The other type of encoder have one detent per quadrature state. Using the "interrupt on rising edge of one channel" method with this type will result in the software detecting every 4th click, skipping the other 3.
/Henrik.