Go Down

Topic: Rotary encoders, 74LS14's and 74LS74's (Read 6 times) previous topic - next topic

neema_t

#15
May 16, 2011, 11:42 pm Last Edit: May 16, 2011, 11:44 pm by neema_t Reason: 1

The best way to get data on all four edges of the quadrature signal is to use this circuit:-
http://www.thebox.myzen.co.uk/Workshop/Rotary_Max.html


I've just built that in a simulator and it seems to work perfectly, I don't know why I didn't try that the first time I read that post... Your site is great, thank you for sharing! I'll be sure to let you know if it works in real life, too, but until I've gotten the parts I'll just carry on with the 7474.

Thanks again!

(edit: In your article you say to interface the counter's output with the Arduino using an input shift register, will a 4021 PISO shift register do the job?)

Grumpy_Mike

Quote
will a 4021 PISO shift register do the job?

Yes anything that will get those bits in will do.

midnightcruise

I was trying to use the original schematic posted by Grumpy Mike but found the pin numbers were wrong...  Here is the schematic as I have it working with an arduino.


Grumpy_Mike

Thanks, there are two pinouts available on the 7474 chips and my original diagram used the alternative origional pinout for the chip.

MarkT

Shouldn't that circuit be updated to use 74HC14 and 74HC74's ?
[ I won't respond to messages, use the forum please ]

midnightcruise

Thanks for the circuit Grumpy Mike... it does work great to simplify encoder input for my UI.

BTW the pin-outs are the same for the HC parts so here is the updated drawing:


dc42

#21
Aug 09, 2011, 12:19 pm Last Edit: Aug 09, 2011, 07:39 pm by dc42 Reason: 1
Personally, I don't use extra ICs for connecting rotary encoders to the Arduino. They're just not necessary. Used properly, these encoders don't need to be debounced either.

To connect a single rotary encoder, connect its centre pin to ground and the 2 outer pins to Arduino pins configured as inputs with pullup enabled. If you use pins 2 & 3 on a Uno, you can have an interrupt generated when the encoder moves, saving the need for polling it.

To connect 2 encoders, duplicate this arrangement (4 Arduino pins needed).

To connect N > 3 encoders without using 2N pins, connect each centre pin of an encoder to its own Arduino output pin. The left pins of the encoders each connect to the cathode of a signal diode (1N4148 or similar), the anodes being commoned and connected to an Arduino input pin with pullup enabled. Same arrangement for the right pins but different Arduino input pin. Total pins needed = N + 2 for N encoders.

Here's the code I use for the encoder:

Code: [Select]
class RotaryEncoder {
 unsigned int state;
 int pin0, pin1;
 int ppc;
 int change;
 static RotaryEncoder *encoderUsingInterrupts;  

 unsigned int readState() {
   return (digitalRead(pin0) == HIGH ? 1u : 0u) | (digitalRead(pin1) == HIGH ? 2u : 0u);
 }

 static void interruptPoll() {
   if (RotaryEncoder::encoderUsingInterrupts != 0) {
     RotaryEncoder::encoderUsingInterrupts->poll();
   }
 }

public:
 RotaryEncoder(int p0, int p1, int pulsesPerClick) :
 pin0(p0), pin1(p1), ppc(pulsesPerClick), change(0), state(0) {
 }

 void init() {
   pinMode(pin0, INPUT);
   pinMode(pin1, INPUT);
   digitalWrite(pin0, 1);
   digitalWrite(pin1, 1);
   change = 0;
   state = readState();
   if ((pin0 == 2 && pin1 == 3) || (pin0 == 3 && pin1 == 2)) {
     RotaryEncoder::encoderUsingInterrupts = this;
     attachInterrupt(0, interruptPoll, CHANGE);
     attachInterrupt(1, interruptPoll, CHANGE);
   }
 }

 void poll() {
   static int tbl[16] = {
     0, +1, -1, 0,  -1, 0, 0, +1,  +1, 0, 0, -1,  0, -1, +1, 0   };
   unsigned int t = readState();
   change += tbl[(state << 2) | t];
   state = t;
 }

 int getChange() {
   int r;
   noInterrupts();
   if (change >= ppc) {
     r = change/ppc;
   }
   else if (change <= -ppc) {
     r = -((-change)/ppc);
   }
   else {
     r = 0;
   }
   change -= (r * ppc);
   interrupts();
   return r;
 }
};

RotaryEncoder *RotaryEncoder::encoderUsingInterrupts = 0;


Then declare an encoder like this:

Code: [Select]
RotaryEncoder encoder(encoderPin1, encoderPin2, 4);  

and call encoder.init() in setup(). If you're not using a single encoder connected to pins 2 and 3, you'll need to call encoder.poll() every millisecond or so. For 3 or more encoders connected with diodes, poll each encoder in turn with its own output pin set low and the output pins for the other encoders set high.
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Grumpy_Mike

Quote
I don't use extra ICs for connecting rotary encoders to the Arduino. They're just not necessary. Used properly, these encoders don't need to be debounced either.

I would totally disagree with you. True optical encoders don't bounce but contact ones do. Your code will miss some bouncing pulses. My circuit was developed for a situation where I couldn't afford to miss a pulse. Maybe you experience of different makes of encoders is limited.

It would be good if you could modify the post, select the code and hit the # icon to get it into a box.

dc42

#23
Aug 09, 2011, 07:36 pm Last Edit: Aug 09, 2011, 07:41 pm by dc42 Reason: 1
Yes of course the contacts bounce, but if you use use the fact that the encoder is outputting Gray code and monitor all changes in the state of the contacts (as my code does), then a bounce just looks like the encoder advanced a quarter click, went back again, then advanced again - rather than advancing a quarter click in one go. If you poll the encoder very quickly then your application might see this, but it typically doesn't matter because the final result is the same. In the unlikely event that it makes a difference to your app, you can add software debounce to my code (I originally included it but removed it). OTOH if you use the make or break of one of the contacts as a clock to sample the other, then you certainly need to debounce the contact you are using as the clock.

Thanks for the hint about # for code - I hadn't spotted that.
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Go Up