Two pushbuttons, one stepper motor. Very close to success using interrupts.

I have two pushbuttons that make a stepper motor spin in two different cycles, and I have attempted to incorporate interrupts so that you don’t need to time the button press according to the stepper motor cycle.
Ultimately, the code works pretty well, except for how I seem to be one “step” (badumtss) away from getting the interrupts to work properly, since i have to define them in the setup and disable them first thing in the loop, in an attempt to accomplish the following:

  • Power up prototype
  • Motor is stationary
  • Choose either button to BEGIN corresponding cycle
  • Be able to use interrupts to switch to other cycle while in still the “starting” cycle
  • ??
  • Profit

My refined code is included, can you point out what I’m missing? Thanks.

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"
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  button2 = 0;
int  button3 = 0;// the pin that the pushbutton is attached to
const int ledPin = 13;       // the pin that the LED is attached to

// Variables will change:

volatile int start=0;


void setup()
{
    AFMS.begin();
   pinMode(2,INPUT);
   pinMode(3,INPUT);
  attachInterrupt(0, stroke, CHANGE);
  attachInterrupt(1, scrub, CHANGE);
}

void loop()
{
  detachInterrupt(0);
  detachInterrupt(1);
  button2 = digitalRead(2);
  button3 = digitalRead(3);
    if (button2 == HIGH)
    {
    start=1;
    }
    else if (button3 == HIGH)
    {
    start=2;
    }

  switch (start){
      case 1: //stroking speed
        myMotor->setSpeed(60);
        myMotor->step(80, FORWARD, DOUBLE); 
        myMotor->step(60, BACKWARD, DOUBLE);
        break;
      case 2: //scrubbing speed
        myMotor->setSpeed(100);
        myMotor->step(20, FORWARD, INTERLEAVE); 
        myMotor->step(10, BACKWARD, INTERLEAVE);
        myMotor->step(30, FORWARD, INTERLEAVE);
        myMotor->step(20, BACKWARD, INTERLEAVE);
        break;

}
}

void stroke()
{
        myMotor->

}

void scrub()
{

}

My first observation is that it is extremely unlikely that you need to complicate things by using interrupts when you could simply poll the two button inputs to achieve what you want. At any given time the system is doing one thing, ie is in one state, which would lend itself to using a state machine which in turn would allow the inputs to be polled in loop()

See State Machines

Neither of your ISR’s do anything so detaching the interrupts also does nothing. Did you actually want to use the ISR’s?

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"
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);

const int ledPin = 13;       // the pin that the LED is attached to

// Variables will change:
volatile int start = 0; // Start in idle state

void setup() {
  AFMS.begin();
  pinMode(2, INPUT);  // I hope there is a pull-up or pull-down on this pin or it will float and give random results
  pinMode(3, INPUT);  // I hope there is a pull-up or pull-down on this pin or it will float and give random results
  attachInterrupt(0, stroke, CHANGE);
  attachInterrupt(1, scrub, CHANGE);
}

void loop() {
  switch (start) {
    case 1: //stroking speed
      myMotor->setSpeed(60);
      myMotor->step(80, FORWARD, DOUBLE);
      myMotor->step(60, BACKWARD, DOUBLE);
      break;
    case 2: //scrubbing speed
      myMotor->setSpeed(100);
      myMotor->step(20, FORWARD, INTERLEAVE);
      myMotor->step(10, BACKWARD, INTERLEAVE);
      myMotor->step(30, FORWARD, INTERLEAVE);
      myMotor->step(20, BACKWARD, INTERLEAVE);
      break;
  }
}

void stroke() {
  start = 1;
}

void scrub() {
  start = 2;
}

johnwasser:
Neither of your ISR’s do anything so detaching the interrupts also does nothing. Did you actually want to use the ISR’s?

#include <Wire.h>

#include <Adafruit_MotorShield.h>
#include “utility/Adafruit_PWMServoDriver.h”
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);

const int ledPin = 13;      // the pin that the LED is attached to

// Variables will change:
volatile int start = 0; // Start in idle state

void setup() {
  AFMS.begin();
  pinMode(2, INPUT);  // I hope there is a pull-up or pull-down on this pin or it will float and give random results
  pinMode(3, INPUT);  // I hope there is a pull-up or pull-down on this pin or it will float and give random results
  attachInterrupt(0, stroke, CHANGE);
  attachInterrupt(1, scrub, CHANGE);
}

void loop() {
  switch (start) {
    case 1: //stroking speed
      myMotor->setSpeed(60);
      myMotor->step(80, FORWARD, DOUBLE);
      myMotor->step(60, BACKWARD, DOUBLE);
      break;
    case 2: //scrubbing speed
      myMotor->setSpeed(100);
      myMotor->step(20, FORWARD, INTERLEAVE);
      myMotor->step(10, BACKWARD, INTERLEAVE);
      myMotor->step(30, FORWARD, INTERLEAVE);
      myMotor->step(20, BACKWARD, INTERLEAVE);
      break;
  }
}

void stroke() {
  start = 1;
}

void scrub() {
  start = 2;
}

Wow, thank you! Does not seem as though I was all too far off… this modded code works great. Now, if I wanted the motor cycles to loop for a finite period of time, instead of infinitely, while still being interrupted by the opposite button press, is that too far-fetched or not?