Accelstepper: if there's a button, the motor never comes up to speed

The purpose of this project is to toggle a stepper motor when a button is pressed and released: if it's on, turn it off; if off, on. It works fine - the motor accelerates to speed - until I introduce the button.

This works, the motor spins up and runs at speed:

#include <AccelStepper.h>

const int  pushbuttonPin = 35;    // the pin for the pushbutton
const int stepsPerRevolution = 200;  // change this to fit the number of steps per revolution

// for your motor
#define X_STEP_PIN         54
#define X_DIR_PIN          55
#define X_ENABLE_PIN       38

AccelStepper stepper3(AccelStepper::FULL2WIRE, X_STEP_PIN, X_DIR_PIN);

void setup() {

    // turn on the power
    pinMode(10, OUTPUT);
    digitalWrite(10, HIGH);
    // set up the stepper
    stepper3.setMaxSpeed(5000.0);
    stepper3.setAcceleration(200.0);
    stepper3.moveTo(10000000000);

}

void loop() {

    stepper3.run();

}

This does not give me what I want, the motor runs, but very slowly:

#include <AccelStepper.h>

const int  pushbuttonPin = 35;    // the pin for the pushbutton
const int stepsPerRevolution = 200;  // change this to fit the number of steps per revolution

// for your motor
#define X_STEP_PIN         54
#define X_DIR_PIN          55
#define X_ENABLE_PIN       38

// Variables will change:
int pushbuttonCounter = 0;   // counter for the number of button presses
int pushbuttonState = 0;         // current state of the button
int lastpushButtonState = 0;     // previous state of the button
int machineIsOn = 0;

AccelStepper stepper3(AccelStepper::FULL2WIRE, X_STEP_PIN, X_DIR_PIN);

void setup() {

    // initialize the serial port:

    pinMode(10, OUTPUT);
    digitalWrite(10, HIGH);

    pinMode(pushbuttonPin, INPUT);

    stepper3.setMaxSpeed(5000.0);
    stepper3.setAcceleration(200.0);
    stepper3.moveTo(10000000000);

}

void loop() {

  pushbuttonState = digitalRead(pushbuttonPin);

  if (pushbuttonState != lastpushButtonState) {
    if (pushbuttonState == LOW) {
      // only register when the button is released
      machineIsOn = !machineIsOn;

    }
    lastpushButtonState = pushbuttonState;
    // avoid a bounce
    delay(50);
  }

  if(machineIsOn == 1){
    stepper3.run();
  } else {
    stepper3.stop();

  }

}

Logically, the code works, but the motor runs very, very slowly. What am I missing?

  • Bill in KCMO

Measure with a micrometer.
Mark with a crayon.
Cut with an axe.

How is the button switch wired? Is there a pull-up or pulldown resistor on that input?

did you want to configure the pin as INPUT_PULLUP

    pinMode(pushbuttonPin, INPUT);

What stepper driver are you using? An A4988 or DRV8825 type driver (step/dir) would have DRIVER in the accelstepper constructor. See the reference.

groundFungus:
How is the button switch wired? Is there a pull-up or pulldown resistor on that input?

Yes. I basically took two example projects - detecting a button press and basic Accelstepper - and folded them together.

groundFungus:
What stepper driver are you using? An A4988 or DRV8825 type driver (step/dir) would have DRIVER in the accelstepper constructor. See the reference.

This one: https://www.dfrobot.com/product-1547.html. It works fine until I introduce the button code.

Left out of my sample code was Serial.printLn() statements - when I changed those to fire only every 1000 loops, the motor picked back up, but I have a new symptom:

I set moveTo(1000000), but checking distanceToGo() at the end of the loop it counts down from some value much, much smaller. 451 for a while, then as I played with motor speeds, it got as high as 7001, but in whichever case, the motor would come on already decelerating!

What gives? Please, I'm tearing my hair out and I don't have much to spare!

Change:

AccelStepper stepper3(AccelStepper::FULL2WIRE, X_STEP_PIN, X_DIR_PIN);

To:

AccelStepper stepper3(AccelStepper::DRIVER, X_STEP_PIN, X_DIR_PIN);

Connect a 10k resistor from pushbuttonPin to GND.
Post your COMPLETE code in code tags.

10k resistor: already done.

#include <AccelStepper.h>

const int  pushbuttonPin = 35;    // the pin for the pushbutton 
const int ledPin = LED_BUILTIN;       // the pin for LED 
const int stepsPerRevolution = 200;  // change this to fit the number of steps per revolution

// for your motor
#define X_STEP_PIN         54
#define X_DIR_PIN          55
#define X_ENABLE_PIN       38

// Variables will change:
int pushbuttonCounter = 0;   // counter for the number of button presses
int pushbuttonState = 0;         // current state of the button
int lastpushButtonState = 0;     // previous state of the button
volatile int machineIsOn = 0;
auto output = "";
// AccelStepper stepper3(AccelStepper::FULL2WIRE, X_STEP_PIN, X_DIR_PIN);
AccelStepper stepper3(AccelStepper::DRIVER, X_STEP_PIN, X_DIR_PIN, 38, 53);

int counter = 0;

void setup() {
    // initialize the serial port:
    pinMode(10, OUTPUT);
    digitalWrite(10, HIGH);
    pinMode(pushbuttonPin, INPUT);
    Serial.begin(9600);
    
    stepper3.setMaxSpeed(2000.0);
    stepper3.setAcceleration(100.0);
    stepper3.moveTo(10000000); 
    Serial.println(stepper3.distanceToGo());
}


void loop() {

  pushbuttonState = digitalRead(pushbuttonPin);
  if (pushbuttonState != lastpushButtonState) {
    // if the state has changed, increment the counter
    if (pushbuttonState == LOW) {
      machineIsOn = !machineIsOn;
    }
    lastpushButtonState = pushbuttonState;
    delay(50);
  }

  if(machineIsOn == 1){
    if(counter % 4000 == 0){
      // just confirming we're where we want to be
      Serial.println("on");
    }
    stepper3.run(); 
  } else {
    if(counter % 4000 == 0){
     Serial.println("off");
    }
    stepper3.stop();
    stepper3.run();
  }
  if(counter % 1000 == 0){
   Serial.println(stepper3.distanceToGo());
  }
  counter++;
}

If it runs - and there's no guarantee that it will - it takes forever to get up to speed OR starts at speed and decelerates to zero. It's taking the proper path through the loop, on is "on", off is "off", but the behavior of the motor is unpredictable.