Quadrature encoder decoder chip. - Page 1
Forum section: electronics / general

author: firewalker
author_rank: Super Contributor
timestamp: October 06, 2011, 07:43:28 am
content: Is there any chip for decoding quadrature encoders?E.g.When encoder at rest: Out-1, Out-2 to LOW.When encoder CW: Out-1 pulsing according to the speed of turning the encoder.When encoder CCW: Out-2 pulsing according to the speed of turning the encoder.I know it can be done with an mcu (I have already implement it). I was wondering for a specific ic for the job.

author: buxtronix
author_rank: Contributor
timestamp: October 06, 2011, 11:11:50 am
content: The MAX7360 has a rotary decoder, but wont give the output you want (it is i2c).You're probably better off implementing it in a small MCU, its easy to get it to run withone chip and no external components. And probably cheaper. Unlikely that there isanything that gives exactly what you want.

author: FreeThinker
author_rank: Frequent Contributor
timestamp: October 06, 2011, 02:11:24 pm
content: Not sure I understand what you are after but the system you describe made in think 'mouse' as a first thought. A single axis of the mouse would give you what you need, or if you need two discrete channels then use both axis. Any good for you?

author: Zad
author_rank: Super Contributor
timestamp: October 06, 2011, 06:11:17 pm
content: Should be a pretty simple state machine. If you can't find a custom chip for the job then a PIC10 or 12 should be easy to configure.

author: firewalker
author_rank: Super Contributor
timestamp: October 06, 2011, 07:23:42 pm
content: I have already made what I want with an AVR.I was wondering if there was a chip just for the job that would be potentially cheaper.

author: deephaven
author_rank: Frequent Contributor
timestamp: October 06, 2011, 09:45:32 pm
content: Quote from: firewalker on October 06, 2011, 07:23:42 pmYou can get a PIC10F204T-I/OT for £0.38 from Farnell (1 off), I doubt if you'll find a dedicated chip cheaper than that.

author: BravoV
author_rank: Super Contributor
timestamp: October 07, 2011, 06:22:28 am
content: Quote from: firewalker on October 06, 2011, 07:23:42 pmI don't think it will be cheaper, thats why it doesn't exist and they don't make it, its too expensive to design and produce such chip and probably will not sell either, this from chip maker's perspective.

author: Zero999
author_rank: Super Contributor
timestamp: October 07, 2011, 05:10:28 pm
content: The cheapest PIC is just over half the price of the cheapest AVR in RS Components: ATTINY4-TSHR costs £0.64 and the PIC10F200 costs £0.34.The MCU you've used is probably overkill, use a cheaper one.

author: Mechatrommer
author_rank: Super Contributor
timestamp: October 08, 2011, 01:04:05 am
content: Quote from: Hero999 on October 07, 2011, 05:10:28 pmi dont think attiny is overkill. i've done this exactly encoder with pic10f206, my limitation is it only can encode reliably up to ~100rpm. if i have 4x processing speed, it will be able to do up to 400rpm. this type of state machine is about speed, if your system got high rpm.

author: NiHaoMike
author_rank: Super Contributor
timestamp: October 08, 2011, 02:15:14 am
content: Have you tried the MSP430? Even the cheapest one can run at up to 16MHz with most instructions only using one cycle.

author: firewalker
author_rank: Super Contributor
timestamp: October 08, 2011, 11:07:11 am
content: Well, the Attiny2313 was the first chip I found in my drawers with two external interrupts pins (there will be two quadrature encoders, and four outputs two for every encoder).Alexander.

author: NiHaoMike
author_rank: Super Contributor
timestamp: October 08, 2011, 12:51:53 pm
content: Since its only task is to decode a quadrature encoder, try using polling instead of interrupts. On most processors, interrupts have a significant latency.

author: buxtronix
author_rank: Contributor
timestamp: October 08, 2011, 01:42:21 pm
content: Indeed, if the only thing your MCU is doing is decoding this, then polling is the way to go. Interrupts only make sense if your MCU has to also do something else.Any MCU should be able to decode these at thousands of RPMs, unless your routine is complex. I have a routine that has 3 lines of logic code (and immune to switch bounce). Thats a pretty tight loop.

author: Mechatrommer
author_rank: Super Contributor
timestamp: October 08, 2011, 02:12:17 pm
content: Quote from: buxtronix on October 08, 2011, 01:42:21 pmor you want low powered (sleep), or there's not much rotation going on, like non continuous or only once a while in a day.

author: Rufus
author_rank: Super Contributor
timestamp: October 08, 2011, 03:01:50 pm
content: Quote from: Mechatrommer on October 08, 2011, 01:04:05 amStating encoder rpm without stating encoder lines is completely meaningless. My rough estimate is a polled loop in a PIC10F2xx should be able to track about 1.5 million lines/minute.

author: Mechatrommer
author_rank: Super Contributor
timestamp: October 08, 2011, 07:05:30 pm
content: Quote from: Rufus on October 08, 2011, 03:01:50 pmthe same with stating encoder lines without stating what it can do or cant. my encoder was to (as usual) encode the rotation (from my old mouse encoder), keep track of previous and current state (4 quadrature state right?) so to be able to decide whether CCW or CW, and then increment or decrement a 32bit value (counter) to be reported back to main mcu when asked through 2pin uart like comm. the idea was to make zero processing in the main mcu (full processing and report mech. in encoder), the main mcu will get a nice 32bit value from pic10f by request. its by polling, and the encoding must not be stopped even while uart reporting. it took me 5 versions to get it speced properly at 100rpm (slightly more). now ask me to do it in 3 opcodes? i surrender.

author: buxtronix
author_rank: Contributor
timestamp: October 09, 2011, 07:30:28 am
content: This is my encoder routine for AVR. 2 lines of C code logic (more if you want to make it verbose).Just add a counter and serial routines.Code:/** Rotary encoder handler.** This assumes wiper is ground, and 2 outputs are on PB0 and PB1.** More info: http://www.buxtronix.net/2011/10/rotary-encoders-done-properly.html*/const char ttable = {{0x3 , 0x2, 0x1, 0x0}, {0x83, 0x0, 0x1, 0x0},{0x43, 0x2, 0x0, 0x0}, {0x3 , 0x5, 0x4, 0x0},{0x3 , 0x3, 0x4, 0x40}, {0x3 , 0x5, 0x3, 0x80}};volatile char state = 0;void rotary_init() {DIRB = 0x0; // PortB is inputPORTB = 0x3; // Weak pullup on PB0/PB1.}/* Read input pins and process for events. Call this either from a* loop or an interrupt (eg pin change or timer).** Returns 0 on no event, otherwise 0x80 or 0x40 depending on the direction.*/char rotary_process() {state = ttable[state & 0xf][PORTB & 0x3];return (state & 0xc0);}

author: Mechatrommer
author_rank: Super Contributor
timestamp: October 09, 2011, 01:12:43 pm
content: nice code bux, using lookup table with some sort of fancy indexing to get current state. with code in C, it could more lines when translated to assembly, not that really important as long as it works. but how do you make sure it is bounce free as you said?edit i just read your site where you explained state 1,2,3,4. if we are at state 2, the only acceptable next state is either 1 and 3. jump to state 4 will be ignored right? well, in my case its possible. so we are working on different system. on high speed system, if it happens state 2 jumps to state 4, i will count as two click (count) and rotation direction is based on previous rotation. based on momentum law.

author: Zero999
author_rank: Super Contributor
timestamp: October 09, 2011, 02:14:15 pm
content: What sort of encoder are you using? An optical encoder shouldn't bounce.

author: Mechatrommer
author_rank: Super Contributor
timestamp: October 09, 2011, 02:33:30 pm
content: me? yes optical encoder, i dont have to handle bounce, only "jump" state. for lookup table as bux's method, pic10f will not be able to do, it only has 24 registers, no eeprom. it was cranking up every bit of it. so attiny should be more comfortable for my earlier job. but if its only for rotary encoder for user interface, like knob, then pic10f should be just fine, no need lookup table no need fancy codes, just code all you like. ymmv.edit: btw, the OP method of CW pin1 pulsing and CCW pin2 pulsing is more elegant way i think compared to serial comm like method (if speed is a concern), its just the main mcu needs a little bit of + - algebra.

author: baljemmett
author_rank: Unknown
timestamp: October 09, 2011, 04:44:14 pm
content: Quote from: Mechatrommer on October 09, 2011, 02:33:30 pmHuh? By my reckoning even a naive assembler translation of the guts of the suggested code above would only require two registers (the state variable and a temporary), 25 words of program space for the lookup table, and approximately eight words of program space for the rotary_process routine. There'd be plenty of space in a 256-word PIC10F device, even after accounting for initialisation code, a main loop to poll rotary_process and pulse outputs as required, and me potentially miscounting lines of code when doing a quick compilation in my head...

author: Mechatrommer
author_rank: Super Contributor
timestamp: October 09, 2011, 06:26:37 pm
content: Quote from: baljemmett on October 09, 2011, 04:44:14 pmi know about two registers. but how do you access program space?

author: buxtronix
author_rank: Contributor
timestamp: October 10, 2011, 12:09:06 am
content: Quote from: Mechatrommer on October 09, 2011, 01:12:43 pmSo two things...1 - If state is jumping from 2 to 4 directly, then something isnt right. It's always bad news if a state from your encoder is going astray. You either have something skipping a contact...or the MCU is not fast enough.2- If there is a reason that cannot be otherwise fixed, it's not hard at all to modify the state table such that from state 2 to state 4, it emits a CW/CCW code. The Arduino library linked from my blog has the state tables more verbose (properly worded #defines), and emitting a code on a jump from 2 to 4 is possible (including adding a 3rd bit to indicate a double jump). Let me know if you'd like me to show the changes necessary.

author: Mechatrommer
author_rank: Super Contributor
timestamp: October 10, 2011, 04:36:11 am
content: Quote from: buxtronix on October 10, 2011, 12:09:06 amyes the problem is if the mcu is not fast enough. its ok i'm not into it anymore maybe next time. at least you showed one way of doing it.Quote from: Mechatrommer on October 09, 2011, 06:26:37 pmlet me answer my own question. even though there's no instruction in pic10f to access the program space directly, but maybe its possible using the program space in form of returning function. by manipulating its address or PC register. i never tried but i think its possible. pseudo code maybe like this...Code://lookup table in program spaceprogAddr:retlw 0x03retlw 0x02....retlw 0x80// the applicationmain:;// do something to get somethingPC = progAddr + state * 4 + PORTB ;//change program address to point to the lookuptable (retlw table)state = W ;// new stateas i said, i never tried and it needs more work rather than this simple pseudo. just maybe.

author: Rufus
author_rank: Super Contributor
timestamp: October 10, 2011, 05:44:30 am
content: Quote from: buxtronix on October 09, 2011, 07:30:28 amCode:....* Revision 1.1 1992/12/03....static Byte bdata encstate; // Encoder statesbit eap = encstate^3;sbit ebp = encstate^2;sbit eac = encstate^1;sbit ebc = encstate^0;....// Absolute position change indexed by new encstatestatic char code absdelta[] = {0, 1, -1, 0, -1, 0, 0, 1, 1, 0, 0, -1, 0, -1, 1, 0};// Maintain absolute position from encoder inputseap = eac;ebp = ebc;eac = ENCAI;ebc = ENCBI;abspos += absdelta;One of mine in 8051 C.

author: baljemmett
author_rank: Unknown
timestamp: October 10, 2011, 12:43:30 pm
content: Quote from: Mechatrommer on October 10, 2011, 04:36:11 amYes, that's how I'd have done it -- seems to be a (or the!) canonical method for non-sparse lookup tables on a PIC. The lookup table is implemented as:Code:ttable:addwf PC, Fretlw 0x3 ; ttableretlw 0x2retlw 0x1retlw 0x0retlw 0x83 ; ttableretlw 0x0retlw 0x1retlw 0x0[... etc ...]And then the rotary_process routine is something like:Code:rotary_process:movf state, W ; table index is 4 * (state & 0x0f) + (GPIO & 0x03)andlw 0xfmovwf temprlf temp, Frlf temp, F ; first term now in tempmovf GPIO, Wandlw 0x3addwf temp, W ; now W contains the computed table indexcall ttable ; do the lookupmovwf state ; and retain new stateandlw 0xc0; and now W's top two bits indicate direction of turn, if any; a return would be nice but the 10F200 seems only to have retlw!... the lack of return means you'd want to actually just make that the main loop, with a few lines at the end to set those two bits on the output pins. But that's no great loss, since the main loop was just going to be a call rotary_process and the same few lines at the end! (Also, my rotary_process can definitely be optimised by at least one instruction, but I'll leave it as is for the sake of clarity.)

author: dfnr2
author_rank: Regular Contributor
timestamp: October 11, 2011, 06:54:35 pm
content: US Digital sells an LSI logic chip (LS7183) that will do what you want(Here's the link.)You can also get in in an SMD version, and a version that provides a DIR and PULSE output instead of separate UP and DOWN pulse outputs (LS7184). These have schmitt triggers and debounce built in. They also have fancier quadrature decoders.If you are producing in large volumes and cost is an issue, then as others have said, you can do this in a 8-pin PIC, which you can order pre-programmed from Microchip direct and save time and errors during assembly. BTW, I personally have learned to steer clear of the Atmel parts for anything other than hobby use, due to their long history of availability issues.Dave

author: Gall
author_rank: Frequent Contributor
timestamp: October 12, 2011, 12:12:50 pm
content: Well, even a couple of 74s is enough to do that.