Bourns encoder filter: Is the extra R useful in practice, are the values 'good'? - Page 1
Forum section: electronics / projects

author: 741
author_rank: Frequent Contributor
timestamp: August 27, 2019, 02:47:28 pm
content: As I currently understand the "EC11" style encodersOn a stable detent, the encoder contacts are well-and-truly un-connected; there is no way 'noise' can occur hereBetween detents is where the action is, there is scraping and the wipers briefly jump away from the track many times in rapid succession, wheras ideally the wiper would be in contact contiguouslyIf I am correct here, I can see why the Bourns filter circuit (at left) has asymmetrical impedances: we need to discharge C rapidly and ignore brief upward spikes.But then I think - why have the extra resistor at all? Why not just one R, one C? It is as though Bourns are saying "there will in fact be noise inside the detent area - but it will not be so bad" (?)Regarding values: Empirically, with an 18-detent unit, the RHS values seem to deliver bettter results.I have also created an LTSpice simulation.Very roughly, I think a user can "twizz" 1/2 turn in 1/4 second for rapid movement, and slow movement is say 2s for 1/2 turn.

author: MarkF
author_rank: Super Contributor
timestamp: August 27, 2019, 07:50:08 pm
content: You need to look at the suggested circuit differently.The circuit consists of a pull-up resister and a low pass filter.The filter suppresses most of the switching noise (debounce).Both resistors are required.I have used PEC11R encoders and the values in the datasheetare a good compromise between noise and rotation speed.

author: fourfathom
author_rank: Super Contributor
timestamp: August 27, 2019, 08:03:40 pm
content: Quote from: MarkF on August 27, 2019, 07:50:08 pmBut if we eliminate the series resistor, then at the first instant of switch contact the capacitor will be discharged. Any subsequent contact open-circuit bounce will be filtered by the 10K pull-up resistor and the capacitor. The bounce noise filtering will still work. If you suggest that the capacitor discharge will not be complete, note that neither will it be complete when the series resistor is in place.Reasons for the series resistor?Perhaps they are worried about the "large" current spike on contact closure? I would think that with a 10nF capacitor this would not be an issue.Possibly they want the 20K combined charging resistance for a slower filter response, and they thought that a single 20K resistor wouldn't be an adequate pull-up?Perhaps they want a series resistor to protect the circuit from noise picked up on the wires running to the switch. This RC circuit would be a good EMI filter.Only the last reason seems likely.

author: floobydust
author_rank: Super Contributor
timestamp: August 27, 2019, 08:46:54 pm
content: You have to debounce an encoder's switch contacts.The RC filters you show can have a fast rise or fast fall time, or both slow. Also two different time constants 0.1msec or 1msec.Debounce can be done in hardware- with a heavy RC filter but the problem there is too much lag will ruin the quadrature edge timing and you mess up which direction the shaft is being turned, when spun fast. People fudge the RC filter in desperation to get it to work.Debounce can be done in firmware- but not if you use input-edge interrupts because a bounce event say a burst of many pulses at usec's can overwhelm the MCU. So you usually see a light RC filter to prevent high frequency usec transitions from making spurious interrupts. The contact bounce can be still longer in the 10's of msec depending on the switch's construction.I'm saying the RC filter has limitations for debouncing, and depends on which edge you are triggering off of. A long time constant does not work when the knob is turned fast.The housing (pins) for EC11 need a path to earth ground, expect ESD hits to the knob/shaft.

author: rstofer
author_rank: Super Contributor
timestamp: August 27, 2019, 08:51:09 pm
content: If you remove the series resistor, the current spike could be quite high. i = C dv/dt where the real problem is dv/dt (the change in voltage per unit of time). For a decent switch, dv/dt could approach infinity, not because dv is high but because dt approaches 0 and division by 'almost' 0 gives a very high result, regardless of dv. It won't really approach infinity, of course, but it IS a short circuit so it will be pretty high and only limited by circuit resistances.There's a problem with switches and it has to do with the lack of wiping action (probably not a problem for an encoder) and oxidation. To burn through the oxide during closing takes voltage and to maintain a sealed contact takes current. If you increase those pull-up resistors very much (say, 1M), you might find things a little fiddly. It could happen at 100k as well. The encoder is nice because the contacts probably wipe. This is not true for most toggle switches. They actually make 'high fidelity' toggle switches with bifurcated gold plated contacts. They don't give them away!If those are the circuits that Bourns provided, I would tend to use them as is. They have more experience with their encoders than I do.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: August 28, 2019, 12:07:00 am
content: Note that an analog debounce circuit should still be combined with digital debounce logic. The principle is signal filtering, and it works just as well on one-bit signals like these, as on 24-bit digital audio.The goal is to place the analog and digital filters' cutoff frequency Fc so that, their combined attenuation is less than 1 LSB (or whatever your noise threshold is), at Fs - Fc. For Fc < Fs/2. That is, so anything aliased above the Nyquist frequency Fs/2 is attenuated significantly.For a 1-bit input, the attenuation is trivially 1 LSB to begin with, so we want some arbitrary amount less, maybe 0.1 LSB. Or we might simply plan on using a low enough cutoff frequency (which for an encoder, can be some kHz, not a big deal).Note that a fixed sample rate means you can't use interrupt driven encoder input; or, you can but you need to calculate the sample index every time, which is probably a pain. (The running sample index doesn't much matter, only how it changes relative to the most recent edges; I guess you could make a sort of event-driven callback FIR filter response, so it's watching to see if the triggering edge is actually a runt pulse or noise, and only sets the internal variable once it's been stable for some time. That would be cool, but ridiculously over-complicated for the purpose, hah.)Also if you're using interrupt driven input, that's a good reason to prioritize even better analog filtering, maybe follow it up with a 74HC7014 or something to get nice crisp edges (so you aren't depending on the MCU's input pins to turn slow-varying analog levels into logic states).In addition to a A/D filter pair, you may want a nonlinear function, like hysteresis. Putting that in analog form is nice. You can also do it digitally: consider a window of the previous N samples of the pin state (this will use a shift register). Set the internal variable to '1' if all samples equal '1'; set to '0' if all samples equal '0'.This works very well for generally any switch input. It's a bit over-the-top for an encoder, but is still a good idea if you intend to use every single step of the encoder's movement.Now, if you've got an MCU with quadrature decoding hardware, you'll again want to prioritize analog filtering or hysteresis, but on the upside, you can choose an encoder with twice as many steps as you were initially considering, and halve it in software (plus hysteresis) -- that way, a one-bit flip won't disturb the state of your program, and both contacts bouncing is unlikely (at least, until a bit later into the encoder's lifetime).Deep analysis, yes; pedantic, over the top, perhaps; but the high level subjects distill nicely down to simple functions, bringing justification for what may otherwise seem arbitrary. And it still took less time to write this discussion than to actually write the code, so it's not wasted time, or at least not as over-the-top as it may seem.Tim

author: thm_w
author_rank: Super Contributor
timestamp: August 28, 2019, 12:39:43 am
content: Quote from: rstofer on August 27, 2019, 08:51:09 pmAnnoyingly they've left out minimum current from the datasheet:https://www.bourns.com/docs/product-datasheets/pec11l.pdf?sfvrsn=7b1089f1_5One ALPS encoder I found said 1mA but that seems a bit high. Then 0.5mA for the tactile portion. Maximum current is 10mA.A decent mechanical switch is 10uA. I would expect these to be not quite as good as that though.

author: MarkF
author_rank: Super Contributor
timestamp: August 28, 2019, 03:30:20 am
content: In my case, I was using a PIC18F2550 with a fixed 500 Hz interrupt to poll the encoder inputsand I selected pins that had schmitt trigger inputs. On the software side, I used the algorithmdescribed in the attached Application Note (It does NOT use a lookup table). The interruptroutine determined the direction of rotation and then either incremented or decremented a globalcount variable. Then in the main() function, the count variable was used and cleared. Thus,the running count could be applied at a slower rate than the encoder sampling rate.On a side note, you could use the amplitude of the running count as a pseudo acceleration ifyour main execution loop occurs at a relatively regular rate.For example, to set some amplitude:int count=0; // Running encoder count from interruptint amplitude=0; // Variable to be changedmain() {int x; // Temp storage for encoder countwhile (1) {x = count; // Get encoder countcount = 0; // Clear count right away to avoid missing an encoder changeif (x>0) {amplitude += 10abs(x-1)} else if (x<0) {amplitude -= 10abs(x-1)}// Do Other Stuff...}}I choose the 500 Hz interrupt rate because of other functions it also needed to do.You can experiment with the rate to see how slow is acceptable.The code (I rewrote it in C):Code:; PROGRAM: Read Rotary Encoder (RD_ENCDR.SRC); This program accepts input from a rotary encoder through bits RA.0 and RA.1,; determines the direction of rotation, and increments or decrements a counter; appropriately. It displays the hexadecimal contents of the four-bit counter on a; seven-segment LED display connected to port RB.; Remember to change device info when programming a different PIC.device pic16c54, rc_osc, wdt_off, protect_offreset startencoder = radisplay = rb; Variable storage above special-purpose registers.org 8temp ds 1counter ds 1old ds 1new ds 1; Set starting point in program ROM to zero.org 0start mov !rb, #0 ; Set rb to output.mov !ra, #255 ; Set ra to input.clr countermov old, encoderand old, #00000011b:loop call chk_encodermov w, countercall sevensegmov display, wgoto :loopchk_encoder mov new, encoder ; Get latest state of input bits.and new, #00000011b ; Strip off all but the encoder bits.mov temp, newxor temp, old ; Is new = old?jz :return ; If so, return without changing counter.clc ; Clear carry in preparation for rotate-left instruction.rl old ; Move old to the left to align old.0 with new.1.xor old, newjb old.1, :up ; If the XOR resut is 1, increment counter, otherwise decrement.:down dec counterskip:up inc counterand counter, #00001111bmov old, new:return retsevenseg jmp pc+w ; display lookup tableretw 126, 48, 109, 121, 51, 91, 95, 112retw 127, 115, 119, 31, 78, 61, 79, 71

author: 741
author_rank: Frequent Contributor
timestamp: August 28, 2019, 08:53:27 am
content: Can pure firmware ever work well? - DSP texts show that sampled systems always requires analog anti-aliasing pre-filters.Are there real-world reasons why pure firmware (no analog filter) can actually be made to work 'pretty well' in practice? I am discounting parasitic filters here, and assuming ordinary uP clock speeds, say a PIC at 16MHz, nothing ultra-fast.PS: Really nice hi-res scope shot of contact noise herehttps://www.sheffieldhackspace.org.uk/wp-content/uploads/2016/04/10k0n.png.

author: MarkF
author_rank: Super Contributor
timestamp: August 28, 2019, 09:25:53 am
content: At a minimum I would use their suggested circuit.I was able to get a PEC11R to work somewhat with a PIC, on schmitt trigger inputs and the internal 10K pull-ups.However, there were many sign reversals and missed rotations. In addition, you had to move the knob slowly.Say 1/2 second per detent. There is quite a lot of switch bounce even with a brand new one.You still have 10% of the switch bounce even with the filtering. And it gets worse the faster you turn it.You can try checking the inputs several times (or at least wait to see the same value twice in a row) to trysoftware debouncing. But you need to poll pretty fast and you tend to miss valid changes.I was never able to get it good enough to suit my tastes. Forget it if you want to see fast rotations.If you are able to get a pure software solution to work, please post it for us to see.

author: Dubbie
author_rank: Unknown
timestamp: August 28, 2019, 09:34:45 am
content: I have used this exact encoder plugged into an STM32 timer configured as a quadrature decoder. I used datasheet values and have never had any trouble at all with my encoder behavior.I seem to recall I looked at it on the scope and decided that the suggested component values were well-chosen given the resulting waveforms.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: August 28, 2019, 09:37:05 am
content: Quote from: 741 on August 28, 2019, 08:53:27 amThat's basically what the analysis comes down to, in terms of number of bits of filtering by Fs/2 or thereabouts. Since this is a 1-bit channel, there isn't really any meaning to a >1 bit level, or to a <1 bit level. It's really just timing, and you can indeed do a good job (like a sliding-window hysteresis, or if you like, "majority voting", function).The one thing that's unique to analog in this situation, is that the impedance of the switch varies between ~0 and ~infty. We can harness this with a filter to give a fast fall and slow rise, affecting some debounce action right away without impacting, well, the falling edge anyway.Even on a PIC, you're only looking at some dozens of cycles to process a few bytes worth of inputs. Unless you're so hard pressed for time that you literally don't have this much to spare (in which case, you really need to consider a more powerful chip!), yeah, it's no problem to fit that in once every millisecond or so.Tim

author: 741
author_rank: Frequent Contributor
timestamp: August 28, 2019, 12:05:06 pm
content: QuoteBased on my own experience, and also on a fair number of web searches, I have the impression that this level of satisfaction is unusual - maybe it is something about the input hysteresis on the STM32 and also it might relate to # detents?Admittedly also, if something works as expected, it is unlikely to get posted up on a forum.

author: Yansi
author_rank: Super Contributor
timestamp: August 28, 2019, 12:10:19 pm
content: I am quite surprised no one mentioned it already, but the other resistors are there also to protect the encoder contacts from discharging the super-low impedance ceramic capacitors that would otherwise be connected directly across the contacts....as that can shorten the lifespan of the encoder contacts, significantly.

author: thm_w
author_rank: Super Contributor
timestamp: August 28, 2019, 10:33:55 pm
content: Quote from: Yansi on August 28, 2019, 12:10:19 pmWas mentioned twice.But if you are confirming it will actually shorten the contact life then that is useful information. As they don't spell this out in the datasheet, although it can be implied (10mA max current so if you put 10A+ through it even for a short time its probably not good).Quote from: 741 on August 28, 2019, 08:53:27 amWith high quality switches, yes. With something like shown in your image, not really, its always a bit of a hack so you compromise on something.

author: ratatax
author_rank: Regular Contributor
timestamp: October 29, 2019, 07:27:21 pm
content: Quite old thread but yeah, I also use bourns EC11 and the ONLY way I managed to make them work properly is by using both software and hardware deboucing.- Only hardware debounce : still not reliable at all- Only software debounce : works more or less depending on the encoder (they don't behave exactly all the same...)I currently have no resistor between the capacitor and the encoder contacts, so I may add one since as you said it may prematurely ruin the contacts

author: MarkF
author_rank: Super Contributor
timestamp: October 29, 2019, 08:30:29 pm
content: I just started a new project with a Bourns PEC11 encoder.I used the suggested circuit in the datasheet but found thata 20nF capinstead of the 10nF works better.No debounce in code (snippet follows):Code:/* * * * * * * * * * * * * * * * * * * ** PIC18F2620** PEC11 Encoder pins:* C0 = Encoder_SW* C1 = Encoder_A* C2 = Encoder_B** * * * * * * * * * * * * * * * * * * */#include "config.h"#include <xc.h>// Global variablesint8_t en0;int8_t count;uint8_t sw0;uint8_t lastA0;uint8_t lastSW0;//============================================================void main(void){// Setup oscillator (order is important)OSCCON=0x70; // Select primary oscillator @ 8MHzOSCTUNE=0x40; // Select 4 x PLL for INTOSC// Setup rotary encoderen0=0;lastA0=PORTCbits.RC1;sw0=0;lastSW0=1;// Setup CCP2 configuration for clock interruptCCPR2H=0x07; // 500 Hz interrupt (32 MHz system clock)CCPR2L=0xd0;CCP2CON=0x0b; // Compare mode, trigger special event// Setup Timer3 configurationTMR3H=0;TMR3L=0;T3CON=0xb9; // RD16 | TMR1->CCP1 && TMR3->CCP2 | 1:8 Prescale | TMR3ON bits// Enable CCP2 interruptPIR2bits.CCP2IF=0; // CCP2 Interrupt Flag bitPIE2bits.CCP2IE=1; // CCP2 Interrupt Enable bitINTCON=0xc0; // GIE and PEIE interrupts// Main loopwhile (1) {// Process encoder switchif (sw0!=0) {sw0=0;// TODO: Your code}// Process encoder knobif (en0!=0) {count=en0;en0=0;// TODO: Your code}// TODO: Your code__delay_ms(100);}}//============================================================void __interrupt() isr(void){uint8_t pin;uint8_t currA0;if (PIE2bits.CCP2IE && PIR2bits.CCP2IF) {PIR2bits.CCP2IF = 0; // Clear CCP2 Interrupt Flag// Read rotary encoderpin = (PORTC >> 1) & 0x03;currA0 = pin & 0x01;if (lastA0==0 && currA0==1) { // rising edge?pin = (pin >> 1) & 0x01;if (pin!=currA0) en0--; else en0++; // clockwise?}lastA0=currA0;// Switch 0 (encoder)pin = PORTCbits.RC0;if (lastSW0==0 && pin==1) sw0=1; // If button release, set sw0lastSW0 = pin;}}

author: maginnovision
author_rank: Super Contributor
timestamp: October 29, 2019, 09:48:22 pm
content: Pretty interesting. I use the PEC12 encoders with no hardware filtering, just pullups. Spinning like a top you get 0 movement, slow-normal-fast speeds are 0 problem though, very reliable. Maybe next revision I'll add some optional filtering and compare it to software performance.

author: dom0
author_rank: Super Contributor
timestamp: October 30, 2019, 01:16:52 pm
content: Debouncing doesn't really matter for incremental encoders, since only one phase is bouncing at a time, and no matter where you sample that track, if you decode the phases correctly you will always get the correct result after the bouncing is done. If you are using every sampling result this may mean that during bouncing your value will bounce as well, but that will be +-1 , when you are in/decrementing +-1 , so it probably doesn't matter. Otherwise you can debounce after decoding the encoder, e.g. by waiting and comparing.I've used these routines (German) for a long time and they always worked:https://www.mikrocontroller.net/articles/Drehgeber#Solide_L.C3.B6sung:_Beispielcode_in_C

author: ratatax
author_rank: Regular Contributor
timestamp: November 01, 2019, 10:33:14 am
content: Things get complicated when you turn the encoder very quickly (there is almost no "boucing free" time window), and also I use encoders with detents which probably makes a lot more noise than smooth ones...But it's possible to make them reliable even at high speed, one soft/hard debounce I tried worked up to the physical limits of my fingers(like 200 steps/s). It's great to combine this with software acceleration, so the user can quickly reach the value he wants. (too much devices lacks this unfortunately)

author: bson
author_rank: Unknown
timestamp: November 01, 2019, 04:34:59 pm
content: Quote from: 741 on August 28, 2019, 08:53:27 amYou do, in general need filters. However, it's not the debounce that's a problem, if it were you could replace the 100µs TC RC with a 150µs rearming delay on the edge trigger and be done. Because that's exactly what the RC does, except with a phase delay while a firmware trigger rearm delay provides an instant response on the first of a series of bouncy pulses as the contact closes, then just ignores ay spurious input for a little bit. The problem is any glitching if the switch is movedwhile in a closed positionprior to changing state to open (if it actually does); those need to be filtered out. Not unlike the wiper of a pot; it's probably going to rub a little bit before the glitch train indicating opening occurs.

author: SiliconWizard
author_rank: Super Contributor
timestamp: November 01, 2019, 04:56:12 pm
content: The filtering network above is recommended in pretty much most of the mechanical rotary encoders datasheets I've ever run into.It has benefits beyond mere "debouncing". As as been said above, it also spares the contacts. And it also protects against potential spurious edges coming from EMI.I have personally always included it. Whether you need any additional digital "filtering" will depend on the encoder itself, and also on the decoding mode you're using. There are essentially 3 modes you can use: x1, x2, and x4.

author: wraper
author_rank: Unknown
timestamp: November 01, 2019, 05:12:57 pm
content: Quote from: 741 on August 28, 2019, 08:53:27 amIf done properly, it will work better than any analog crap you can come up with. What aliasing filters? It's not like you are feeding it into ADC. The only reason there might be some need for input filtering is strong EMI.

author: wraper
author_rank: Unknown
timestamp: November 01, 2019, 05:15:15 pm
content: Quote from: bson on November 01, 2019, 04:34:59 pmIn general you don't. In most cases analog filtering is done by those who don't know any better. Or is there are "non general" reason to do so.

author: mjs
author_rank: Regular Contributor
timestamp: November 01, 2019, 05:43:22 pm
content: The series resistor is important - the capacitor discharge current can be quite big and will quickly destroy the contact.I've seen 5-10A pulses from 100nF cap in similar settings without the series resistor when digging out why there was a lot of field failures in one device.

author: 741
author_rank: Frequent Contributor
timestamp: November 04, 2019, 04:28:36 pm
content: QuoteYes you are, a 1-bit ADCIt'd be interesting to see your code...

author: wraper
author_rank: Unknown
timestamp: November 04, 2019, 05:58:22 pm
content: Quote from: 741 on November 04, 2019, 04:28:36 pmBy this logic, every digital IC is ADC. Even more, there is no digital at all. All is analog because electricity is not digital and "digital" signals have transition time with voltage levels in between.

author: 741
author_rank: Frequent Contributor
timestamp: November 04, 2019, 09:03:59 pm
content: Well: It can be argued that digital is "overdriven analog".Really, my point is that (I believe) we still have a "sampled data system", even with "1 bit resolution".

author: T3sl4co1l
author_rank: Super Contributor
timestamp: November 05, 2019, 04:06:35 am
content: Quote from: wraper on November 04, 2019, 05:58:22 pmYes, quite!Every pin is an ADC or DAC, as the case may be. Within the chip, we can follow the rules of digital logic (combinatorial and sequential logic, drive strengths if applicable, and propagation delays), and make some exceptions or precautions for metastability where applicable; but outside the chip, it's the wilderness. This is why logic circuits don't always simply work when you lash them together. You can't ignore analog considerations like signal quality forever.Tim

author: thm_w
author_rank: Super Contributor
timestamp: December 13, 2019, 09:32:15 pm
content: Some more bounce testing here:http://www.ganssle.com/tem/tem387.html(scroll half way to "Encoder bouncing").The PEC11 was better than spec, 250us worst case, CUI was 5ms.Cheap aliexpress PEC clones I have are usually good but will sometimes bounce up to ~6ms or so. A lot of it due to the technique you use to turn it.

author: 741
author_rank: Frequent Contributor
timestamp: December 19, 2019, 09:49:47 am
content: Jack Ganssle (TEM) has given some interesting info. See The Embedded Muse #387 (http://www.ganssle.com/tem/tem387.html) for more info, scope shots etcHe found a 24 detent unit seemed to be ideally filtered with Bourn's suggested generic RC, but a 12 detent unit was not so easily tamed. My own experience has been that with a Bourns PEC-11 18 detent unit, the results were more like the images given for the 12-detent unit.

author: ita4ever
author_rank: Contributor
timestamp: March 16, 2024, 11:26:54 am
content: Quote from: MarkF on August 27, 2019, 07:50:08 pmOk but why don't use the internal uC's pull-up?

author: MarkF
author_rank: Super Contributor
timestamp: March 16, 2024, 12:42:02 pm
content: Quote from: ita4ever on March 16, 2024, 11:26:54 amIt may work, it may not, it might not be reliable, ...Sometimes your gray_code count decoding will actually reverse direction.You are basically eliminating the low pass filter by only using the built-in pull-ups, allowing more switching noise into the MCU. Also, the internal pull-ups would be after the filter. Not before as desired.

author: ita4ever
author_rank: Contributor
timestamp: March 16, 2024, 02:14:11 pm
content: Quote from: MarkF on March 16, 2024, 12:42:02 pmThanks for your answer.Yes, surely, the internal pull-ups would be after the filter. This was mainly my doubt.In my experience a normal push-button with RC low-pass filter + internal uC's pull-up is reliable.But of course here we have an encoder so also the train pulses speed and direction matter.

author: MarkT
author_rank: Frequent Contributor
timestamp: March 17, 2024, 09:44:56 am
content: You don't need low pass filtering on an encoder switch like this, in general you don't get both contacts bouncing at the same time so any microcontroller sampling of the signals sees a valid quadrature signal. And even if you do occasionally who cares, its an encoder switch, its relative, not absolute. Just don't sample it too fast and any uncorrected bouncing issues will be limited in effect.If absolute position matters you need an absolute encoder switch anyway, like this:https://www.mouser.co.uk/ProductDetail/Bourns/EAW0J-B24-CE0128L?qs=N2XN0KY4UWWoYrMCVscpfw%3D%3D

author: tooki
author_rank: Super Contributor
timestamp: March 17, 2024, 10:01:53 am
content: Quote from: MarkT on March 17, 2024, 09:44:56 amThen why do the rotary encoder manufacturers recommend using them in the datasheets, providing recommended circuits and values?

author: MarkF
author_rank: Super Contributor
timestamp: March 17, 2024, 12:02:12 pm
content: Quote from: MarkT on March 17, 2024, 09:44:56 amActually, the exact opposite of everything you said is true.These encoders (example a Bourns PEC11) are very noisy when switching (look at them on a scope).A resistor and a capacitor on each pin is trivial to ease the burden on the software.And unless you're willing to accept turning the encoder very slowly, you will wanta pretty fast sample rate. I sample mine at 500Hz to provide an expected response.It's been some time since I've looked at these, but you certainly want to be above 100Hz.As I said earlier, no filter, a slow update and you will often get a response in the oppositedirection than you're turning encoder. Unless you want to drop big bucks on an optical encoder.

author: Peabody
author_rank: Super Contributor
timestamp: March 17, 2024, 06:51:15 pm
content: Just to mention that a big downside of interrupt based encoder servicing - a large number of interrupts generated by bouncing - can be avoided by having interrupts enabled on only one line at a time. So when A triggers its interrupt, the ISR disables further interrupts on that line, and enables them on B, which should be stable by now. So subsequent bouncing on A will not trigger interrupts. Special provisions are needed to deal with a change in direction, but in the end you end up with four interrupts per detent for a standard encoder. The encoder needs to not be totally awful, because if both lines are bouncing at the same time, this won't work. But if that's the case, no firmware method will work.

author: MarkF
author_rank: Super Contributor
timestamp: March 17, 2024, 08:06:10 pm
content: Quote from: Peabody on March 17, 2024, 06:51:15 pmNever interrupt on pin change. That's just asking for trouble.And the interrupt service routine WILL get swamped.You set up a timer and interrupt at a fixed clock rate.Then check for pin changes and decode into an up/down count.Very short quick interrupt service.The main process then uses the count from the interrupt (i.e. + or - count since last).Increments/decrements whatever (can do some acceleration here) and clears the count fromthe interrupt service and waits (or does something else) until the next count arrives.(Usually check for a non-zero count somewhere during your main processing loop.)

author: Peabody
author_rank: Super Contributor
timestamp: March 18, 2024, 02:02:25 am
content: Interrupts work fine with rotary encoders. When the knob isn't being turned, you have zero overhead. You just need to limit interrupts caused by bouncing so nothing gets swamped. See the PDF here:https://github.com/gbhug5a/Rotary-Encoder-Servicing-Routines/tree/master/Arduino

author: ita4ever
author_rank: Contributor
timestamp: March 20, 2024, 01:20:40 pm
content: Quote from: MarkF on March 16, 2024, 12:42:02 pmThese are some screenshots for a single encoder's channel.scope_10/11 are with the 10K pull-up removed from encoder's pin and moved after the RC as it was a uC's internal pull-up.scope_12/13 are as suggested by encoder datasheet.scope_15/16 are with just a 10K pull-up.The encoder is a generic one, not the Bourns.

author: 741
author_rank: Frequent Contributor
timestamp: March 21, 2024, 12:33:40 pm
content: Interesting images. Is is possible to show the two channels (A,B) on the same screen-shot?

author: ita4ever
author_rank: Contributor
timestamp: March 22, 2024, 09:00:11 pm
content: Quote from: 741 on March 21, 2024, 12:33:40 pmImages below refer to the datasheet suggested solution (RC=10k+10nF, pu=10k) applied on both channels.After the previous analysis I think it's the best solution, as pointed-out by @MarkF.Going without the RC filter is too expansive to be handled by the fw in my opinion.The solution with internal pull-up might work tuning a bit the RC filter because the uC's internal pull-up is not tunable of course. And uC's Vil_max must be respected.e.g. stm32gxxx has 40k typical pull-up and Vil_max near 1V.scope_17/18: both channels, single knob stepscope_20/21: both channels, fast knob turning

author: 741
author_rank: Frequent Contributor
timestamp: March 23, 2024, 06:37:13 pm
content: These images show good logic levels - provided the read is made soon after an edge (e.g. a falling edge) is seen. For instance in scope_21.jpg , it would be necessary to read green within 1ms of yellow falling, preferably within 0.5ms.I am impressed that the eges are so clean ('strictly falling' or 'strictly rising', not "up & down"), so the RC does seem to be "just right". I seem to recall that I had less well-behaved edges, even with RC filtering.Also, I notice that the high level is more steady than the low level - perhaps suggesting the read should be best done following a rising edge.How many 'detents' are on this encoder (and what make is it out of interest?).

author: MarkF
author_rank: Super Contributor
timestamp: March 24, 2024, 02:08:26 am
content: On the Bourns PEC11 encoders I've been using, both pins go high when it's not being turned (i.e. the encoder contacts are open).Mine were 24 detents but I don't think that effects the gray code or the way you would process it.The biggest impact is the rotation speed. Obviously, the faster the rotation the less time you have to detect transitions in the gray code.I don't know how fast the encoder was being turned for the screen captures. The faster you sample the pins, the faster you will be able to turn the encoder a get good results. The happy medium for me given a 48MHz pic18f2620 MCU is about 500Hz (2ms, which is quit a bit slower than the 0.5ms you pointed out).Again, I don't recommend doing interrupts based on Interrupt-on-Change.If you look earlier, you see that a periodic interrupt service should be able to get in and out in only 6 or 7 lines of code.

author: ita4ever
author_rank: Contributor
timestamp: March 24, 2024, 08:12:40 pm
content: Quote from: 741 on March 23, 2024, 06:37:13 pm20 steps; brand/make unknown because there is no marking on the encoder.

author: ita4ever
author_rank: Contributor
timestamp: March 24, 2024, 08:19:35 pm
content: Quote from: 741 on March 23, 2024, 06:37:13 pmThe trace of scope_12.jpg is not so clean (because the encoder was probably spinning at a higher speed).