I am not a programmer. The basic code presented here was written in 2012 by a person known in the stepping motor forums only as cannedmushrooms. It was modified for pushbutton input and various speeds for me in October of 2013 by my own son, a C programmer extraordinaire (who, alas, is not a ham).


So I thank them both for their help without which I might have spent a year or more attempting to learn - possibly unsuccessfully - C programming and its implementation for this application.


Here’s the code exactly as I use it which any and all are welcome to use:


#include <Wire.h>

#include <Adafruit_MotorShield.h>

#include "utility/Adafruit_PWMServoDriver.h"


// Create the motor shield object with the default I2C address

Adafruit_MotorShield AFMS = Adafruit_MotorShield();


// Connect a stepper motor with 200 steps per revolution (1.8 degree)

// to motor port #2 (M3 and M4)

Adafruit_StepperMotor *myMotor = AFMS.getStepper(200, 2);


int state, prevstate = 500, count = 500;

int nextEncoderState[4] = { 2, 0, 3, 1 };

int prevEncoderState[4] = { 1, 3, 0, 2 };


// Number of steps per turn of encoder

int forward=1;

int backward=1;


// Fast forward and backward steps

int fastforward=3;

int fastbackward=3;


// Used to calculate direction

int direct=0;


// Encoder inactivity counter

// using an unsigned int here effectively removes negative numbers and doubles the range of the integer

// I read that Aruduino Uno is limited to 16 bits, so the max value here is 65535

unsigned int inactivity_count;


// Setup an arbitray value to compare inactivity counter against

// Make this smaller if the time before motor stop is too long.  If this is never big enough, we might need a nested counter loop

#define ARBITRARY_COUNT 65534


void setup() {

Serial.begin(9600);

Serial.println("Follows encoder, Fast & Slow mod by SPT");


AFMS.begin(); //default frequency is 1.6kHz

//AFMS.begin(1000); //sets frequency to 1kHz


myMotor->setSpeed(200);  // 100 rpm


//place a Rotary encoder on pins

//A=Pin10, B=Pin2


pinMode(10, INPUT);

pinMode(2, INPUT);

pinMode(6, INPUT);


pinMode(4, INPUT);  //To run motor forward on button push

pinMode(8, INPUT);  //To run motor backward on button push


digitalWrite(2, HIGH);

digitalWrite(10, HIGH);

digitalWrite(6, HIGH);


digitalWrite(4, HIGH);

digitalWrite(8, HIGH);


}


void loop() {


state = (digitalRead(10) << 1) | digitalRead(2);


if (state != prevstate) {  // encoder is active


   inactivity_count = 0;  // clear the encoder inactivity counter


   if (state == nextEncoderState[prevstate]) {

     count++;

     direct= count-1;


     if (count > direct){

       if(digitalRead(6)){

         myMotor->step(forward, FORWARD, DOUBLE);

       }

       else{

         myMotor->step(forward, FORWARD, INTERLEAVE);

       }


       direct=0; 

     }

   }  

   else if (state == prevEncoderState[prevstate]) {

     count--;

     direct= count+1;


     if (count < direct){

       if(digitalRead(6)){

         myMotor->step(backward, BACKWARD, DOUBLE);

       }

       else{

         myMotor->step(backward, BACKWARD, INTERLEAVE);

       }


       direct=0;


      }

   }


   prevstate = state;


}


else {  // encoder is inactive


   // If button 4 is depressed, step the motor at fastforward rate

   if(!digitalRead(4)){

     myMotor->step(fastforward, FORWARD, DOUBLE); 

     inactivity_count = 0;

   }

 

   else {  // if buttons 4 and 8 are depressed, button 4 wins...


     // If button 8 is depressed, step the motor at fastforward rate

     if(!digitalRead(8)){

       myMotor->step(fastbackward, BACKWARD, DOUBLE); 

       inactivity_count = 0;

     }

   }



   // if inactivity count is greater than our arbitrary value, turn motor off

   if(inactivity_count > ARBITRARY_COUNT){

     myMotor->release(); 

   }

   else{

    // Avoid letting the counter roll over by only incrementing it when it is not > arbitrary count value

    inactivity_count++;

   }

}

}