Rotary Encoder Accuracy

Hi All,

I am using a DC motor with a rotary encoder and am having problems with the accuracy of it.

The Setup:

Arduino Uno
Pololu Dual TB9051FTG Motor Shield
Pololu 131:1 Metal Gearmotor 37Dx73L mm 12V with 64 CPR Encoder (Helical Pinion)

The Challenge:

The code is running, the motor is turning, the motor stops when it is suppose to…technically. It stops when the encoder reaches the proper count but I can tell from the amount of rotations of the output shaft that it is turning too many times. When I output the encoder count it is repeating the same numbers a bunch at the beginning and gradually gets more accurate but is still missing numbers in the count. The output looks like this:

Number: 1500
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
2
2
2
2
2
2
2
2
2
2
2
3
3
3
3
4
4
4
4
4
4
5
5
6
6
6
6
6
6
6
7
8
8
8
8
8
9
10
10
10
10
10
10
10
11
12
12
12
12
12
12
12
12
12
12
12
14
14
14
15
15
15
15
15
15
15
15
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
17
18
19
19
19
19
19
19
19
19

I have taken a look at some of the encoder posts on the forum from Robin2 and Nick Gammon but I am not fully understanding how they work and don’t want to just be dropping code snippets in. I’d like some input on how I am attaching the interrupts, how I am placing the interrupt code, and how I have the ISR setup. I assume that optimizing these pieces could fix some of the problems I am seeing. Any help would be appreciated!

Code below.

The Code:

#include "DualTB9051FTGMotorShield.h"
DualTB9051FTGMotorShield md;

#define CCW 0
#define CW 1

const byte encoder1 = 2;
const byte encoder2 = 3;
boolean dialDirection = CW;
volatile unsigned int encoder = 0;
volatile unsigned int copyOfEncoder = 0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);  //Initialize the serial connection
  pinMode(encoder1, INPUT_PULLUP); //Set the pins the encoder is connected to as inputs
  pinMode(encoder2, INPUT_PULLUP); //Set the pins the encoder is connected to as inputs
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);
  attachInterrupt(0, encoderISR, CHANGE);
  md.init(); // Initialize the motor driver
  md.enableDrivers();
  turn(1500);
}

void loop() {
  // put your main code here, to run repeatedly:

}

void turn(int number) {
  Serial.println((String)"Number: " + number);
  while (copyOfEncoder <= number) {
    md.setM1Speed(400);
    noInterrupts();
    copyOfEncoder = encoder;
    interrupts();
    Serial.println(copyOfEncoder);
  }
  md.setM1Speed(0);

}

void encoderISR() {
  if (dialDirection == CW) {
    if (bitRead(PORTD, 2) == bitRead(PORTD, 3) ) {
      encoder += 1;
    }
  } else if (dialDirection == CCW) {
    if (bitRead(PORTD, 2) == bitRead(PORTD, 3) ) {
      encoder -= 1;
    }
  }
}

I recommend to try a good encoder library. This is the best one.

Also, avoid use of Strings. They are completely unnecessary and on AVR-based Arduinos, cause memory problems and unpredictable crashes.

It is completely impractical to print the encoder count in each iteration of a WHILE loop - the loop runs much too fast. I suspect it would be impractical even to print the value every time the encoder value changes. Just print the value when the motor stops.

Also, you should have the reading of the enocoder separate from the control of the motor so that the encoder keeps reading after the motor is told to stop.

How many pulses per second does the encoder produce?

...R

@jremington

Thanks for the link to the library. I have seen it before and it does look useful but reading through the documentation its not super clear to me how to implement it. I see how you import the library, how you include the call to the library, how you set the pins for the encoder… and then I kind of get lost…

I think I setup a “counter” variable and then assign the .read() of the myEnc that I initialized…?

and then do I just use that in place of any ISR and counter code I am using now? Any advice would be great as this seems like a simplified approach.

@Robin2

Thanks for the notes on separating out the encoder counting from the motor operation. It makes sense to have it be able to count after the motor is suppose to stop. Also, makes sense to not print out the count in every loop. I do have a question about that part though. If we aren’t able to print out the count every time how do we know if it is counting the same number multiple times, like I am seeing above?

Also, here is the specs for the motor and encoder.
It will do 8400 counts per revolution at the output shaft.

I tried separating out the counter code from the motor control and moved the println for the counter for when the motor stops but it doesn’t seem to count at all now. Code below:

#include "DualTB9051FTGMotorShield.h"
DualTB9051FTGMotorShield md;

#define CCW 0
#define CW 1

const byte encoder1 = 2;
const byte encoder2 = 3;
boolean dialDirection = CW;
volatile unsigned int encoder = 0;
volatile unsigned int copyOfEncoder = 0;
volatile boolean fired;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);  //Initialize the serial connection
  pinMode(encoder1, INPUT_PULLUP); //Set the pins the encoder is connected to as inputs
  pinMode(encoder2, INPUT_PULLUP); //Set the pins the encoder is connected to as inputs
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);
  attachInterrupt(0, encoderISR, CHANGE);
  md.init(); // Initialize the motor driver
  md.enableDrivers();
  turn(1500);
}

void loop() {
  // put your main code here, to run repeatedly:
    if (fired)
    {
  noInterrupts();
  copyOfEncoder = encoder;
  interrupts();
  fired = false;
    }
}

void turn(int number) {
  Serial.println((String)"Number: " + number);
  while (copyOfEncoder <= number) {
    md.setM1Speed(400);
  }
  md.setM1Speed(0);
  Serial.println(copyOfEncoder);
}

void encoderISR() {
  if (dialDirection == CW) {
    if (bitRead(PORTD, 2) == bitRead(PORTD, 3) ) {
      encoder += 1;
    }
  } else if (dialDirection == CCW) {
    if (bitRead(PORTD, 2) == bitRead(PORTD, 3) ) {
      encoder -= 1;
    }
  }
  fired = true;
}

Any advice on how to proceed would be great.

You need to implement proper quadrature encoder logic. On every change the count must either increase or decrease, otherwise you'll misscount.

And you have to declare every global variable used in the ISR as volatile, not just some of them.

@MarkT Thanks for the notes!

I adjusted “boolean dialDirection = CW;” to be “volatile boolean dialDirection = CW;”. So I think I have captured all of the ISR variables as volatile now. Could you provide more info or clarification by what you mean as “proper quadratic encoder logic”? I thought I was capturing the encoder change in the ISR currently. Can you help me understand what I am missing? Appreciate any assistance you can offer! Updated code below:

#include "DualTB9051FTGMotorShield.h"
DualTB9051FTGMotorShield md;

#define CCW 0
#define CW 1

const byte encoder1 = 2;
const byte encoder2 = 3;
volatile boolean dialDirection = CW;
volatile unsigned int encoder = 0;
volatile unsigned int copyOfEncoder = 0;
volatile boolean fired;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);  //Initialize the serial connection
  pinMode(encoder1, INPUT_PULLUP); //Set the pins the encoder is connected to as inputs
  pinMode(encoder2, INPUT_PULLUP); //Set the pins the encoder is connected to as inputs
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);
  attachInterrupt(0, encoderISR, CHANGE);
  md.init(); // Initialize the motor driver
  md.enableDrivers();
  turn(1500);
}

void loop() {
  // put your main code here, to run repeatedly:
    if (fired)
    {
  noInterrupts();
  copyOfEncoder = encoder;
  interrupts();
  fired = false;
    }
}

void turn(int number) {
  Serial.println((String)"Number: " + number);
  while (copyOfEncoder <= number) {
    md.setM1Speed(400);
  }
  md.setM1Speed(0);
  Serial.println(copyOfEncoder);
}

void encoderISR() {
  if (dialDirection == CW) {
    if (bitRead(PORTD, 2) == bitRead(PORTD, 3) ) {
      encoder += 1;
    }
  } else if (dialDirection == CCW) {
    if (bitRead(PORTD, 2) == bitRead(PORTD, 3) ) {
      encoder -= 1;
    }
  }
  fired = true;
}

reading through the documentation its not super clear to me how to implement it.

The encoder library I linked comes with four different implementation examples. Please study them carefully for insight into how to use the library.

This one shows you how to avoid the problem pointed out by Robin2, i.e. printing every time through loop():

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

#include <Encoder.h>

// Change these two numbers to the pins connected to your encoder.
//   Best Performance: both pins have interrupt capability
//   Good Performance: only the first pin has interrupt capability
//   Low Performance:  neither pin has interrupt capability
Encoder myEnc(5, 6);
//   avoid using pins with LEDs attached

void setup() {
  Serial.begin(9600);
  Serial.println("Basic Encoder Test:");
}

long oldPosition  = -999;

void loop() {
  long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    Serial.println(newPosition);
  }
}

@jremington

Thanks for the note. I have previously and I am again examining the examples for the Encoder library. It is still not clear to me how to make use of the library in terms of using it start and stop the motor. Below is the latest test I tried. Any advise you can provide would be great!

#include <Encoder.h>
#include "DualTB9051FTGMotorShield.h"
DualTB9051FTGMotorShield md;
volatile long newPosition;

// Change these two numbers to the pins connected to your encoder.
//   Best Performance: both pins have interrupt capability
//   Good Performance: only the first pin has interrupt capability
//   Low Performance:  neither pin has interrupt capability
Encoder myEnc(2, 3);
//   avoid using pins with LEDs attached

void setup() {
  Serial.begin(115200);
  Serial.println("Basic Encoder Test:");
  md.init(); // Initialize the motor driver
  md.enableDrivers();
  turn(1500);
}

volatile long oldPosition  = -999;

void loop() {
  newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    Serial.println("Why isn't this happening?");
    oldPosition = newPosition;
    Serial.println(newPosition);
  }
}

void turn(int number) {
  Serial.print("Number: ");
  Serial.println(number);
  while (newPosition <= number) {
    md.setM1Speed(400);
  }
  md.setM1Speed(0);
  Serial.println(newPosition);
}

The encoder library just tells you the motor shaft position.

Please outline your goals with respect to motor control, and how knowledge of the motor shaft position will play a role.

If your goal is to have the motor drive to a certain output shaft position, most people end up using PID control algorithms. But that can be quite difficult, to impossible, if the gear train has significant backlash. In that case, the encoder belongs on the output shaft.

@jremington

Thanks for this! The goal is to be able to start and stop the motor on precise encoder counts. So turn the motor shaft this many encoder counts and stop it, change direction and go to a new encoder count. I know this is possible to do with this specific motor encoder combination but I haven’t been able to accomplish it accurately. Any advice would be great!

I know this is possible to do with this specific motor encoder combination

How do you know this?

I suggest to measure the gearbox backlash and tell us what it is, in encoder counts.

@jremington

How would you suggest measuring the motor backlash? Thanks!

GorillaDetective:
If we aren't able to print out the count every time how do we know if it is counting the same number multiple times, like I am seeing above?

It's not counting the same number multiple times, It is printing the same number because the number has not changed.

...R

@Robin2

Ah, that makes more sense! It doesn’t explain why the motor makes too many rotations though...Could it be that all the extra serial printing is throwing it off?

GorillaDetective:
@MarkT Thanks for the notes!

I adjusted "boolean dialDirection = CW;" to be "volatile boolean dialDirection = CW;". So I think I have captured all of the ISR variables as volatile now. Could you provide more info or clarification by what you mean as "proper quadratic encoder logic"? I thought I was capturing the encoder change in the ISR currently. Can you help me understand what I am missing? Appreciate any assistance you can offer! Updated code below:

Every transition must either increase or decrease the count. You still are not doing this, so you are not
counting transitions correctly, you are ignoring some. Better still learn how to work with state-transition
diagrams, they are very general and very useful in interfacing to the outside world in many situations.

Your code is only working with half the total transitions as you are only triggering on one of the signals,
its also possible to trigger on both of them and get twice the resolution.

@MarkT

Thanks for this! That makes sense. I think I am capturing all the transitions now…but the encoder count doesn’t seem to happen in the loop() like I would expect. I assume it has something to do with the while() loop I am running in the turn() function? Update code below:

#include "DualTB9051FTGMotorShield.h"
DualTB9051FTGMotorShield md;

#define encoder0PinA  2
#define encoder0PinB  3

volatile unsigned int encoder0Pos = 0;
volatile unsigned int copyOfEncoder = 0;

void setup() {
  Serial.begin(115200);  //Initialize the serial connection
  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);
  md.init(); // Initialize the motor driver
  md.enableDrivers();
  turn(1500);
}

void loop() {
  //Do stuff here
     if (encoder0Pos != copyOfEncoder) {
    copyOfEncoder = encoder0Pos;
    Serial.println(copyOfEncoder);
    }
}

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 turn(int number) {
  Serial.print("Number: ");
  Serial.println(number);
  while (copyOfEncoder <= number) {
    md.setM1Speed(400);
  }
  md.setM1Speed(0);
  Serial.print("Encoder Count at Stop: ");
  Serial.println(copyOfEncoder);
}

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
    }
  }
}

At the very least the code in loop() needs to be

void loop() {
  //Do stuff here
     noInterrupts();
        latestEncoderPos = encoder0Pos;
     interrupts();
     if (latestEncoderPos != copyOfEncoder) {
         copyOfEncoder = lastestEncoderPos;
         Serial.println(copyOfEncoder);
     }
}

I think if you have interrupts on both encoder pins you don't need CHANGE as that produces 2 interrupts for each pulse. I think RISING will be sufficient (assuming the pulse produces a HIGH).

...R

Thanks @Robin2!

It is counting the encoder ticks properly now. I included your loop() code, changed the attachInterrupt() to RISING, and I moved the while loop in the turn() function so it shuts off the motor rather than turns it on but the encoder count does not trigger the while loop. Any thoughts on why that would be? Updated code below:

#include "DualTB9051FTGMotorShield.h"
DualTB9051FTGMotorShield md;

#define encoder0PinA  2
#define encoder0PinB  3

volatile unsigned int encoder0Pos = 0;
volatile unsigned int copyOfEncoder = 0;
volatile unsigned int latestEncoderPos = 0;

void setup() {
  Serial.begin(115200);  //Initialize the serial connection
  pinMode(encoder0PinA, INPUT);
  pinMode(encoder0PinB, INPUT);

  // encoder pin on interrupt 0 (pin 2)
  attachInterrupt(0, doEncoderA, RISING);

  // encoder pin on interrupt 1 (pin 3)
  attachInterrupt(1, doEncoderB, RISING);
  md.init(); // Initialize the motor driver
  md.enableDrivers();
  turn(1500);
}

void loop() {
  //Do stuff here
     noInterrupts();
        latestEncoderPos = encoder0Pos;
     interrupts();
     if (latestEncoderPos != copyOfEncoder) {
         copyOfEncoder = latestEncoderPos;
         Serial.println(copyOfEncoder);
     }
}

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 turn(int number) {
  Serial.print("Number: ");
  Serial.println(number);
    md.setM1Speed(400);
    while (copyOfEncoder > number) {
  md.setM1Speed(0);
  Serial.print("Encoder Count at Stop: ");
  Serial.println(copyOfEncoder);
    }
}

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
    }
  }
}

You seem to be calling the turn() function from setup() and at that time loop() won't be working.

You need to call turn() from loop() and you need to change the WHILE to IF so it does not block the Arduino from updating copyOfEncoder

I would also separate the initial conditions from the turn() function - for example the motor speed does not need to be updated every time turn() is called. And the way it is now, even if turn() sets the speed to 0 the next call to turn() will set it back to full speed.

...R

@Robin2 thanks for this! That got it working! It does blow by the encoder flagged stopping point by about 165 encoder counts but i am pretty sure that is just because I am slamming the motor into high gear and then dead stop. I wrote up a linear acceleration/deceleration function to try to smooth out the motor transition from full on to off and hopefully lessen the amount of blow by. The function works in isolation but it does not work when I call it from the turn() function like below:

#include "DualTB9051FTGMotorShield.h"
DualTB9051FTGMotorShield md;

#define encoder0PinA  2
#define encoder0PinB  3

volatile int encoder0Pos = 0;
volatile int copyOfEncoder = 0;
volatile int latestEncoderPos = 0;
float number = 3000;
int minimumSpeed = 40;
boolean runOnce = true;

void setup() {
  Serial.begin(115200);  //Initialize the serial connection
  pinMode(encoder0PinA, INPUT);
  pinMode(encoder0PinB, INPUT);

  // encoder pin on interrupt 0 (pin 2)
  attachInterrupt(0, doEncoderA, RISING);

  // encoder pin on interrupt 1 (pin 3)
  attachInterrupt(1, doEncoderB, RISING);
  md.init(); // Initialize the motor driver
  md.enableDrivers();
  Serial.print("Number: ");
  Serial.println(number);
  //accelDecel(number);
}

void loop() {
  //Do stuff here
  noInterrupts();
  latestEncoderPos = encoder0Pos;
  interrupts();
  if (latestEncoderPos != copyOfEncoder) {
    copyOfEncoder = latestEncoderPos;
    //Serial.println(copyOfEncoder);
  }

  turn(number);
  //if (runOnce) {
  //  accelDecel(number);
  //  runOnce = false;
 // }
}

void turn(int number) {
  if (copyOfEncoder < number) {
    //md.setM1Speed(400);
    md.setM1Speed(accelDecel(float(number)));
  } else if (copyOfEncoder >= number) {
    md.setM1Speed(0);
    if (runOnce) {
      Serial.print("Encoder Count at Stop: ");
      Serial.println(copyOfEncoder);
      runOnce = false;
    }
  }
}

int accelDecel(float number) {
  // Gradually accelerates and decelerates the motor across the step number provided. Peaks at the half way point.

  float z; // iniatilze to use as the goal for the Decel 'for loop'
  float y; // iniatilze to use for speed set for the Accel 'for loop'
  float x; // iniatilze to use for speed set for the Decel 'for loop'
  if (int(number) % 2 != 0) { // Check if the number is even or odd. We need to do this so we don't drop a step when the number is odd
    z = 0.0; // If the number is odd set z to 0
  } else z = 1.0; // If the number is even set z to 1
  float percent = 400 / (number / 2.0); // The rate we will ramp up at in the for loops. We use this creates out linear accel and decel profile.
  Serial.print("Number/2.0: "); // For testing
  Serial.println(number / 2); // For testing
  Serial.print("Percent: "); // For testing
  Serial.println(percent, 8); // For testing
  Serial.print("Z: "); // For testing
  Serial.println(z); // For testing
  for (float i = 1.0; i <= number / 2.0; i++) { // First for loop for the linear accel for the first half of the steps
    y = i * percent;  //Calculates the speed the motor will accelerate at for each loop
    if (y < minimumSpeed) {  //Checking if y is going to be lower than what we want the minimum speed of the motor is going to be and if it is below that set it to our min speed
      y = minimumSpeed;  // Set the motor speed tp the minimum
    }
    //Serial.println(int(y)); // For testing
    //return (int(y));
    md.setM1Speed(int(y));
  }
  //Serial.println(int(y)); // For testing

  for (float i = number / 2.0; i >= z; i--) { // Second for loop for the linear decel for the second half of the steps
    x = i * percent; //Calculates the speed the motor will decelerate at for each loop
    if (i == z || i < 1) { // We want the motor to completely stop. We check the value of 'i' to deal with if the number the function recieved was odd or even and then we ensure that we set the motor speed for the last step to zero
      x = 0; // Set the motor speed to zero
    }
    else if (x < minimumSpeed) {  // Checking if x is going to be lower than what we want the minimum speed of the motor is going to be and if it is below that set it to our min speed
      x = minimumSpeed; // Set the motor speed tp the minimum
    }

    //Serial.println(int(x)); // For testing
    //return (int(x));
    md.setM1Speed(int(x));
  }
  //Serial.println(int(x)); // For testing
  //Serial.println(copyOfEncoder);

}

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
    }
  }
}

The motor does not ramp up and down as expected. I do not see it reporting a new speed gradually ramping up and down for each encoder tick. Any thoughts on why it fails when I connect it to the turn function?