Rotary encoder code (Dave's) explanation. - Page 1
Forum section: electronics / general

author: firewalker
author_rank: Super Contributor
timestamp: March 10, 2012, 07:33:51 pm
content: Can someone explain witch approach Dave used to decode the encoders? I always had an issue with this subject.Code: (C)#define ENC1A PB0#define ENC1B PB1#define PHASE_A bit_is_set(PINB, ENC1A)#define PHASE_B bit_is_set(PINB, ENC1B)static int8_t enc_delta;static int8_t last;static int8_t knobcount;void UpdateRotaryEncoders(void){int8_t state, diff;//read the voltage rotary encoder knobstate = 0;if( PHASE_A ) state = 3;if( PHASE_B ) state ^= 1;// convert gray to binarydiff = last - state;// difference valueif( diff & 1){// bit 0 = value (1)last = state;// store new as next lastenc_delta += (diff & 2) - 1;// result will be +1 for positive direction and -1 for negative direction}}void CheckKnob(void){if (enc_delta==1) knobcount++;if (enc_delta==-1) knobcount--;enc_delta=0;if (knobcount>3){ //knob1 (Voltage) has been turned in the negative directioncounter--;knobcount=0;}if (knobcount<-3){ //knob1 (Voltage) has been turned in the positive directioncounter++;knobcount=0;}}Basically theUpdateRotaryEncoders()function.Alexander.

author: IanB
author_rank: Super Contributor
timestamp: March 10, 2012, 08:07:26 pm
content: You need to know how PHASE_A and PHASE_B change as the knob is turned. After that just plug Dave's code into Excel and watch what it does as you change PHASE_A and PHASE_B in the proper fashion.

author: Rufus
author_rank: Super Contributor
timestamp: March 10, 2012, 08:58:17 pm
content: Quote from: firewalker on March 10, 2012, 07:33:51 pmCopying someone else's code (from herehttp://embdev.net/articles/Rotary_Encoders).

author: gregariz
author_rank: Frequent Contributor
timestamp: March 10, 2012, 09:22:46 pm
content: I can't comment on the Arduino environment (never used it) but there's *a lot* written about the best way to do it on the various compiler forums. From what I ascertained you essentially use an interrupt handler to detect the movement of the encoder and then try to figure out which way its going why looking at both the signals.I had various bits of code working but I found them troublesome (see the forums for much more on that). From what I see in the end the consensus was that *if possible* decode the encoder signals in hardware and then use a simpler interrupt handler to detect motion and direction. I've used GALS and special quad chips for this and can say from my experience it seems to be the most bulletproof route ie no skipped indents or misreads.

author: Rufus
author_rank: Super Contributor
timestamp: March 10, 2012, 10:04:36 pm
content: Quote from: gregariz on March 10, 2012, 09:22:46 pmFirmware decoding of incremental encoders is not difficult or unreliable. There are obviously restrictions on maximum line rate which can't complete with hardware decoding and counting.Interrupt driven solutions can be troublesome and fairly pointless because if you have to be able to take interrupts at the maximum line rate then taking timer interrupts and polling at say twice the maximum rate isn't that big a deal and it avoids some problems, for example, line rates exceeding the expected maximum swamping the processor.I have used interrupt driven solutions where I needed to time stamp edges for velocity measurement with and without using processor input capture hardware.

author: sonicj
author_rank: Frequent Contributor
timestamp: March 11, 2012, 01:52:45 am
content: i guess hes using hardware debouncing?

author: george graves
author_rank: Super Contributor
timestamp: March 11, 2012, 05:48:06 am
content: "Rotary encoders, done properly"http://www.buxtronix.net/2011/10/rotary-encoders-done-properly.html

author: Bored@Work
author_rank: Super Contributor
timestamp: March 11, 2012, 08:36:57 am
content: Quote from: gregariz on March 10, 2012, 09:22:46 pmAnd this is where it is already going wrong. Mechanical encoders bounce and you get more interrupts than you bargained for. Sample the encoder, don't wait for interrupts, use the gray code to detect missed steps and bounces in one go, only accept valid transitions and you are golden.

author: firewalker
author_rank: Super Contributor
timestamp: March 11, 2012, 09:17:52 am
content: Quote from: george graves on March 11, 2012, 05:48:06 amBuxtronix, is a member of this forum and he had analyzed his code. I think it is one of the most elegant ways to do it out there. Dave's code confused me, but I think I "decoded" it.Alexander.

author: caroper
author_rank: Regular Contributor
timestamp: March 11, 2012, 09:28:07 am
content: I was going to suggest a State machine approach, but that link to buxtronics says it far better than I ever could.

author: buxtronix
author_rank: Contributor
timestamp: March 12, 2012, 05:20:35 am
content: Quote from: BoredAtWork on March 11, 2012, 08:36:57 amMy approach, which has been posted in this thread, is perfect for interrupt driven service, as it's inherently bounce-immune, yet will still sample as fast as you want. I have managed to spin an encoder with a drill and still missed nothing. If a solution requires (sw/hw) debounce, you're going to miss some transitions at speed.3 lines of code at each event, what better simplicity could you want?I've used the same state machine approach for other similarly encoded protocols, eg manchester decoding in 3 lines for Rfid and RC5 IR...

author: IanB
author_rank: Super Contributor
timestamp: March 12, 2012, 05:29:31 am
content: Quote from: buxtronix on March 12, 2012, 05:20:35 amDon't take this the wrong way, but how do you know?If for example you ignore all transitions except valid state transitions you could capture a valid transition after 1/4 rotation, or after 1 1/4 rotations, or after 2 1/4 rotations, and so on. How do you know you didn't miss any full rotations between registered transitions?

author: buxtronix
author_rank: Contributor
timestamp: March 12, 2012, 06:20:17 am
content: Quote from: IanB on March 12, 2012, 05:29:31 amUse an optical sensor+foil to pulse ch1 of a cro when the shaft gets to a known position. Have the micro invert an output when it senses same position via encoder, and plot that on ch2 of cro. Display both and watch for phase shift (or lack of).