I looked at the playground example for using an encoder and it seemed like the code did not take into account the fact that it was using pullups (e.g. the logic was reversed) and there was no kind debouncing.
Without debouncing I found that for every turn to a new divet (e.g. one click) I was getting 2-4 values instead of just one.
This was using the code for pinA connected to an interrupt and pinB to a normal input and pinCom to gnd.
The two inputs had pullups active.
To debounce I just delayed new interrupt readings by 200ms. This obviously slows down how quickly I can turn the encoder but it cleaned up a lot.
However, if I advance slowly one lcick at a time, sometimes it jumps back a step instead of forward.
What else can I do to make the encoder more reliable?
I am using a panasonic encoder that is equivalent to the alps one used in the example.
The appnotes show to use caps bewteen A and COM and B and COM.
I assume this should help filter the signal a little bit.
Is software debouncing a bad idea?
Should I be doing something different with how it is connected electrically?
Yes mechanical encoders generate a lot of noise... pull up or pull down doesn't matter.
the way I fixed it is to basically put the 2 bits of the current state of the AB pins and the 2 previous state into a byte then build a table that defines what is the sequence of valid values
i.e. if that byte is now (say) 0x04 the next value can only be (say) 0x02 for one directions etc etc
I was looking at that thread (using the timer interrupts).
Is this a more effective way than what Massimo is suggesting of just properly comparing state changes of the two pins?
What concerns me is calling the ISR so frequently that it bogs down the software on unecessary tasks and could interfere with the more important realtime data processing (e.g. reading sensor inputs and controlling actuators)
1ms is not so frequent for a timer interrupt, only once every 16,000 clock cycles. The interrupt could be made more efficient by using direct access to the pins rather than digitalRead().
Also you might like to read your other sensor inputs, or control your actuators on the same timing schedule (or set a flag to do so in the main loop once the ISR returns). Using counters in the ISR to divide down to a lower frequency before flagging any inputs/outputs for attention in the main loop is also a good way to schedule lower-rate activities.
Edit: Regardless, it is not good practice to use a bouncy switch on an interrupt input.
ok I am using Crimony's code now and it works great!
What I am not so clear on is exactly how FrequencyTimer2 is using pins 3 and 11 since I need those for other connections.
Right now what I do is when the deBounce() function is called by the timer I disable() the timer, run the code that needs pin 11 (e.g. it was the data pin for my shiftregister) and then enable() it again when I am done.
That works well so far but pin 3 is actually where I have my second encoder hooked up and I don't really have any other spare pins.
Is it possible to disable the timer (in enough time) once the deBounce function is called so that I can then read values from pin3 and then reenable it once I am done?
Is this the best strategy for sharing the pins?
FrequencyTimer2 creates a timer (with setPeriod()), and makes available 2 mechanisms for notification of the timer expiration: a) An external output pin (pin 11), and b) An interrupt.
These two mechanisms are controlled independently, a) is controlled by the enable() and disable() calls, and b) is controlled by the setOnOverflow().
If you don't want to use (a), then just don't ever call enable(). The library will leave pin 11 completely alone for your exclusive use.
If you don't want to use (b), then don't ever call setOnOverflow().
In your case to want to use setOnOverflow() but not enable() and disable().
Pin 3 is available for general purpose I/O but because the PWM output which normally is available at pin 3 uses timer2, you can't use PWM output on pin3 when using this library. Go ahead and use pin 3 for your second encoder input, just check both encoder inputs in the ISR.
can someone provide the whole code about encoder reading with the FrequenceyTimer interrupt. i can't get it to work. i do not really understand how to use the frequenceytimer lib and how to combine it with the code from crimony.
thank you very much! not only arduino rocks, but its community! it works great with the ALPS encoder (i do have another, that reacts jumpy but the ALPS works great). i really would like to know more about encoders. also the technique massimo describes sounds very interesting, anyway its not clear to me, without code respectively with my little knowledge.