using a rotary encoder

Status
Not open for further replies.

nagual

Well-known member
hello,

This thread is about using a rotary encoder with Teensy 3.1

m8-aMqwQUlfEHTDZ0HtQhsA.jpg

This topic at the Arduino forum may be of help:
http://forum.arduino.cc/index.php?topic=242356.0
 
Last edited:
The only 5 pin rotary encoders I have encountered only used three for 'encoder' part and the other two pins were for a momentary push button in the shaft; I haven't seen one that names a 'CLK' signal etc; having said that, I have modified the code you posted with the expectation that my modifications increase your chances of seeing activity in the Serial Monitor.
Code:
/* Encoder Library - NoInterrupts Example
 * http://www.pjrc.com/teensy/td_libs_Encoder.html
 *
 * This example code is in the public domain.
 */

// If you define ENCODER_DO_NOT_USE_INTERRUPTS *before* including
// Encoder, the library will never use interrupts.  This is mainly
// useful to reduce the size of the library when you are using it
// with pins that do not support interrupts.  Without interrupts,
// your program must call the read() function rapidly, or risk
// missing changes in position.
#define ENCODER_DO_NOT_USE_INTERRUPTS
#include <Encoder.h>

// Beware of Serial.print() speed.  Without interrupts, if you
// transmit too much data with Serial.print() it can slow your
// reading from Encoder.  Arduino 1.0 has improved transmit code.
// Using the fastest baud rate also helps.  Teensy has USB packet
// buffering.  But all boards can experience problems if you print
// too much and fill up buffers.

// Change these two numbers to the pins connected to your encoder.
//   With ENCODER_DO_NOT_USE_INTERRUPTS, no interrupts are ever
//   used, even if the pin has interrupt capability

#define ENC1 0
#define ENC2 1


Encoder myEnc(ENC1, ENC2);
int led = 14;

//   avoid using pins with LEDs attached

void setup() {
  pinMode(ENC1,INPUT_PULLUP);
  pinMode(ENC2,INPUT_PULLUP);
  Serial.begin(9600);
  while(!Serial); // wait for user to connect...
  Serial.println("Basic NoInterrupts Test:");
  pinMode(led, OUTPUT);  
}

long position  = -999;

elapsedMillis dbad;
uint8_t led_state=0;

void loop() {
  long newPos = myEnc.read();
  if (newPos != position) {
    position = newPos;
    Serial.println(position);
  }
  if(dbad>999)
  {
    dbad=0;
    led_state=1-led_state;
    digitalWrite(led,led_state);
  } // don't delay so much if you want encoder results without using interrupts...

  // With any substantial delay added, Encoder can only track
  // very slow motion.  You may uncomment this line to see
  // how badly a delay affects your encoder.
  //delay(50);
}
 
thank you very much for the code! I sorted the Serial Monitor issue in another thread.

It turns out that for this particular encoder, i think the GND and +3.3v need to be connected.
The CLK and the DT labelled contacts seem to like being plugged into Encoder's two pins.

The readout looks really imprecise though... pic below...

encoder choppy.JPG
 
did you have some kind of documentation about this encoder? I really don't understand why there's a CLK (clock) pin and DT (data?) pin on a rotary encoder without any logic.
I have several encoder laying around my lab, some has 4 pin, common ones are 3 pin but if there's a switch there's 2 pin more so I'm pretty sure that yours it's a standard 3 pin ( an A-ground-B plus Switch 1,2 ).
If it's a 3 pin standard encoder normally you don't need the positive.
The picture it's too small, there's any SMD resistor soldered on PCB?
 
did you have some kind of documentation about this encoder? I really don't understand why there's a CLK (clock) pin and DT (data?) pin on a rotary encoder without any logic.
I have several encoder laying around my lab, some has 4 pin, common ones are 3 pin but if there's a switch there's 2 pin more so I'm pretty sure that yours it's a standard 3 pin ( an A-ground-B plus Switch 1,2 ).
If it's a 3 pin standard encoder normally you don't need the positive.
The picture it's too small, there's any SMD resistor soldered on PCB?

I will try to connect the central pin of the encoder to ground (look the side of the encoder with 3 pins) and the remaining 2 to A and B (or ENC1 and ENC2)
 
Last edited:
Wire up as near exactly as described in that post as possible (do not connect '+' to 5V but instead to 3V3 pin on Teensy); change my 'INPUT_PULLUP' entries to 'INPUT' only; Try it with 'CLK' as 'A' and 'DT' as 'B', then other way around;

improvement?
 
thanks, i used this code and it jumps 4 numeric places every time the rotary encoder hits a 'detent' or bump.

how do you get a 3.3v pin?

Code:
/* Encoder Library - NoInterrupts Example
 * http://www.pjrc.com/teensy/td_libs_Encoder.html
 *
 * This example code is in the public domain.
 */

// If you define ENCODER_DO_NOT_USE_INTERRUPTS *before* including
// Encoder, the library will never use interrupts.  This is mainly
// useful to reduce the size of the library when you are using it
// with pins that do not support interrupts.  Without interrupts,
// your program must call the read() function rapidly, or risk
// missing changes in position.
#define ENCODER_DO_NOT_USE_INTERRUPTS
#include <Encoder.h>

// Beware of Serial.print() speed.  Without interrupts, if you
// transmit too much data with Serial.print() it can slow your
// reading from Encoder.  Arduino 1.0 has improved transmit code.
// Using the fastest baud rate also helps.  Teensy has USB packet
// buffering.  But all boards can experience problems if you print
// too much and fill up buffers.

// Change these two numbers to the pins connected to your encoder.
//   With ENCODER_DO_NOT_USE_INTERRUPTS, no interrupts are ever
//   used, even if the pin has interrupt capability

#define ENC1 0
#define ENC2 1


Encoder myEnc(ENC1, ENC2);
int led = 14;

//   avoid using pins with LEDs attached

void setup() {
  pinMode(ENC1,INPUT);
  pinMode(ENC2,INPUT);
  Serial.begin(9600);
  while(!Serial); // wait for user to connect...
  Serial.println("Basic NoInterrupts Test:");
  pinMode(led, OUTPUT);  
}

long position  = -999;

elapsedMillis dbad;
uint8_t led_state=0;

void loop() {
  long newPos = myEnc.read();
  if (newPos != position) {
    position = newPos;
    Serial.println(position);
  }
  if(dbad>999)
  {
    dbad=0;
    led_state=1-led_state;
    digitalWrite(led,led_state);
  } // don't delay so much if you want encoder results without using interrupts...

  // With any substantial delay added, Encoder can only track
  // very slow motion.  You may uncomment this line to see
  // how badly a delay affects your encoder.
  delay(2);
}
 
Last edited:
I know this is an old thread, but for anyone else who runs into issues, and since I am a rank amateur, I had to work my way through this issue too...

1) Find the data sheet. There are thousands and thousands of encoders out there, and they are all different. I have had ones with detents where the detent is one per pulse, and where the detents are one per four pulses. There are many permutations.

2) In the scenario like the encoder described, and using Paul's example code, I simply added a division by 4, so that it essentially only counted once at every detent, even though technically that was four pulses. Using the serial monitor and turning the encoder very slowly between detents, you can usually see if there are additional counts between the detents.

3) On a number of the mechanical encoders (as opposed to the optical ones) I found I had to add 0.1µF (104) capacitors between the common terminal and each of the channel pins, like this:

A --||--Common--||--B

4) It seems like every new encoder has a new issue to learn about.
 
It's fairly normal for an encoder to give four counts per detent. for example say a 24 detent encoder has 2 channels with 24 square waves out per revolution. Since the two square waves are 90 degrees out of phase, the teensy sees 4 edges per pulse. demodulating the quadrature signal, allows 4 times the encoder resolution, and the ability to determine direction.
When there are no detents, this is not a problem, and you get a finer resolution. with the detents, however, it means counting in steps of four, which needs to be dealt with throughout your code.

It would be a nice feature of the encoder library if you could pass it a decimate value or even a multiplier value so that it would handle quadrature or scaling at a lower level.
 
Last edited:
CLK and DATA are normal names for encoder signals. If you read DATA on the rising edge of CLK, it tells you whether you turned one detent left or right. CLK and DATA match up exactly with a flip-flop, or other digital circuitry.

High resolution readers like the encoder library can trigger or clock off of all four rising and falling signal edges and get higher resolution counts from all four quadrants of the quadrature cycle than a plain copy-data-on-clock-rise interpretation.
 
Status
Not open for further replies.
Back
Top