how to read an optical rotary encoder

I am wanting to use an optical rotary encoder where I previously was using a mechanical encoder to move a servo. My code workes good with the mechanical encoder, moving it in both directions within a given range. The optical encoder will only move the servo in one direction however.

this is the data sheet for the optical encoder ENT1J-D28-L00128L

Here is the code I am using.

Servo throttleServo; // Define throttle Servo
int servoPos = 30;    // Initial power up “servo position”
int moveServoAmount = 12;    // move the servo 10 degrees per 1/24 pulse
const int pin_A = 3;  // pin 15
const int pin_B = A2;  // pin 14
unsigned char encoder_A;
unsigned char encoder_B;
unsigned char encoder_A_prev=0;
void throttleSetup()  {
  throttleServo.attach(12); // servo on digital pin 12
  throttleServo.write(30);
  pinMode(pin_A, INPUT);
  digitalWrite(pin_A, HIGH);// turn on pullup resistor
  pinMode(pin_B, INPUT);
  digitalWrite(pin_B, HIGH);// turn on pullup resistor
} 

void throttleLoop()  {

  encoder_A = digitalRead(pin_A); // Read encoder pins
  encoder_B = digitalRead(pin_B);
  if((!encoder_A) && (encoder_A_prev)){
    // A has gone from high to low
    if(encoder_B) {
      // B is high so clockwise
      // increase the throttle, dont go over 255
      if(servoPos + moveServoAmount <= 220) servoPos += moveServoAmount;
    }
    else {
      // B is low so counter-clockwise
      // decrease the throttle, dont go below 20
      if(servoPos - moveServoAmount >= 20) servoPos -= moveServoAmount;
    }
  }
  encoder_A_prev = encoder_A;     // Store value of A for next time
  // set the new location of servo:
  throttleServo.write(servoPos);
}
const int pin_A = 3;  // pin 15
const int pin_B = A2;  // pin 14
unsigned char encoder_A;
unsigned char encoder_B;
unsigned char encoder_A_prev=0;

Comments are good, when they match the code. They look pretty dumb when they don't.

http://snippets-r-us.com might be able to help you. Here, we need to see all of your code.

You only check for a falling edge of pin A, check both edges to get a higher resolution and better accuracy because a vibration on the encoder won't affect your results.

i figured it out, crossed 2 wires in my connector.

Could you give me an idea on how to include the rising edge in my code? Thanks,

Here is the Encoder part of the code

void throttleLoop()  {

  encoder_ThrottleUp = digitalRead(pin_ThrottleUp); // Read encoder pins
  encoder_ThrottleDn = digitalRead(pin_ThrottleDn); // Read encoder pins
  if((!encoder_ThrottleUp) && (encoder_ThrottleUp_prev)){
    // A has gone from high to low
    if(encoder_ThrottleDn) {
      // B is high so clockwise
      // increase the throttle, dont go over 220
      if(servoPos + moveServoAmount <= 220) servoPos += moveServoAmount;
    }
    else {
      // B is low so counter-clockwise
      // decrease the throttle, dont go below 20
      if(servoPos - moveServoAmount >= 20) servoPos -= moveServoAmount;
    }
  }
  encoder_ThrottleUp_prev = encoder_ThrottleUp;     // Store value of ThrottleUp for next time
  // set the new location of servo:
  throttleServo.write(servoPos);
}

Here is the whole code.

#include <Bounce.h>
#include <Servo.h>
code]

void setup(){
buttonSetup();
throttleSetup();
}

void loop(){
throttleLoop();
cruiseButtonLoop();

}

Servo throttleServo; // Define throttle Servo
int servoPos = 30; // Initial power up “servo position”
int moveServoAmount = 2; // move the servo 2 degrees per 1/125 pulse
const int pin_ThrottleUp = 4;
const int pin_ThrottleDn = A2; // pin 14
unsigned char encoder_ThrottleUp;
unsigned char encoder_ThrottleDn;
unsigned char encoder_ThrottleUp_prev=0;

// set pin numbers:
const int buttonPin = 11; // the number of the button pin
const int buttonPin2 = 10;
const int buttonPin3 = 9;
const int buttonPin4 = 8;

long debounceDelay = 50; // the debounce time; increase if the output flickers

//Debounce objects
// Instantiate a Bounce object with a 5 millisecond debounce time
Bounce cruiseUp = Bounce(buttonPin, debounceDelay);
Bounce cruiseDn = Bounce(buttonPin2, debounceDelay);
Bounce brakeReleaseToThrottle = Bounce(buttonPin4, debounceDelay);
Bounce clutchReleaseToThrottle = Bounce(buttonPin3, debounceDelay);

void throttleSetup() {
throttleServo.attach(12); // servo on digital pin 12
throttleServo.write(30);
pinMode(pin_ThrottleUp, INPUT);
digitalWrite(pin_ThrottleUp, HIGH);// turn on pullup resistor
pinMode(pin_ThrottleDn, INPUT);
digitalWrite(pin_ThrottleDn, HIGH);// turn on pullup resistor
}

void throttleLoop() {

encoder_ThrottleUp = digitalRead(pin_ThrottleUp); // Read encoder pins
encoder_ThrottleDn = digitalRead(pin_ThrottleDn); // Read encoder pins
if((!encoder_ThrottleUp) && (encoder_ThrottleUp_prev)){
// A has gone from high to low
if(encoder_ThrottleDn) {
// B is high so clockwise
// increase the throttle, dont go over 220
if(servoPos + moveServoAmount <= 220) servoPos += moveServoAmount;
}
else {
// B is low so counter-clockwise
// decrease the throttle, dont go below 20
if(servoPos - moveServoAmount >= 20) servoPos -= moveServoAmount;
}
}
encoder_ThrottleUp_prev = encoder_ThrottleUp; // StAof ThrottleUp for next time
// set the new location of servo:
throttleServo.write(servoPos);
}

void buttonSetup(){
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
pinMode(buttonPin2, INPUT);
pinMode(buttonPin3, INPUT);
pinMode(buttonPin4, INPUT);
}

void cruiseButtonLoop(){
//Update debounce tool
cruiseUp.update();
cruiseDn.update();
brakeReleaseToThrottle.update();
clutchReleaseToThrottle.update();
//Do not need to update these here are they are not used
//bouncer3.update();
//bouncer4.update();
if (cruiseUp.read() == HIGH)
{
cruiseLoop(); //Enters button control loop
}
if (cruiseDn.read() == HIGH)
{
cruiseLoop(); //Enters button control loop
}
else if (brakeReleaseToThrottle.read() == HIGH)
{
servoPos = 30;
}
}

/**

  • If button control is enabled, loop and handle control buttons
  • If exit buttons (To return to pot control) are pressed, exit loop and return
  • to pot control
    */
    void cruiseLoop(){
    servoPos = throttleServo.read(); //reads current servo location
    int btnControlEnabled = 1; //If button control is enabled this equals 1, else it equals 0
    while(btnControlEnabled == 1)
    {
    //Update all debounce tools
    cruiseUp.update();
    cruiseDn.update();
    brakeReleaseToThrottle.update();
    clutchReleaseToThrottle.update();
    if (cruiseUp.read() == HIGH)
    {
    throttleServo.write(servoPos + 1); //Add 2 degrees to servo position for increased motor rpm
    servoPos = throttleServo.read();
    delay(40); //allows time for switch ro reset
    }
    //If first button not pressed, check the next…
    else if (cruiseDn.read() == HIGH)
    {
    throttleServo.write(servoPos - 1); //Subtract 2 degrees to servo position for decreased motor rpm
    servoPos = throttleServo.read(); //Read new servo position
    delay(40); //allows time for switch ro reset
    }
    else if (clutchReleaseToThrottle.read() == HIGH)
    {
    servoPos = 30;
    btnControlEnabled = 0; //Set loop exit condition
    throttleLoop();
    }
    else if (brakeReleaseToThrottle.read() == HIGH)
    {
    servoPos = 30;
    btnControlEnabled = 0; //Set loop exit condition
    throttleLoop();
    }
    }
    }code]

Could you give me an idea on how to include the rising edge in my code?

Change your start condition:

  if((!encoder_ThrottleUp) && (encoder_ThrottleUp_prev)){

to a condition for both edges:

  if(encoder_ThrottleUp != encoder_ThrottleUp_prev) {
    if (encoder_ThrottleUp) {
      // rising edge
    } else {
      // falling edge
    }
}

I am new to this programming stuff like many on here. This sample will red the falling and rising edge? I get how the encoder works and what this means but I don't get the code provided at all. Could I please get some explanation? Thanks

An explanation of rotary encoders is found here: Rotary encoder - Wikipedia. Look for "Incremental rotary encoder" to get a description of your type of encoder.

As I said, I understand how the Encoder works just fine. I dont understand the suggestion on the code and how it is reading the up tick and how to include it into what I already have.

I tried it this way as suggested but it does not work.

void throttleLoop()  {

  encoder_ThrottleUp = digitalRead(pin_ThrottleUp); // Read encoder pins
  encoder_ThrottleDn = digitalRead(pin_ThrottleDn); // Read encoder pins
  if(encoder_ThrottleUp != encoder_ThrottleUp_prev) {
    if (encoder_ThrottleUp) {
      // rising edge
      if(servoPos + moveServoAmount <= 220) servoPos += moveServoAmount;
    }
    else {
      // B is low so counter-clockwise
      // decrease the throttle, dont go below 20
      if(servoPos - moveServoAmount >= 20) servoPos -= moveServoAmount;
    }
  }
  encoder_ThrottleUp_prev = encoder_ThrottleUp;     // Store value of A for next time
  // set the new location of servo:
  throttleServo.write(servoPos);

but it does not work.

The code does something. What does it do?

You want the code to do something. What does it do that you don't want? What does it not do that you do want?

You have to react on the rising or falling edges:

if(encoder_ThrottleUp != encoder_ThrottleUp_prev) {
    if (encoder_ThrottleUp) {
      // rising edge
      if (encoder_ThrottleDn) {
        // rotated forward, do something
      } else {
        // rotated backward, do something
      }
    } else {
      // falling edge
      if (encoder_ThrottleDn) {
        // rotated backward, do something
      } else {
        // rotated forward, do something
      }
    }
}

If you don’t care which step it was, it’s even shorter:

if(encoder_ThrottleUp != encoder_ThrottleUp_prev) {
    if (encoder_ThrottleUp == encoder_ThrottleDn) {
      // rotated forward, do something
    } else {
      // rotated backward, do something
    }
}

Thank you again, I have not been able to test this yet but I am starting to understand. I don’t get one thing though, maybe it is a typo?.

On the first one of Throttle Dn
if (encoder_ThrottleDn)

if(encoder_ThrottleUp != encoder_ThrottleUp_prev) {
    if (encoder_ThrottleUp) {
      // rising edge
     if (encoder_ThrottleDn) {
        // rotated forward, do something
      } else {
        // rotated backward, do something
      }
    } else {
      // falling edge
      if (encoder_ThrottleDn) {
        // rotated backward, do something
      } else {
        // rotated forward, do something
      }
    }
}

I don't see the type. Where exactly is your understanding problem?