Stepper Motor Stopping Early Using AccelStepper

I am attempting to make three steppers stop in succession with each additional button press, and the first and third stepper stop correctly, however when I press the button for the third time (counter % 4 = 3), the second and third steppers both stop. The second stops the way it is supposed to; the third takes a little longer and vibrates once it comes to a stop, only stopping completely on the fourth press.

I am using HW135 EasyDriver and NEMA17 steppers.

#include <AccelStepper.h>
#define stp 3
#define stp2 4
#define stp3 5
#define dir 6
#define dir2 7
#define dir3 8

AccelStepper stepper3(AccelStepper::DRIVER, stp, dir);
AccelStepper stepper1(AccelStepper::DRIVER, stp2, dir2);
AccelStepper stepper2(AccelStepper::DRIVER, stp3, dir3);

int SPR = 1600, decTime = 6000;

int button = 10, Switch = 11;
int Time, timeSince;
int switchVal, buttonVal, lastButtonVal, counter;
int speed = 2500;
int accel = 500;

bool Off = false, midRun = false;
void setup() {
  stepper1.setMaxSpeed(speed);
  stepper2.setMaxSpeed(speed);
  stepper3.setMaxSpeed(speed);

  stepper1.setAcceleration(accel);
  stepper2.setAcceleration(accel);
  stepper3.setAcceleration(accel);

  pinMode(button, INPUT);
  pinMode(Switch, INPUT_PULLUP);
}

void loop() {
  switchVal = digitalRead(Switch);
  buttonVal = digitalRead(button);
  Time = millis();
  if (!switchVal) {
    Off = true;
    if (buttonVal && (lastButtonVal != buttonVal) && (Time - timeSince > 100)) {
      timeSince = Time;
      counter++;
      if (counter % 4 == 1) {
        stepper1.moveTo(stepper1.currentPosition() + 1e9);
        stepper2.moveTo(stepper2.currentPosition() + 1e9);
        stepper3.moveTo(stepper3.currentPosition() + 1e9);

      } else if (counter % 4 == 2) {
        stepper1.moveTo(stepper1.currentPosition() + decTime + (SPR - (stepper1.currentPosition() % SPR)));
      } else if (counter % 4 == 3) {
        stepper2.moveTo(stepper2.currentPosition() + decTime + (SPR - (stepper2.currentPosition() % SPR)));
        midRun = true;
      } else if (counter % 4 == 0 && midRun) {
        stepper3.moveTo(stepper3.currentPosition() + decTime + (SPR - (stepper3.currentPosition() % SPR)));
        midRun = false;
      }
    }
  } else {
    if (Off) {
      stepper1.moveTo(stepper1.currentPosition() - (stepper1.currentPosition() % SPR));
      stepper2.moveTo(stepper2.currentPosition() - (stepper2.currentPosition() % SPR));
      stepper3.moveTo(stepper3.currentPosition() - (stepper3.currentPosition() % SPR));
      counter = 0;
      Off = false;
      midRun = false;
    }
  }
  lastButtonVal = buttonVal;
  stepper1.run();
  stepper2.run();
  stepper3.run();
}

I also tried writing it like this:

else if (counter % 4 == 3) {
        stepper2.moveTo(stepper2.currentPosition() + decTime + (SPR - (stepper2.currentPosition() % SPR)));
        stepper3.moveTo(stepper3.currentPosition() + 1e9);
        midRun = true;
      } 

Your wiring might need to be examined.

In a simulation, your code "works" like this:

A button press does nothing.

With the switch ON, and the button short-pressed, the three motors accelerate CW. At this point, no button presses are recognized (with the switch ON).

Switching the switch OFF, starts negative CW acceleration, at this time no button presses are recognized, until the motors stop, change direction to CCW, then find "home."

diagram.json for wokwi.com
{
  "version": 1,
  "author": "foreignpigdog x",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-arduino-nano", "id": "nano", "top": 14.4, "left": -0.5, "attrs": {} },
    { "type": "wokwi-a4988", "id": "drv1", "top": -110.4, "left": 129.6, "attrs": {} },
    {
      "type": "wokwi-stepper-motor",
      "id": "stepper1",
      "top": -211.21,
      "left": 185.82,
      "attrs": { "size": "8", "arrow": "lime" }
    },
    { "type": "wokwi-vcc", "id": "vcc1", "top": -181.64, "left": 288, "attrs": {} },
    { "type": "wokwi-gnd", "id": "gnd1", "top": 0, "left": 191.4, "attrs": {} },
    { "type": "wokwi-a4988", "id": "drv2", "top": -110.4, "left": -4.8, "attrs": {} },
    {
      "type": "wokwi-stepper-motor",
      "id": "stepper2",
      "top": -211.21,
      "left": 51.42,
      "attrs": { "size": "8", "arrow": "yellow" }
    },
    { "type": "wokwi-a4988", "id": "drv3", "top": -110.4, "left": -129.6, "attrs": {} },
    {
      "type": "wokwi-stepper-motor",
      "id": "stepper3",
      "top": -211.21,
      "left": -73.38,
      "attrs": { "size": "8", "arrow": "cyan" }
    },
    {
      "type": "wokwi-pushbutton",
      "id": "btn1",
      "top": 35,
      "left": 211.2,
      "attrs": { "color": "green", "xray": "1" }
    },
    {
      "type": "wokwi-pushbutton",
      "id": "btn2",
      "top": 83,
      "left": 211.2,
      "attrs": { "color": "green", "xray": "1" }
    }
  ],
  "connections": [
    [ "gnd1:GND", "drv1:GND.1", "black", [ "v0" ] ],
    [ "gnd1:GND", "drv1:GND.2", "black", [ "v0" ] ],
    [ "vcc1:VCC", "drv1:VMOT", "red", [ "v0" ] ],
    [ "vcc1:VCC", "drv1:VDD", "red", [ "v0" ] ],
    [ "drv1:2B", "stepper1:A+", "green", [ "h0" ] ],
    [ "drv1:2A", "stepper1:A-", "green", [ "h0" ] ],
    [ "drv1:1A", "stepper1:B-", "green", [ "h0" ] ],
    [ "drv1:1B", "stepper1:B+", "green", [ "h0" ] ],
    [ "drv1:SLEEP", "drv1:RESET", "green", [ "h-9.6", "v-9.6" ] ],
    [ "drv1:GND.2", "drv1:ENABLE", "black", [ "h19.35", "v-19.12", "h-76.8", "v9.6" ] ],
    [ "drv2:2B", "stepper2:A+", "green", [ "h0" ] ],
    [ "drv2:2A", "stepper2:A-", "green", [ "h0" ] ],
    [ "drv2:1A", "stepper2:B-", "green", [ "h0" ] ],
    [ "drv2:1B", "stepper2:B+", "green", [ "h0" ] ],
    [ "drv2:SLEEP", "drv2:RESET", "green", [ "h-9.6", "v-9.6" ] ],
    [ "drv2:GND.2", "drv2:ENABLE", "black", [ "h19.35", "v-19.12", "h-76.8", "v9.6" ] ],
    [ "drv3:2B", "stepper3:A+", "green", [ "h0" ] ],
    [ "drv3:2A", "stepper3:A-", "green", [ "h0" ] ],
    [ "drv3:1A", "stepper3:B-", "green", [ "h0" ] ],
    [ "drv3:1B", "stepper3:B+", "green", [ "h0" ] ],
    [ "drv3:SLEEP", "drv3:RESET", "green", [ "h-9.6", "v-9.6" ] ],
    [ "drv3:GND.2", "drv3:ENABLE", "black", [ "h19.35", "v-19.12", "h-76.8", "v9.6" ] ],
    [ "vcc1:VCC", "drv2:VMOT", "red", [ "v134.4", "h-240", "v-86.48" ] ],
    [ "vcc1:VCC", "drv3:VMOT", "red", [ "v134.4", "h-364.8", "v-86.48" ] ],
    [ "vcc1:VCC", "drv2:VDD", "red", [ "v134.4", "h-240", "v-28.88" ] ],
    [ "vcc1:VCC", "drv3:VDD", "red", [ "v134.4", "h-364.8", "v-28.88" ] ],
    [ "gnd1:GND", "drv2:GND.1", "black", [ "v-28.8", "h-153.75" ] ],
    [ "gnd1:GND", "drv3:GND.1", "black", [ "v-28.8", "h-278.55" ] ],
    [ "gnd1:GND", "drv2:GND.2", "black", [ "v0" ] ],
    [ "gnd1:GND", "drv3:GND.2", "black", [ "v0" ] ],
    [ "nano:3", "drv3:STEP", "green", [ "v-14.4", "h-249.6", "v-52.8" ] ],
    [ "nano:4", "drv2:STEP", "green", [ "v-14.4", "h-115.7", "v-38.4" ] ],
    [ "nano:5", "drv1:STEP", "green", [ "v0" ] ],
    [ "nano:6", "drv3:DIR", "green", [ "v-24", "h-211.2", "v-33.6" ] ],
    [ "nano:7", "drv2:DIR", "green", [ "v-24", "h-96.5", "v-19.2" ] ],
    [ "nano:8", "drv1:DIR", "green", [ "h9.6", "v-57.6" ] ],
    [ "nano:GND.2", "btn1:2.l", "black", [ "v0" ] ],
    [ "nano:10", "btn1:1.l", "green", [ "v28.8", "h172.8" ] ],
    [ "nano:GND.2", "btn2:2.l", "black", [ "v0" ] ],
    [ "nano:11", "btn2:1.l", "green", [ "v0" ] ]
  ],
  "dependencies": {}
}
sketch.ino from Post #1 that I used

#include <AccelStepper.h>
#define stp 3
#define stp2 4
#define stp3 5
#define dir 6
#define dir2 7
#define dir3 8

AccelStepper stepper3(AccelStepper::DRIVER, stp, dir);
AccelStepper stepper1(AccelStepper::DRIVER, stp2, dir2);
AccelStepper stepper2(AccelStepper::DRIVER, stp3, dir3);

int SPR = 1600, decTime = 6000;

int button = 10, Switch = 11;
int Time, timeSince;
int switchVal, buttonVal, lastButtonVal, counter;
int speed = 2500;
int accel = 500;

bool Off = false, midRun = false;
void setup() {
  stepper1.setMaxSpeed(speed);
  stepper2.setMaxSpeed(speed);
  stepper3.setMaxSpeed(speed);

  stepper1.setAcceleration(accel);
  stepper2.setAcceleration(accel);
  stepper3.setAcceleration(accel);

  pinMode(button, INPUT);
  pinMode(Switch, INPUT_PULLUP);
}

void loop() {
  switchVal = digitalRead(Switch);
  buttonVal = digitalRead(button);
  Time = millis();
  if (!switchVal) {
    Off = true;
    if (buttonVal && (lastButtonVal != buttonVal) && (Time - timeSince > 100)) {
      timeSince = Time;
      counter++;
      if (counter % 4 == 1) {
        stepper1.moveTo(stepper1.currentPosition() + 1e9);
        stepper2.moveTo(stepper2.currentPosition() + 1e9);
        stepper3.moveTo(stepper3.currentPosition() + 1e9);

      } else if (counter % 4 == 2) {
        stepper1.moveTo(stepper1.currentPosition() + decTime + (SPR - (stepper1.currentPosition() % SPR)));
      } else if (counter % 4 == 3) {
        stepper2.moveTo(stepper2.currentPosition() + decTime + (SPR - (stepper2.currentPosition() % SPR)));
        midRun = true;
      } else if (counter % 4 == 0 && midRun) {
        stepper3.moveTo(stepper3.currentPosition() + decTime + (SPR - (stepper3.currentPosition() % SPR)));
        midRun = false;
      }
    }
  } else {
    if (Off) {
      stepper1.moveTo(stepper1.currentPosition() - (stepper1.currentPosition() % SPR));
      stepper2.moveTo(stepper2.currentPosition() - (stepper2.currentPosition() % SPR));
      stepper3.moveTo(stepper3.currentPosition() - (stepper3.currentPosition() % SPR));
      counter = 0;
      Off = false;
      midRun = false;
    }
  }
  lastButtonVal = buttonVal;
  stepper1.run();
  stepper2.run();
  stepper3.run();
}

It works for the first and second steppers, though? And switching the code to this...

AccelStepper stepper1(AccelStepper::DRIVER, stp, dir);
AccelStepper stepper2(AccelStepper::DRIVER, stp2, dir2);
AccelStepper stepper3(AccelStepper::DRIVER, stp3, dir3);

... still causes the 3rd motor to stop early, meaning it cannot be a circuitry issue (it consistently follows the code, not the circuit).

Here is what I see with the code.

  1. Nothing is moving.
  2. Press the button to no effect
  3. Switch the switch ON... nothing is moving.
  4. Short press the button... all three motors accelerate CW
  5. Pressing button has no effect
  6. Switch the switch OFF... all three motors begin negative acceleration in CW, arrive at "zero", change direction, accelerate CCW, begin negative acceleration in CCW, arrive at "zero/home"
  7. Pressing button has no effect.
  8. GOTO 3.

Check your wiring.

You could also replace all motor commands with Serial.print(); statements to see what happens (switch ON, button PRESSED, mot1CW, mot2CW, ... et c), without needing correct wiring.

So you're saying pressing the button after the first press doesn't do anything? But it does? Where is the discrepency?

Your wiring?

How is "button" wired? Why INPUT ant INPUT_PULLUP?

The button is wired like this:


The steppers are wired like this:

Except without the Enable, MS1, or MS2 pins wired, and with the 5+ and GND pins wired.

The switch only works with INPUT_PULLUP, the button works with INPUT

Make a drawing that shows your configuration.

1 Like

I don't have fritzing, and tinkercad doesn't have a stepper

That is a wring thing. The pin needs to be pulled (HIGH or LOW) while not being pressed to avoid noise creating an "ON" indication. Same with the button... tie it to one state to avoid noise, and use the other state to indicate "BUTTON PRESS"

Try WOKWI.COM... use the diagram.json I posted in Post #2 for a quick setup. Ask any question.

It is? Switch is either On or Off, Button is Off when not being pressed. Isn't that what the resistor is for?

There isn't the driver I'm using on there

Can You please read and reply to the first question in reply #7.

It is INPUT because I am using a pull-down resistor, for the Switch it is INPUT_PULLUP because that's the only way I've gotten it to work (otherwise it inputs random noise)

updated diagram.json for wokwi.com
{
  "version": 1,
  "author": "foreignpigdog x",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-arduino-nano", "id": "nano", "top": 14.4, "left": -0.5, "attrs": {} },
    { "type": "wokwi-a4988", "id": "drv1", "top": -110.4, "left": 129.6, "attrs": {} },
    {
      "type": "wokwi-stepper-motor",
      "id": "stepper1",
      "top": -211.21,
      "left": 185.82,
      "attrs": { "size": "8", "arrow": "lime" }
    },
    { "type": "wokwi-a4988", "id": "drv2", "top": -110.4, "left": -4.8, "attrs": {} },
    {
      "type": "wokwi-stepper-motor",
      "id": "stepper2",
      "top": -211.21,
      "left": 51.42,
      "attrs": { "size": "8", "arrow": "yellow" }
    },
    { "type": "wokwi-a4988", "id": "drv3", "top": -110.4, "left": -129.6, "attrs": {} },
    {
      "type": "wokwi-stepper-motor",
      "id": "stepper3",
      "top": -211.21,
      "left": -73.38,
      "attrs": { "size": "8", "arrow": "cyan" }
    },
    { "type": "wokwi-pushbutton", "id": "btn1", "top": 63.8, "left": 240, "attrs": {} },
    { "type": "wokwi-slide-switch", "id": "sw1", "top": 60, "left": -100, "attrs": {} },
    { "type": "wokwi-vcc", "id": "vcc1", "top": -181.64, "left": 288, "attrs": {} },
    { "type": "wokwi-gnd", "id": "gnd1", "top": 0, "left": 191.4, "attrs": {} },
    {
      "type": "wokwi-resistor",
      "id": "r1",
      "top": 61.55,
      "left": 336,
      "attrs": { "value": "1000" }
    }
  ],
  "connections": [
    [ "btn1:1.r", "nano:10", "green", [ "v0" ] ],
    [ "sw1:3", "nano:GND.2", "black", [ "v0" ] ],
    [ "sw1:1", "nano:11", "green", [ "v0" ] ],
    [ "drv1:STEP", "nano:3", "green", [ "v0" ] ],
    [ "drv1:DIR", "nano:6", "green", [ "v0" ] ],
    [ "drv2:STEP", "nano:4", "green", [ "v0" ] ],
    [ "drv2:DIR", "nano:7", "green", [ "v0" ] ],
    [ "drv3:STEP", "nano:5", "green", [ "v0" ] ],
    [ "drv3:DIR", "nano:8", "green", [ "v0" ] ],
    [ "drv1:1A", "stepper1:B-", "green", [ "h0" ] ],
    [ "drv1:1B", "stepper1:B+", "green", [ "h0" ] ],
    [ "drv1:2A", "stepper1:A-", "green", [ "h0" ] ],
    [ "drv1:2B", "stepper1:A+", "green", [ "h0" ] ],
    [ "drv2:1A", "stepper2:B-", "green", [ "h0" ] ],
    [ "drv2:1B", "stepper2:B+", "green", [ "h0" ] ],
    [ "drv2:2A", "stepper2:A-", "green", [ "h0" ] ],
    [ "drv2:2B", "stepper2:A+", "green", [ "h0" ] ],
    [ "drv3:1A", "stepper3:B-", "green", [ "h0" ] ],
    [ "drv3:1B", "stepper3:B+", "green", [ "h0" ] ],
    [ "drv3:2A", "stepper3:A-", "green", [ "h0" ] ],
    [ "drv3:2B", "stepper3:A+", "green", [ "h0" ] ],
    [ "drv1:SLEEP", "drv1:RESET", "green", [ "h-10" ] ],
    [ "drv2:SLEEP", "drv2:RESET", "green", [ "h-10" ] ],
    [ "drv3:SLEEP", "drv3:RESET", "green", [ "h-10" ] ],
    [ "vcc1:VCC", "drv1:VDD", "red", [ "v0" ] ],
    [ "vcc1:VCC", "drv1:VMOT", "red", [ "v0" ] ],
    [ "vcc1:VCC", "drv2:VDD", "red", [ "v0" ] ],
    [ "vcc1:VCC", "drv2:VMOT", "red", [ "v0" ] ],
    [ "vcc1:VCC", "drv3:VDD", "red", [ "v0" ] ],
    [ "vcc1:VCC", "drv3:VMOT", "red", [ "v0" ] ],
    [ "gnd1:GND", "drv1:GND.1", "black", [ "v0" ] ],
    [ "gnd1:GND", "drv1:GND.2", "black", [ "v0" ] ],
    [ "gnd1:GND", "drv2:GND.1", "black", [ "v0" ] ],
    [ "gnd1:GND", "drv2:GND.2", "black", [ "v0" ] ],
    [ "gnd1:GND", "drv3:GND.1", "black", [ "v0" ] ],
    [ "gnd1:GND", "drv3:GND.2", "black", [ "v0" ] ],
    [ "btn1:2.r", "r1:1", "black", [ "h0" ] ],
    [ "r1:2", "nano:GND.2", "black", [ "v0" ] ],
    [ "btn1:1.l", "nano:5V", "green", [ "h0" ] ]
  ],
  "dependencies": {}
}

I think this is how it's wired, but I am unfamiliar with the A4988 driver

Not according to electronics and wires acting as antennae. You must tie the pin through a resistor (HIGH or LOW) to avoid noise, then use the opposite state as "active"

The A4988 is a driver that uses STEP/DIR just like your code wants.

You need to be accurate, or what you see is not what we see.

Does your wokwi sim work? Describe what you observe.

Thank You!