How do I debounce rotary encoder when using interupts?
I was using a polling techniques and there is info on how to debounce in that setup but using interrupts is more suitable for my current application.
However I want to increment a value on an LCD display by one for each click of the rotary encoder. Using interrupts it jumps ahead several numbers for each click and it is not always consistent.
lemming:
How do I debounce rotary encoder when using interupts?
I was using a polling techniques and there is info on how to debounce in that setup but using interrupts is more suitable for my current application.
However I want to increment a value on an LCD display by one for each click of the rotary encoder. Using interrupts it jumps ahead several numbers for each click and it is not always consistent.
That has been discussed before several times, even in the last day or two. It's problematic debouncing in software when using encoder interrupts as the millis() and micros() functions (which are normally used for timing bounce periods) don't work inside a active ISR as all interrupts are disabled at that time. One can do the debouncing with external hardware components, but that take up room and costs extra.
I fought that battle with those cheap bouncy mechanical encoders for awhile without success until I found some real nice optical encoders on sale from a surplus outfit for $5 each a couple of years ago, great price and they don't bounce, so no debouncing required. 8)
The solution is to maintain state in variables - the interrupt routine just records the event and the timestamp in a buffer (you can call micros() and millis() in an ISR, its just that you should not wait in an ISR)
You need some logic to look at the past history and decide which changes are bounces and which are genuine. Typically you call a change a bounce if it is close in time to the last change. That way the ISR can be fast too...
You could also add a Schmitt trigger chip between Arduino and the encoder....might help. I guess if the bounce goes full scale...maybe not.. but then could you add 1st order filter with a resistor and a cap. You just have to make sure it can respond to the maximum speed you expect to turn the encoder at.
I recall something from the ATMEL datasheet where you can filter the INTerrupt but that probably involves going outside of the Arduino library.
I'm a beginner myself so..... trying to help but I guess you can take my advice with a grain of salt
A schmidt trigger alone will not help, it will just clean up the rise/fall times. Bounces are on the timescale of microseconds to milliseconds. You need some sort of low-pass filtering. For instance a low pass filter followed by a schmidt trigger will do the job. A time constant of 20 to 50ms would be reasonable.
The dirt cheap, bouncy as h… rotary encoder button seems to cause all kinds of issues, but really should not. They use manchester encoding and if decoded properly, bouncing becomes a non issue. A microcontroller can do so effectively and the main trick is to realize that state changes can only follow a predictable sequence as dictated by the manchester code. Some state transitions are valid, some are not and it just happens that contact bounce triggers invalid state transitions (so no wonder why this protocol was chosen).
A good clean implementation that works well can be found in the following link:
I've been trying different capacitors that go from the encoder pin to ground and it definitely has helped some of the debouncing issues, but every now and then I still get some false interrupts. I've set up my code so that when the interrupt occurs, another pin gets set high and then low again immediately.
Here is my o-scope reading that shows the encoder output/interrupt pin on the Arduino on the top and the pin that just goes high and low to signal that the interrupt has occurred beneath it.
Does anyone know why the interrupted would have triggered there? When I zoom in I can see that the voltage does dip from 3.359 to 3.356 volts for less than 10 microseconds (see second graph). I don't think that should be enough to trigger a falling edge interrupt, does anyone have any ideas why this interrupt is triggering?
Looks to me like you're using CHANGE interrupt mode, but then again, can't see your code.
EDIT ... or the voltage dip is worse than the Saleae? sample rate can record. Try viewing just one analog channel and set to the highest sample rate. Might give a different picture. An oscilloscope with higher sample frequency (or analog scope) might be better suited.
Just noticed how old this thread is ... you should start a new thread, ideally with your code, connection diagram and link to your encoder.
BenF:
The dirt cheap, bouncy as h… rotary encoder button seems to cause all kinds of issues, but really should not. They use manchester encoding and if decoded properly, bouncing becomes a non issue. A microcontroller can do so effectively and the main trick is to realize that state changes can only follow a predictable sequence as dictated by the manchester code. Some state transitions are valid, some are not and it just happens that contact bounce triggers invalid state transitions (so no wonder why this protocol was chosen).
A good clean implementation that works well can be found in the following link:
dlloyd:
Looks to me like you're using CHANGE interrupt mode, but then again, can't see your code.
Sorry for the late reply and lack of code. I was using FALLING actually. I ended up fixing the issue by using smaller caps (turns out the recommended circuit on the datasheet is helpful ;)) I should have realized my caps were too big when they were taking so long to recharge just based on that image. I also had issues where the interrupt wouldn't trigger because they hadn't charged up enough.
dlloyd:
EDIT ... or the voltage dip is worse than the Saleae? sample rate can record.
I tried on a real oscilloscope but wasn't able to see anything. I wonder if it triggered because the voltage went just high enough to trigger a logic high and then dip into the undefined region? I've had a hard time finding detailed documentation of how Arduino interrupts really work.
On the image, regarding the middle interrupt in question, the input voltage is in the undefined region (1.5V - 3V). Any ripple on the voltage within this region could trigger a false interrupt. I'm not sure what the hysteresis would be (if any) as it's value is not specified.
Note that the real signal could have spikes and glitches that cannot be seen due to limitations of the equipment and probe.