rotary encoder help!

Hey All-
I'm a Noob trying to figure out how to read a rotary encoder. I'm using a Bourns ECW1J-B24-BC0024L digital encoder from Digi-key. The application i'll be using it for requires it to register at about 35RPM, and I'll be (hopefully) using encoder data to figure out where an un-connected linear actuator should be based on full and partial revolutions counted by the encoder.

I've copied one of the sets of code from the playground, hooked up the wiring including 1.5kOhm resistors between each of the encoder leads and the Arduino. I'm getting consistently odd numbers that seem to fluctuate and don't respond properly at all to me twisting the encoder. I've attached a photo of my breadboard setup below, and the code I'm using. Any suggestions would be appreciated.

#define encoder0PinA 2

#define encoder0PinB 3

volatile unsigned int encoder0Pos = 0;

void setup() {

  pinMode(encoder0PinA, INPUT); 
  pinMode(encoder0PinB, INPUT); 

// encoder pin on interrupt 0 (pin 2)

  attachInterrupt(0, doEncoderA, CHANGE);

// encoder pin on interrupt 1 (pin 3)

  attachInterrupt(1, doEncoderB, CHANGE);  

  Serial.begin (9600);

}

void loop(){ //Do stuff here }

void doEncoderA(){

  // look for a low-to-high on channel A
  if (digitalRead(encoder0PinA) == HIGH) { 

    // check channel B to see which way encoder is turning
    if (digitalRead(encoder0PinB) == LOW) {  
      encoder0Pos = encoder0Pos + 1;         // CW
    } 
    else {
      encoder0Pos = encoder0Pos - 1;         // CCW
    }
  }

  else   // must be a high-to-low edge on channel A                                       
  { 
    // check channel B to see which way encoder is turning  
    if (digitalRead(encoder0PinB) == HIGH) {   
      encoder0Pos = encoder0Pos + 1;          // CW
    } 
    else {
      encoder0Pos = encoder0Pos - 1;          // CCW
    }
  }
  Serial.println (encoder0Pos, DEC);          
  // use for debugging - remember to comment out

}

void doEncoderB(){

  // look for a low-to-high on channel B
  if (digitalRead(encoder0PinB) == HIGH) {   

   // check channel A to see which way encoder is turning
    if (digitalRead(encoder0PinA) == HIGH) {  
      encoder0Pos = encoder0Pos + 1;         // CW
    } 
    else {
      encoder0Pos = encoder0Pos - 1;         // CCW
    }
  }

  // Look for a high-to-low on channel B

  else { 
    // check channel B to see which way encoder is turning  
    if (digitalRead(encoder0PinA) == LOW) {   
      encoder0Pos = encoder0Pos + 1;          // CW
    } 
    else {
      encoder0Pos = encoder0Pos - 1;          // CCW
    }
  }

}

No photo?

wiring including 1.5kOhm resistors between each of the encoder leads and the Arduino.

No don't need that unless you have a capacitor to do debounce.

Thanks Mike.
I pulled the resistors, didn't help. The photo isn't showing up for you? I just checked it from a separate computer.

Hmmm.

Still no photo

hopefully this will work.

Imgur

I think you need to activate the internal software pull-up resistors for both pins 2 & 3.

pinMode(pin, INPUT); // set pin to input
digitalWrite(pin, HIGH); // turn on pullup resistors

Also you are sure to get some contact bounce with that mechanical encoder. I tried one that worked somewhat but didn't get stable performance until I switched to an optical encoder.

Lefty

OK got the photo, as was said you need pull up resistors either externally or internally.
If they are external you can also use capacitors to debounce the circuit. But it is likely that there will be to much bounce at the speed you want to go at.

May I suggest using simpler code: H I F I D U I N O: Arduino Code for Rotary Encoder

Ok thanks everyone. I'm going to try the pull-up resistor code, also try 1.5k resistors with capacitors (in series??? encoder->resistor->capacitor->arduino?), will order an optical encoder to use instead, and will try the simpler code that glt suggested.

Hopefully one of those things will work!!!

I'll let you know when I go through all those options what worked and what didn't.

I really appreciate all of your suggestions.

(in series??? encoder->resistor->capacitor->arduino?)

No.

+5v -> resistor -> encoder + arduino -> capacitor -> ground

I don't seem to have the option of posting images so here is a link to my Flickr page where there is an example of why you need to debounce a mechanical encoder output.

Imgur

I don't seem to have the option of posting images so here is a link to my Flickr page where there is an example of why you need to debounce a mechanical encoder output.

Excellent picture of what contact bounce looks like. It's exasperated by the fact of when using a mechanical encoder with a Interrupt routine you can't use a delay() function to do the standard 'fix' for contact bounce, you have to either code in do nothing statements. All in all I think eliminating contact bounce externally with either hardware filters or optical switching is the best solution for demanding encoder handling tasks.

Lefty

Unfortunately the optical solution costs several times what a good mechanical encoder does.

If your shaft speed is slow enough, e.g. < around 10 msec per step, you can create a 1 msec interrupt from one of the unused timers and decode the switch state via a 4-state machine in the ISR(). If your switch bounces 4msec, you would have a clean decode in about 8 msec.

I have some code for another processor that I can probably illustrate in Arduino if anyone is interested.

I have used this to successfully convert the output of a rotary encoder into step and direction signals. These are much easier to read from the arduino and it contains some debouncing as well.

1 Like

Thanks very much everyone. I'll keep you posted on my progress. Other areas of work have been busy so I haven't had much time to spend on this yet.

Grumpy_Mike, can you please explain that schematics? I'm a little confused with "triangle" part, what are they?

They are Schmitt trigger inverters. In the chip 74LS14 there are six of them.

They output the logic inverse of the input, the Schmitt trigger bit adds some hysteresis so you don't get oscillation when the input voltage is close to the threshold voltage of being 0 or 1.
Hope that helps