Author Topic: Quadrature Rotary encoder  (Read 7332 times)

0 Members and 1 Guest are viewing this topic.

Offline mr1979Topic starter

  • Contributor
  • Posts: 14
Quadrature Rotary encoder
« on: August 30, 2017, 06:30:16 pm »
I need to read rotation direction of a quadrature rotary encoder without any delay because I need to drive an up/down counter very accurate. Encoder will be used to select a value on a control panel. I need to realize the circuit only with discrete logic without using any software or programmable logic. Please help me to find a solution. Thank you in Advance. Marco


Inviato dal mio PLK-L01 utilizzando Tapatalk

 

Online Benta

  • Super Contributor
  • ***
  • Posts: 5877
  • Country: de
Re: Quadrature Rotary encoder
« Reply #1 on: August 30, 2017, 06:43:58 pm »
D flip-flop is the usual way, provided the encoder is debounced already.
 

Offline mr1979Topic starter

  • Contributor
  • Posts: 14
Re: Quadrature Rotary encoder
« Reply #2 on: August 30, 2017, 06:51:07 pm »
I tried with D flip flop but there is a transition between 2 detent in a particular position where i loss one or two steps before recognizing the change of direction. Can you post an example circuit?

Inviato dal mio PLK-L01 utilizzando Tapatalk

 

Offline mr1979Topic starter

  • Contributor
  • Posts: 14
Re: Quadrature Rotary encoder
« Reply #3 on: August 30, 2017, 07:18:25 pm »
I found a lot of example circuit on Internet but none of them seems to work well. If only a phase is used to clock data in D flip flop i loose a direction detection when this phase doesn't change and change only the other phase. Did you experienced this problem? Maybe i' m doing some mistake.

Inviato dal mio PLK-L01 utilizzando Tapatalk

 

Offline max_torque

  • Super Contributor
  • ***
  • Posts: 1282
  • Country: gb
    • bitdynamics
Re: Quadrature Rotary encoder
« Reply #4 on: August 30, 2017, 08:40:07 pm »
i Assume this is for some education project?  Because in the real world, in 2017, you'd be mad not to use a small cheap micro, which now retail for less than even the price of some old school "glue logic" ICs...........
 
The following users thanked this post: Someone

Offline mr1979Topic starter

  • Contributor
  • Posts: 14
Re: Quadrature Rotary encoder
« Reply #5 on: August 30, 2017, 09:03:43 pm »
No it's not for education. Is an application in which also simple software is not permitted.

Inviato dal mio PLK-L01 utilizzando Tapatalk

 

Offline mr1979Topic starter

  • Contributor
  • Posts: 14
Re: Quadrature Rotary encoder
« Reply #6 on: August 30, 2017, 09:04:55 pm »
Using a micro is very simple and cost effective, but in this application is not allowed.

Inviato dal mio PLK-L01 utilizzando Tapatalk

 

Offline Ian.M

  • Super Contributor
  • ***
  • Posts: 12860
Re: Quadrature Rotary encoder
« Reply #7 on: August 30, 2017, 09:54:50 pm »
If you want to implement a QEI to Up/Down pulse interface in pure LSI/MSI logic hardware, the best option would be a clocked synchronous implementation of the classic QEI state machine.

Here's a C implementation of the classic 4 bit QEI state machine for reference:
Code: [Select]
/*
   State | A B | direction
   ------+-----+----------
       1 | 1 0 | ^ reverse (B leads A)
       2 | 1 1 | ^
       3 | 0 1 | ^
       4 | 0 0 | .
       1 | 1 0 | v
       2 | 1 1 | v
       3 | 0 1 | v forward (A leads B)
       
   Logic Equations
   ===============
   NoMove  = /A'./B'./A./B + /A'.B'./A.B + A'./B'.A./B + A'.B'.A.B
   Forward = /A'./B'.A./B  + A'./B'.A.B  + A'.B'./A.B  + /A'.B'./A./B
   Reverse = /A'./B'./A.B  + /A'.B'.A.B  + A'.B'.A./B  + A'./B'./A.B
   Error   = /A'./B'.A.B   + A'./B'./A.B + /A'.B'.A./B + A'.B'./A./B
   
*/

// vector is packed bits: A' B' A B
vector=(vector<<2)&0xA; // Preserve old A,B as A',B'
if(A) vector|=2; // Read encoder inputs
if(B) vector|=1;

// Convert to up/down count
switch(vector) {
   case: 0b0000 // /A'./B'./A./B
   case: 0b0101 // /A'.B'./A.B
   case: 0b1010 // A'./B'.A./B
   case: 0b1111 // A'.B'.A.B
   // No movement
   break;

   case: 0b0010       // /A'./B'.A./B
   case: 0b1011 // x4 // A'./B'.A.B
   case: 0b1101 // x2 // A'.B'./A.B
   case: 0b0100 // x4 // /A'.B'./A./B
   // Forward
   count++;
   break;

   case: 0b0001       // /A'./B'./A.B
   case: 0b0111 // x4 // /A'.B'.A.B
   case: 0b1110 // x2 // A'.B'.A./B
   case: 0b1000 // x4 // A'./B'./A.B
   // Reverse
   count--;
   break;

   case: 0b0011 // /A'./B'.A.B
   case: 0b1001 // A'./B'./A.B
   case: 0b0110 // /A'.B'.A./B
   case: 0b1100 //  A'.B'./A./B
   // Error: both signals changed
   break;
}

// Comment out lines tagged // x4 to halve the count rate. 
// Commenting out lines tagged // x2 and // x4 will quarter the count rate.
Edit:  Corrected inconsistencies between comments and code + added logic equations: . is AND, + is OR and / is NOT.

The above code needs to be either polled faster than A or B can change or triggered by an interrupt on change of A or B.  The delay with even a 10KHz polling rate would be negligible for a manual UI control knob, even if it has a spinner.


Considering a hardware implementation in 74HCxx logic, I belive it can be done in five chips:  The state of A and B would be captured by a 74HC74 dual D type flipflop,  Another 74HC74 would capture both Q outputs of the first one to preserve the previous state of A and B.  All the flipflops in both 74HC74 chips would be clocked by the external sampling clock.   The four Q outputs from both 74HC74 chips form the four bit state vector as in the code above.   The vector goes to a 4 to 16 line decoder (built from two 74HC138 chips, with A0 to A2 connected to the low three bits of the vector and the high bit connected to an EN of one and /EN of the other.  The remaining /EN pins are strapped low and EN pin strapped high).  This section is equivalent to the switch(vector) statement.  Finally, the decoded state outputs from the '138 chips, each one being equivalent to a case in the code above, feed a 74HC20 dual 4 input NAND gate.  Each NAND combines four states to get one directional count pulse, equivalent to the count++ and count-- statements above.  The output pulse will go high for one clock period if the encoder has moved in that direction.

An asynchronous self-clocked implementation would be similar, but you'd need a mess of XORs and monostables to generate two clock pulses shortly after every input transition.
« Last Edit: August 31, 2017, 07:29:28 pm by Ian.M »
 
The following users thanked this post: exe

Offline Cerebus

  • Super Contributor
  • ***
  • Posts: 10576
  • Country: gb
Re: Quadrature Rotary encoder
« Reply #8 on: August 30, 2017, 11:00:35 pm »
If you want a one chip solution, look at the Agilent HCTL-2000 Quadrature Decoder/Counter Interface IC and its close cousins (probably now a Broadcom part as I believe this part of Agilent was sold off to them).

Even if you don't want a single chip solution (or want to program a corner of a CPLD or FPGA to do the job) the datasheet is still worth a look as there is a passable 'theory of operation' section in it, including a simple but effective digital filter for debouncing before feeding the quadrature signals into a state machine and counter.
Anybody got a syringe I can use to squeeze the magic smoke back into this?
 

Offline Someone

  • Super Contributor
  • ***
  • Posts: 4531
  • Country: au
    • send complaints here
Re: Quadrature Rotary encoder
« Reply #9 on: August 31, 2017, 01:09:54 am »
No it's not for education. Is an application in which also simple software is not permitted.
Doing this in logic introduces significant challenges in meeting the timing requirements of the logic. Since you said this is for a user control the timescales of possible input changes is so slow that logic is a poor choice for the problem, analog comparators might be more appropriate!
 

Offline Ian.M

  • Super Contributor
  • ***
  • Posts: 12860
Re: Quadrature Rotary encoder
« Reply #10 on: August 31, 2017, 02:00:42 pm »
I've taken the QEI state machine concept I posted earlier and implemented it in (simulated) 74HCT logic. 5 chips if externally clocked or 6 if self clocked.   Its *FUGLY* but it should work.   Complete zipped LTspice sim attached.

« Last Edit: August 31, 2017, 02:03:10 pm by Ian.M »
 
The following users thanked this post: cdev

Offline mr1979Topic starter

  • Contributor
  • Posts: 14
Re: Quadrature Rotary encoder
« Reply #11 on: August 31, 2017, 07:09:46 pm »
I've taken the QEI state machine concept I posted earlier and implemented it in (simulated) 74HCT logic. 5 chips if externally clocked or 6 if self clocked.   Its *FUGLY* but it should work.   Complete zipped LTspice sim attached.
Thank you for your support!!! You have help me a lot!!!!

Inviato dal mio PLK-L01 utilizzando Tapatalk

 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7740
  • Country: ca
Re: Quadrature Rotary encoder
« Reply #12 on: September 01, 2017, 05:46:32 am »
I've taken the QEI state machine concept I posted earlier and implemented it in (simulated) 74HCT logic. 5 chips if externally clocked or 6 if self clocked.   Its *FUGLY* but it should work.   Complete zipped LTspice sim attached.

Change your 74HC74 with a 74HC574.  1 clock wire, feed 2 d inputs and their output to the next stage d inputs.  GND the unused D inputs.  Simplifies breadboarding...

Also, you can get rid of the 74HCT86 and feed the enables with a CLK signal instead.  This will slightly delay the count pulse depending on the clock rate, but, what the hell, just feed this circuit a 4MHz clock.  If you think the quadrature res-once circuitry will affect location with a sample time of 1 - 4 millionth of a second, you must have a rotary encoder approaching relativistic speeds.  (A significant portion of the speed of light...)

Also, you don't necessarily need to debounce the encoder signal, all a bounce would do it move the counter position back and forth during that middle ground.  If the bounce output of your encoder exceeds the time between a transition on both A&B source signals, you are moving the encoder too fast for reliable motion acquisition.


Also in the schematic, is says you can feed an external clock, but, that clock signal is shorted with the 74HCT86 output.  Be careful here.  I believe that they mean use and external clock like I recommend and completely get rid of the 74HCT86, or, use the 74HCT86 as your clock generator as stated 'SELF CLOCKING OPTION'...
« Last Edit: September 01, 2017, 06:02:54 am by BrianHG »
 
The following users thanked this post: cdev

Offline Ian.M

  • Super Contributor
  • ***
  • Posts: 12860
Re: Quadrature Rotary encoder
« Reply #13 on: September 01, 2017, 06:47:06 am »
Thanks for the feedback.

I could do that, and, if one was building the externally clocked version, that would leave enough flipflops for a second QEI interface in the same chip. Also, while I'm using TTL with far too many pins  >:D I could also switch to 74HC154 4 to 16 line decoders.  That would get the chip count down to 2.5 per QEI. and then all you need to do is add some up/down counters, tristate buffers and address decoding and you've got an old-skool (crappy) bus mouse interface.  8)

However I was sticking to 'vanilla' 14 pin 74xx series logic + the LTspice 74HCT library (+symbols) I'm using doesn't have 74xx154 or 74xx574,  :-- and I certainly cant be ars3d to build it for real when I could just drop in a small PIC or AVR .  :horse:

It does require debouncing, otherwise in the real world, it increases the risk that it will occasionally loose counts due to metastability causing an invalid transition to be be decoded.  Your proposed 4MHz external clocked version would do well to use the spare flipflops in the 74xx574 to implement a multi-flop synchroniser for A and B, and assuming you haven't splurged on some Schmitt input buffers, the first stage of it could do with a feedback resistor from Q to D to add hysterisis.

Also you may have noticed the text 'Self Clocking Option' and the dotted line round the 74HCT86 clock pulse generator gilded turd.  Hopefully its obvious that its an either/or option - use the self-clocking furball of RC delays without a proper monostable or Schmitt trigger input in sight OR (my preference) delete that section and provide an external clock.  :-// Sorry I was lazy and didn't separate out the daggy bit and hook it up with net labels. :-[  Unfortunately LTspice doesn't have a 'cut here' scissors symbol!  :-DD
« Last Edit: September 01, 2017, 07:13:12 am by Ian.M »
 

Offline bson

  • Supporter
  • ****
  • Posts: 2270
  • Country: us
Re: Quadrature Rotary encoder
« Reply #14 on: September 03, 2017, 12:31:42 am »
Detect change on the sine, direction on the cosine.  If you feed it into a  bidirectional counter you could clock it on A, either rising or falling edge, and use B for the counting direction.  This is exactly how you'd do it in software: interrupt on A, read B to determine direction.  Obviously you need to debounce it if needed - which in software means leaving the interrupt disabled for the debounce interval (aka rearming delay).  In hardware it means RC.
« Last Edit: September 03, 2017, 12:33:40 am by bson »
 

Offline exe

  • Supporter
  • ****
  • Posts: 2562
  • Country: nl
  • self-educated hobbyist
Re: Quadrature Rotary encoder
« Reply #15 on: September 23, 2018, 04:50:37 pm »

Here's a C implementation of the classic 4 bit QEI state machine for reference:

Sorry for ressurecting old thread, just wanted to say thanks for the code. Here is what I ended up (removed switch/case to states that do not change counter, fixed some minor typos):
Code: [Select]
class QEI {
public:
    ioportid_t port;
    u32 pad1;
    u32 pad2;
    u8 state = 0;
    u16 count = 0;
    u16 value = 0;

    QEI(ioportid_t _port, u32 _pad1, u32 _pad2)
    : port(_port), pad1(_pad1), pad2(_pad2) {
        palSetPadMode(port, pad1, PAL_MODE_INPUT_PULLUP);
        palSetPadMode(port, pad2, PAL_MODE_INPUT_PULLUP);
    }
    int scan() {
        // idea from
        // [url]https://www.eevblog.com/forum/projects/quadrature-rotary-encoder/msg1291497/#msg1291497[/url]

        bool pad1_state = palReadPad(port, pad1);
        bool pad2_state = palReadPad(port, pad2);

        state = (state << 2) & 0b1111;
        if (pad1_state) { state |= 0b01; }
        if (pad2_state) { state |= 0b10; }

        switch(state) {
            // Forward
            case 0b0010:
            case 0b1011:
            case 0b1101:
            case 0b0100:
                count++;
                break;

            // Reverse
            case 0b0001:
            case 0b0111:
            case 0b1110:
            case 0b1000:
                count--;
                break;
        }

    if (count % 4 == 0) {
        value = count / 4;
    }

    return value;
    }
};
 

Offline OM222O

  • Frequent Contributor
  • **
  • Posts: 768
  • Country: gb
Re: Quadrature Rotary encoder
« Reply #16 on: September 23, 2018, 05:54:30 pm »
I think I have a fairly simple solution for you  ;D

You need to get a quad XOR gate chip. It will be used to detect the edge both rising and falling edge of one of the phases. This can be used as a trigger (clock) signal to D flip flop.

You need some additional gates to work out the direction. for example if (A is High and B is low) or (A is low and B is high) (which is basically another XOR of A and B) you're moving forward. the output of the the logic that determines the direction, can be fed to the data input of the flip flop. then you have both your clock and direction signals and you can do the switching based on that.I'm gonna quickly make the circuit diagram if my explanation is confusing.
« Last Edit: September 23, 2018, 06:16:48 pm by OM222O »
 

Offline OM222O

  • Frequent Contributor
  • **
  • Posts: 768
  • Country: gb
Re: Quadrature Rotary encoder
« Reply #17 on: September 23, 2018, 06:32:58 pm »
Ok, here is the simulation:
http://tinyurl.com/y7a56zo5

As you can see, phase B is offset by -90 degrees and the output of the D flip flop is constantly HIGH.
If you change phase B to be offset by +90 degrees (change of direction) the output of the flip flop would be constantly low. You can change that by double clicking on the "CLK" next to "PHASE B" text and writing the offset value as you desire.

You can also get double the clock frequency if you use the rest of the 2 XOR gates but try this first and see if it works for your application. I'll post the other circuit simulation as well.
 

Offline OM222O

  • Frequent Contributor
  • **
  • Posts: 768
  • Country: gb
Re: Quadrature Rotary encoder
« Reply #18 on: September 23, 2018, 06:42:38 pm »
And here is the final circuit simulation with double the clock frequency:
http://tinyurl.com/y9253f45

Note that if you connect the phases backwards, you can switch the direction output. i.e: clockwise rotation would be HIGH in one case, and if you switch the phases, it would be LOW in the other case.

I hope you found this useful and it's not too confusing for you. it's basically 2 chips: a quad XOR and a D flip flop with a resistor and a capacitor which is as basic as you can get.

If you're rotating the encoder really fast, try decreasing the value of the resistor and capacitor to lower the trigger pulse ON time. you should test it in your application with your specific use case and see how low of a value you can get away with.
 

Online RoGeorge

  • Super Contributor
  • ***
  • Posts: 6203
  • Country: ro
Re: Quadrature Rotary encoder
« Reply #19 on: September 23, 2018, 07:11:40 pm »
LS7183 or LS7184

Online MarkF

  • Super Contributor
  • ***
  • Posts: 2550
  • Country: us
Re: Quadrature Rotary encoder
« Reply #20 on: September 23, 2018, 09:51:52 pm »
Here is a circuit I found online a while back that may be useful. 
I never wired it up.  So, I don't know how well it works.

   
« Last Edit: September 26, 2018, 03:05:03 am by MarkF »
 

Offline chris_leyson

  • Super Contributor
  • ***
  • Posts: 1541
  • Country: wales
Re: Quadrature Rotary encoder
« Reply #21 on: February 16, 2022, 09:59:30 am »
The state machine approach works well, for example https://chome.nerpa.tech/mcu/reading-rotary-encoder-on-arduino/
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf