Hardware debouncing for rotary encoder - an unusual case - Page 1
Forum section: electronics / projects

author: Peabody
author_rank: Super Contributor
timestamp: March 01, 2018, 11:49:57 pm
content: The DSO150 Shell kit oscilloscope has a rotary encoder that's used to adjust the postition of the display and the trigger level, and set other things. I've been working with a guy at the manufacturer to get the best software for reading the encoder, and I think he has made as much progress as we're going to get. But for a device costing $21, as you can imagine the encoder isn't exactly the highest quality, so even after he tweaked the software I still experience some glitches. It works ok, but only ok. There's no hardware debouncing in the encoder circuit. It is read by polling at 3 ms intervals. We tried numerous intervals, and 3ms worked best.I could replace the encoder in the hope of getting a better one, but the only one I have found that looks like it would physically fit is the Bourns PEC11L, and the datasheet for that isn't encouraging - its bouncing spec (10 ms max) isn't nearly as good as the PEC11R (2 ms max) which I have used before, but I don't think it will fit because of the lipo battery now laying under it.So I thought maybe I could add some hardware debouncing to the circuit. This is all tiny SMD stuff, except the encoder itself, so my options are limited. The encoder has 30 detents per revolution, and 15 pulses per revolution, so at alternating detents the encoder will come to rest with both switches open, or both switches closed.The problem is - the port lines used for the encoder and several push-button switches are shared as the data bus for the display. The relevant part of the schematic is shown in the picture.So the port may be in output mode driving the display, or in input mode for reading the switches, and the 1K resistors appear to provide enough isolation for that to work. So for instance, if the encoder has come to rest at a detent where both switches are closed (grounded), the processor is still able to drive the lines high because of the 1K resistors. But this also means that I can't be hanging .1ufd caps on the lines on the processor side of the resistors because that would mess up data transmission to the display. Now some might say they wouldn't have designed it that way, but I think it's a clever way to get maximum use out of available port pins, if only the encoder worked better.I don't see a good solution for hardware debouncing that I can implement on my copy. I did try hanging caps from the switch pins to ground, but depending on their value they either had little effect, or prevented the encoder from working at all. The position of the 10K pullups is not helpful since the port line is never fully grounded by the switch - it's only 10/11 grounded.As far as I can tell, the main problem is that in addition to some bounce when a switch makes contact and the line goes low, which any encoder would have, there is also some bouncing during the entire time the switch is supposed to be closed. In other words, it looks like it never actually settles as closed while it is still moving. Of course when open it works ok.Well, if anyone sees a solution here, please let me know.

author: BrianHG
author_rank: Super Contributor
timestamp: March 01, 2018, 11:57:57 pm
content: You can try to add a 10-100nf cap to GND on each encoder output. But, you should be able to take care of this in software. Are you sure you glitches aren't because you are missing transitions. If you are stuck, you can use something like a dedicated 8 pin PIC to debounce and decode that encoder & feed your processor a increment/decrement signal.Also, move your 10ks to the encoder side and change the series 1k resistors to 100k to isolate that caps from the data going to your LCD. Also, when not sending a characters to the LCD, keep that data io buss in tristate for as long as possible.If I were to do software debouncing, I would be sampling much faster than 3ms intervals, something like 1ms, especially if I'm on a shared data bus with a mechanical encoder. I would expect 10 consecutive high or lows before I consider the pin high or low. This count would be 5 with 2ms sampling intervals. 3ms with 3 consecutive shots for validity would be on the borderline, though the caps & resistor changes I mentioned should fix that.Any other solution would be 74HC/LS 14 pin logic ICs, resistors and caps and some tuning of the circuit on your part. Your processor will still need to catch the pattern and decode the motion.

author: KL27x
author_rank: Super Contributor
timestamp: March 01, 2018, 11:58:31 pm
content: Not a direct answer to your question. But when I get the time, I'm going to write up a micro firmware to emulate the output of a mechanical encoder electrically and just wire that up to two momentary switches, once for each direction, to trigger each output. The latest failure is my Korad power supply. Try to increase the voltage, and it goes down. (Try to turn the voltage down, and that works fine, of course, lol). Rather than try to fix it through hardware, I'm just going to replace the knob with the buttons. I have other devices with this problem, too, and this would seem to be a universal hack solution.

author: langwadt
author_rank: Super Contributor
timestamp: March 02, 2018, 12:12:11 am
content: Quote from: Peabody on March 01, 2018, 11:49:57 pmhow is the software doing the decoding?always driving the outputs to the same state shortly be fore reading?split the 1K in two and hang a cap in the middle?

author: BrianHG
author_rank: Super Contributor
timestamp: March 02, 2018, 12:19:28 am
content: Quote from: langwadt on March 02, 2018, 12:12:11 amMy solution of making the series caps (r5,r6,r7) 100k instead of 1k, then moving the pull-ups (r23,r24,r25) right to the encoder switches and placing the caps there at the encoder should give a bit of isolation. Though, when making the data-bus tristate, you would need to pause long enough for the series 100k to pass the data before reading the IO pins. As long as the LCD doesn't have pull-up or pull-down resistors in it.

author: MarkF
author_rank: Super Contributor
timestamp: March 02, 2018, 01:02:10 am
content: Have you tried the filter recommended in the Bourns PEC11R specification

author: Peabody
author_rank: Super Contributor
timestamp: March 02, 2018, 02:43:46 am
content: Thanks for the responses. I guess I didn't make it clear. This is not my product. I do not have the source code for the firmware, so can't make changes to that. And the only physical changes I can make would be to tack caps or diodes or whatever to the encoder pins, and perhaps cut existing traces. So my options are limited.@langwadt,> how is the software doing the decoding?> always driving the outputs to the same state shortly be fore reading?I understand they use the state machine look-up table that everybody likes these days. It supposedly distinguishes between valid and invalid (bounce) transitions. I don't like that very much, but I suggested an alternate method that I thought was better, and they compiled a test of that and sent it to me, and it turned out to be much worse. So I think they're going to stick with the look-up table.They do not drive the outputs to the same state before reading, but do wait a few cycles after switching the port to input to let things settle down.@BrianHG,Except for the encoder, this is all in microscopic SMD. I'm just not able to move transistors around or change the circuit materially.@MarkF,> Have you tried the filter recommended in the Bourns PEC11R specification.That places capacitors on the port lines. I'm concerned that would slow down those lines when they are driving the display, which is what they do most of the time. I think any capacitors would have to be placed on the encoder side of the 1K resistors. But I'll take another look at that possibility.

author: DBecker
author_rank: Frequent Contributor
timestamp: March 02, 2018, 03:23:37 am
content: It's very likely that this is a firmware issue that can't be fixed with hardware debounce. I haven't looked at the DSO150 firmware, but I looked at the DSO138 firmware pretty closely. It's not bad, but there are plenty of flat-out bugs, especially with the button handling code.Supporting this is that Gray Code rotary encoders reduce the need for debounce. Up-down-up should count the same as a single up transition. It should only affect velocity sensitive logic (e.g. incrementing by 10 when the control is spun quickly), and even there it's pretty easy to implement logic to only observe the sum of transitions.

author: Peabody
author_rank: Super Contributor
timestamp: March 02, 2018, 04:22:47 am
content: They posted an early version of the DSO150 source code on Github, but we are several versions down the road from that, and in particular the encoder and button polling has been rewritten and given its own timer interrupt. We just don't know what that looks like now.My understanding is that a quadrature rotary encoder produces Gray code. Only one bit changes at a time. In any case, there would be no problem if while one switch is changing state and bouncing, the other switch is settled and not bouncing, so that the switches are never bouncing at the same time. But the encoder I have appears not to follow that pattern. It appears to continue to bounce the whole time it's supposed to be closed as the knob is turned. I'm not sure any firmware algorithm would produce good output with an encoder like that.

author: DBecker
author_rank: Frequent Contributor
timestamp: March 02, 2018, 07:25:47 am
content: If the rotary encoder is still bouncing on one phase when the other phase is switching, it's close to useless.It's difficult to see how such an encoder could be de-bounced in hardware.It would be possible for software to make sense of what the knob is doing, but only by doing something like tracking the speed and adapting the filtering to not miss actual switching when turned quickly.

author: David Hess
author_rank: Super Contributor
timestamp: March 02, 2018, 01:05:28 pm
content: Quote from: DBecker on March 02, 2018, 07:25:47 amLow pass filtering the encoder output in hardware *almost* works to solve this.If quadrature optical encoders were more popular, then they would be almost as inexpensive and debouncing issues would be solved

author: Kalvin
author_rank: Super Contributor
timestamp: March 02, 2018, 02:28:55 pm
content: If the rotary encoding is done in software by using a state machine, one could detect invalid state transitions, ignore those transitions, and wait N*3ms since last encoder state change before re-starting the state machine with good inputs.

author: BrianHG
author_rank: Super Contributor
timestamp: March 02, 2018, 02:34:04 pm
content: Quote from: DBecker on March 02, 2018, 07:25:47 amInstead of interrupt on pin change, like I posted earlier, pooling the pins at said 3ms, or better 1ms, and confirming all the port reads equal over the previous 3-5 reads and use that matched result to update you internal software port state as your given encoder position creates a 'software' low pass filter for the data which will ignore glitches from both rotary quadrature inputs. Just like having the 2 sets of 10k resistors and caps on both pins and electrical filters. Now, you use that 'software low pass filter' de-glitched results as you rotary encoder position, not the raw readout from the port. I've done around 4 projects this way with mechanical rotary encoders and never has a skip due to mechanical brush noise. EVER...Please pass this along to your programmer and don't bother changing the PCB or re-wire anything...

author: danadak
author_rank: Super Contributor
timestamp: March 02, 2018, 02:54:18 pm
content: PSOC ahs a quad dec that can be used for this. Includes glitch filtering.http://www.cypress.com/file/185361/downloadSome example projects here -https://community.cypress.com/thread/10200?start=0&tstart=0Regards, Dana

author: DBecker
author_rank: Frequent Contributor
timestamp: March 02, 2018, 05:02:13 pm
content: Quote from: Kalvin on March 02, 2018, 02:28:55 pmIf the rotary encoder is still bouncing on one phase when the other phase is switching... what is an 'invalid' state transition?It's theoretically possible to decode with clever enough adaptive filtering, but the encoder is effectively useless.Cheap encoders are used all of the time, and they don't have this problem. The STM32 used on DSO150 has dedicated hardware timer modes with filters so you don't even need to count encoder pulses with software. Those timer modes often work even without the filters turned on.I'm pretty sure this is a firmware problem, likely a problem with other signals on the dual-use pins. I don't expect it's actually the encoder having an extreme bounce problem.

author: Kalvin
author_rank: Super Contributor
timestamp: March 02, 2018, 05:37:03 pm
content: Quote from: DBecker on March 02, 2018, 05:02:13 pmIn gray code invalid state transition is something that more than one bit changes state at a time.A simple filter would be something that samples pins at given 3 ms, and compares N last pin states. If N last pin states are equal (ie. no debouncing) then use that as filtered pin states.

author: Peabody
author_rank: Super Contributor
timestamp: March 02, 2018, 07:17:49 pm
content: I don't believe a state machine can distinguish valid transitions from noise that makes the same pattern. If both switches are high, then one goes low, then that same switch goes back high, that could be a legitimate reversal of direction, or it could just be bouncing.I worked out what I thought was a firmware solution to this problem, sent it to JYETech, and even wrote it up and posted it on Github. The idea is that the first time both switches are high, you immediately begin looking only for the first time they both are low. The trailing switch which was the last to go high will bounce, but the leading switch, having gone high "much" earlier, is now stable high. So both can't ever be low until the trailing switch goes low. The direction is determined by the state immediately before one of these "target" states first occurs.I think the logic of this is solid, but it depends on the switches settling down after bouncing, so that the two switches are never bouncing at the same time. I tried this out on an MSP430 rig using a PEC11R encoder, which is all I had at hand, and it worked extremely well polling at 2ms, and also using an interrrupt-based method that I thought was extremely slick and efficient.JYETech made a version of the DSO150 firmware using my polling method, and even sent me the relevant portion of the source code, and they did it exactly as I had suggested. So I flashed the new version to my Shell, and guess what - it didn't work worth diddley-squat. It was much worse than the state machine.They said they liked my routine, and that version actually worked fine on their test Shell. So I concluded that my Shell encoder is just really marginal, and that my routine is better than the state machine only if the encoder is well behaved. If it's a bad actor, then the state machine lookup table deals with bad behavior better.The only explanation I can think of for all this is that when one of the switches makes contact, it continues to bounce intermittently the whole time the knob is moving. Maybe both switches, but I kinda think only one. It shouldn't do that. The state machine at 3 ms deals with this reasonably well, but it's still flaky. I guess further firmware "filtering" could help, but was just hoping a minor modification to the circuit would fix it.Anyway, if anyone wants to critique my method, it's in a long-winded PDF file here:https://github.com/gbhug5a/Rotary-Encoder-Servicing-Routines