Hall Encoder on DC Gear Motor, Having troubles(leonardo)

I recently purchased an arduino leonardo board, and a DC geared motor(131:1 gear drive) with a hall sensor encoder(from DFRobot). I chose a DC gear motor out of cost and the hope to achieve reasonable positional control while maintaining full motion(not limited to 180* or 360* like a servo). I only need the motor to rotate in one direction so that simplifies things a bit. I've been having a lot of fun tinkering but I've hit a road-block.

I'm driving the motor with a TIP120 darlington circuit for a simple PWM power-supply. Arduino allows me to set 0-255 values to adjust the speed of the motor essentially. That part works great. Now I calculated the theoretical amount of encoder pulses that should occur for a full 360* rotation. Should be 131(gear enlargement) * 16 pulses per revolution = 2096 pulses per revolution of motor shaft.

If I write the code to cut power to the motor via the PWM once it achieves 2096 pulses at full power(255 on the TIP120 PWM) I end up running more like 1.25 revolutions.

If I write the code to cut the power to the motor via PWM once it achieves 2096 pulses at say 'less' power(110) on the TIP120 PWM I end up running more like 0.75 revolutions.

Shouldn't the motor speed have nothing to do with the pulse count on the encoder. Unless of course the motor is running too quickly for the encoder/microcontroller to handle. So I'm not sure what is actually going on I suspect the Interrupt code I have written is sub-par. I borrowed most of it from a tutorial written about the motor&encoder.

Should I be looking into PID control for this? I assumed the problem was inertia at first but it doesn't seem to be the case. I could be wrong.

//PIN Constants
const byte tip120PIN = 6;
const byte encoderPinA = 2;//A pin -> the interrupt pin 0
const byte encoderPinB = 4;//B pin -> the digital pin 4

//Program Constants
const int oneRevolutionPulseCount = 2096;//Theoretical number of pulses per revolution of pinion gear

//Global Program variables
byte encoderPinALast;
int pulseCount;//the number of the pulses
boolean Direction;//the rotation direction
boolean driveMotor;

void setup() {
  Serial.begin(57600);//Initialize the serial port for 57600 baud
  Serial.println("Initializing...");
  
  //Initialize PWM control for motor
  pinMode(tip120PIN, OUTPUT);//Set pin to be output
  analogWrite(tip120PIN, 110);//0 to 255 to control motor speed
  driveMotor = true;
  
  //Initialize Encoder
  encoderInitialization();//prepare encoder interrupt
}

void encoderInitialization() {
  Direction = true;//default -> Forward 
  pinMode(encoderPinA, INPUT); 
  pinMode(encoderPinB, INPUT); 
  attachInterrupt(0, rotorPulsed, CHANGE);
}

void loop() {
//If the motor is turned off then run this routine to wait a while and turn back on
  if(!driveMotor){
    delay(6000);
    driveMotor = true;
    analogWrite(tip120PIN, 111);// 0 to 255 to control motor speed
    pulseCount = 0;
  }
  
  delay(100);
}

void rotorPulsed() {
//If pulse count is greater then the theoretical one revolution Stop the motor and use the logic block in the Loop
  if(pulseCount >= oneRevolutionPulseCount) {
    driveMotor = false;
    pulseCount = 0;
    analogWrite(tip120PIN, 0);//Turn motor off
  }
  
  if(driveMotor) {
    int lastState = digitalRead(encoderPinA);
    //if Last Pin A state was Low, and New Pin A state is High
    if((encoderPinALast == LOW) && (lastState == HIGH)) {    
      int val = digitalRead(encoderPinB);
      //If Pin B is low and direction is Forward
      if(val == LOW && Direction) {
        Direction = false;//Change Direction to Reverse
      }
      //If Pin B is High and direction is Backward
      else if(val == HIGH && !Direction) {
        Direction = true;//Change Direction to Forward
      }
    }
    
    //Update the number of pulses that have occured if there was a change of state
    if(encoderPinALast != lastState) {
      if(!Direction)  
          {pulseCount++;}
        else 
          {pulseCount--;}
    }
    
    encoderPinALast = lastState;
  }
  
}

The wiring schematic is essentially the same as in this tutorial - 12V_DC_Motor_251rpm_w_Encoder_(SKU__FIT0186)-DFRobot . Only with a simple PWM circuit on a half-size breadboard with a wall-wart supply feeding into the motor.

Any help would be greatly appreciated :).

TheFool:
If I write the code to cut power to the motor via the PWM once it achieves 2096 pulses at full power(255 on the TIP120 PWM) I end up running more like 1.25 revolutions.

If I write the code to cut the power to the motor via PWM once it achieves 2096 pulses at say 'less' power(110) on the TIP120 PWM I end up running more like 0.75 revolutions.

I can see getting too much motion because of coasting but I can't see how you could end up with less then one revolution unless your pulse count is off.

I would only count one edge of each pulse (RISING or FALLING, not CHANGE).

I would limit the ISR to just incrementing the position. Everything else can be done in loop().

Variables used in the ISR should be declared "volatile".

The code that reads (or sets) the current position should be protected by noInterrupts() and interrupts():

volatile unsigned long position;
void loop() {
   unsigned long currentPosition;
   noInterrupts();
   currentPosition = position;
   interrupts();

   // Calculate based on currentPosition


   noInterrupts();
   position = 0;  // Reset position
   interrupts();
}

Encoder outputs are often open-collector, so you should use pinMode (..., INPUT_PULLUP)

Thanks everyone now its a lot more consistent using different PWM settings! Still having some variations in position. Some of it could be glide/moment of inertia, some of it appears to be undershooting however hard to keep track of it though. Does my new code look acceptable?

should I look into PID? Or is there something else going on?

//PIN Constants
const byte tip120PIN = 6;
const byte encoderPinA = 2;//A pin -> the interrupt pin 0
const byte encoderPinB = 4;//B pin -> the digital pin 4

//Program Constants
const int oneRevolutionPulseCount = 2096;//Theoretical number of pulses per revolution of pinion gear

//Global Program variables
volatile unsigned int pulseCount;//the number of the pulses
byte motorPWM = 110;
boolean driveMotor;

void setup() {
  Serial.begin(57600);//Initialize the serial port for 57600 baud
  Serial.println("Initializing...");
  
  //Initialize PWM control for motor
  pinMode(tip120PIN, OUTPUT);//Set pin to be output
  analogWrite(tip120PIN, motorPWM);//motor "speed" PWM
  driveMotor = true;
  
  //Initialize Encoder
  encoderInitialization();//prepare encoder interrupt
}

void encoderInitialization() {
  pinMode(encoderPinA, INPUT_PULLUP); 
  pinMode(encoderPinB, INPUT_PULLUP);//INPUT); 
  digitalWrite(encoderPinA, HIGH); //turn on pullup resistor
  digitalWrite(encoderPinB, HIGH);
  attachInterrupt(0, rotorPulsed, FALLING);
}

void loop() {
  unsigned long currentPulseCount;
  noInterrupts();
  currentPulseCount = pulseCount;
  interrupts();
  
  if(currentPulseCount == oneRevolutionPulseCount) {
    driveMotor = false;
    noInterrupts();
    pulseCount = 0;
    interrupts();
    analogWrite(tip120PIN, 0);//Turn motor off
  }
  
  if(!driveMotor) {
    delay(6000);
    driveMotor = true;
    analogWrite(tip120PIN, motorPWM);//Turn motor on
  }
}

void rotorPulsed() {
  if (PINB & 0b00000001){pulseCount++;} //if(digitalRead(PinB)==HIGH)
}