Bounce-busting Bullet Proof Rotary Encoder Code
No pullups and no capacitors!
Initial post by Peter Mather and further refinement by @apalert on TBS.
My bounce-busting bullet proof Rotary Encoder code
One thing I learned while testing is that it's very easy to exceed the speed these rotary encoders can cope with which causes missed pulses.
The data sheet for my encoder gives maximum rotary speed of 100 rpm. It has 20 indents per full turn so that calculates down to 33 clicks per second, a bit over 1 1/2 turns, 30mS per click. You can easily exceed that in short bursts. I setup a timing loop and with a finger twirl on the knob for 1/4 turn some pulses were as low as 6mS apart, 5 times the maximum speed recommended. Little wonder it missed a few pulses!
One tweak was to grab the direction data on the first clock pin interrupt but not finalize it until the data pin interrupt. This means the user can overshoot 49% of the way to the next indent and back off without a miscount.
Anyway, in case there is interest I'll attach the code:
'Code for rotary encoder interpretation by Malcolm Young
'Rotating the encoder prints incremental numbers as appropriate
' eg 0 1 2 3 4 3 2 1 0 -1 -2 etc as well as a direction flag
'in the form of 1 and -1. Developed on Picomite
OPTION ExPLICIT
OPTION DEFAULT NONE
dim float pre_action = 0 'temporarily holds data from new encoder movement
dim float dir_action = 0 'makes "public" the new directional data
dim float inc_action = 0 'makes "public" the new incremental data
dim float old_inc_action = 1 'used to decide if data has changed
dim float clock_enable = 1 'flag to control clock pin interrupt process
dim float reset_enable = 0 'flag to control data pin interrupt process
dim float clk = 20 'use to name clock pin
dim float dat = 19 'use to name data pin
setpin clk, intl , clock_interrupt,pullup 'clock pin (encoder pin a)
setpin dat, intb, reset_clock_enable,pullup 'data pin (encoder pin b)
print
print "inc_action", "dir_action"
do
If inc_action <> old_inc_action then
print inc_action,, dir_action
'cls: text 96,60, str$(inc_action),RB,6 'LCD panel output
old_inc_action = inc_action
end if
loop
sub clock_interrupt
if clock_enable = 1 then
clock_enable=0 'prevents any further "noise" pulses being processed
if pin(dat) = 1 then 'direction was clockwise
pre_action = 1
else 'direction was counter-clockwise
pre_action = -1
endif
reset_enable=1 'makes reset_clock_enable ready to accept data
endif
end sub
sub reset_clock_enable
if reset_enable = 1 then
reset_enable = 0 'prevents any further "noise" pulses being processed
if pin(clk) = 0 then 'prevents processing if RE position reverted to origin
dir_action = pre_action 'directional output
inc_action=inc_action + pre_action 'incremental output
endif
clock_enable = 1 'enables data pin again, even if reverted to origin
endif
end sub
