Unknown Country
Asked

Use Buttons To Control Stepper Motors

Hello Athena,

I am using the stepper servo robot skill.

I am trying to add 3 buttons, 1 for CW, 1 for CCW, and 1 to stop. Can you guide me on how I can achieve that? I have 2 stepper motors, both have different travel distance but they come back to position 0.


Related Hardware Arduino Genuino Uno

ARC Pro

Upgrade to ARC Pro

Get access to the latest features and updates before they're released. You'll have everything that's needed to unleash your robot's potential!

Author Avatar
PRO
Canada
#1  

Thanks - I can help. First, quick clarification so I give exactly what you need:

  • Are the 3 buttons physical buttons wired to the Arduino (hardware)? Or do you want three virtual buttons in ARC’s UI to command the Stepper servo skill?
  • When you press CW, do you want both steppers to move toward their respective "max" travel (different distances), and CCW to move both back to position 0? Or do you want CW/CCW to jog continuously while pressed?
  • Do you want the Stop button to decelerate to a stop (recommended) or cut power immediately?

Answer those and I’ll tailor code/instructions. Below are two ready-to-use examples: (A) Arduino-side code for physical buttons using AccelStepper with acceleration and deceleration (non-blocking); and (B) ARC-side method (if you prefer UI buttons in ARC to control virtual servos from the Stepper servo robot skill).

  1. Arduino Mega (physical buttons) - AccelStepper, 2 steppers, 3 buttons
  • Behavior in this example:
    • CW button pressed: move both steppers to their defined "maxPosition" (different values for each motor).
    • CCW pressed: move both back to position 0.
    • Stop pressed: call stop() on each stepper to decelerate to a halt.
    • Buttons use INPUT_PULLUP (active LOW). Debouncing included.
    • Non-blocking loop uses stepper.run() so acceleration is applied.

Wiring notes:

  • Buttons connect between the Arduino input pin and GND. Use INPUT_PULLUP on the Arduino pin.
  • STEP/DIR of each DRV8825 -> connect STEP to the STEP pin in code, DIR to the DIR pin.
  • Common ground: ensure Arduino GND and motor power GND are common.
  • Make sure each DRV8825 current limit is set correctly and your 12V supply can handle peak current.

Arduino code:

// Arduino Mega example using AccelStepper
#include <AccelStepper.h>

// Pin definitions (change to match your wiring)
const int STEP1 = 2;
const int DIR1  = 5;
const int STEP2 = 3;
const int DIR2  = 6;

// Button pins (wired to GND when pressed, using INPUT_PULLUP)
const int BTN_CW   = 22; // CW (move to max)
const int BTN_CCW  = 23; // CCW (move to 0)
const int BTN_STOP = 24; // Stop (decelerate immediately)

// Travel positions (steps). Set per motor to your travel distance.
const long MAX_POS1 = 800;   // motor1 max steps
const long MAX_POS2 = 1600;  // motor2 max steps

// Debounce
const unsigned long DEBOUNCE_MS = 50;
unsigned long lastChangeTimeCW = 0;
unsigned long lastChangeTimeCCW = 0;
unsigned long lastChangeTimeStop = 0;
bool lastStateCW = HIGH;
bool lastStateCCW = HIGH;
bool lastStateStop = HIGH;

// AccelStepper objects (DRIVER uses STEP,DIR)
AccelStepper stepper1(AccelStepper::DRIVER, STEP1, DIR1);
AccelStepper stepper2(AccelStepper::DRIVER, STEP2, DIR2);

void setup() {
  // Buttons
  pinMode(BTN_CW, INPUT_PULLUP);
  pinMode(BTN_CCW, INPUT_PULLUP);
  pinMode(BTN_STOP, INPUT_PULLUP);

  // Steppers
  stepper1.setMaxSpeed(1000);      // steps/sec (tune for your motors)
  stepper1.setAcceleration(600);   // steps/sec^2 (tune)
  stepper2.setMaxSpeed(1000);
  stepper2.setAcceleration(600);

  // Optionally set current position to 0 at power-up if you know home is 0
  stepper1.setCurrentPosition(0);
  stepper2.setCurrentPosition(0);

  // If you have an ENABLE pin on drivers, you could toggle them here.
}

void loop() {
  // Read and debounce buttons
  readButtonsAndAct();

  // Non-blocking stepper updates. Must be called frequently.
  stepper1.run();
  stepper2.run();
}

void readButtonsAndAct() {
  unsigned long now = millis();

  // CW button
  bool currentCW = digitalRead(BTN_CW);
  if (currentCW != lastStateCW && now - lastChangeTimeCW > DEBOUNCE_MS) {
    lastChangeTimeCW = now;
    lastStateCW = currentCW;
    if (currentCW == LOW) { // pressed (active low)
      // Move both steppers to their max positions
      stepper1.moveTo(MAX_POS1);
      stepper2.moveTo(MAX_POS2);
    }
  }

  // CCW button
  bool currentCCW = digitalRead(BTN_CCW);
  if (currentCCW != lastStateCCW && now - lastChangeTimeCCW > DEBOUNCE_MS) {
    lastChangeTimeCCW = now;
    lastStateCCW = currentCCW;
    if (currentCCW == LOW) { // pressed
      // Move both steppers back to zero
      stepper1.moveTo(0);
      stepper2.moveTo(0);
    }
  }

  // STOP button
  bool currentStop = digitalRead(BTN_STOP);
  if (currentStop != lastStateStop && now - lastChangeTimeStop > DEBOUNCE_MS) {
    lastChangeTimeStop = now;
    lastStateStop = currentStop;
    if (currentStop == LOW) { // pressed
      // Decelerate to stop (non-instant). AccelStepper::stop() sets a target
      // so the motor decelerates to a stop respecting acceleration.
      stepper1.stop();
      stepper2.stop();
      // If you want to hold position after stopping, keep currentTarget as is.
      // To cancel target and hold position as current, you can:
      // stepper1.setCurrentPosition(stepper1.currentPosition());
    }
  }
}

Notes & tuning:

  • If you want CW/CCW to jog while the button is held (continuous movement while pressed), use move(speed) or setSpeed() + runSpeed(); I can show that variant if needed.
  • stop() will decelerate to a stop using the configured acceleration. If you want immediate stop without deceleration, you can:
    • Disable the driver via ENABLE pin (if wired), or
    • setMaxSpeed(0) temporarily (less graceful), or
    • setCurrentPosition(currentPosition()) to zero movement (but that doesn’t brake motors - drivers may float torque).
  • Ensure microstepping and current limit on each DRV8825 are configured. 2A motors require heat sinking and perhaps active cooling on DRV8825.
  • Keep run() continuously in loop; using blocking runToPosition() will prevent buttons from being read while moving.
  1. ARC-side UI buttons (if instead you want 3 virtual buttons in ARC) If you prefer to have 3 buttons in ARC to command the Stepper servo robot skill (virtual servos V1, V2, etc.), you can do this with a simple JavaScript IDE script or Project Buttons:
  1. Add three Script Controls or Button Controls in an ARC project (Project -> Add Control -> Script or Button).
  2. Example ARC JavaScript to move virtual servos V1 and V2 to their positions (replace v1/v2 with your virtual ports):
// "CW" button script example: move to max positions
Servo.setPosition(v1, 180); // replace 180 with your ARC max servo value for that motor
Servo.setPosition(v2, 180);
// "CCW" button script example: move back to 1 (home)
Servo.setPosition(v1, 1);
Servo.setPosition(v2, 1);
// "STOP" button script example: stop both (attempt decel)
Servo.release(v1); // releases torque (if Stepper skill supports it)
Servo.release(v2);
  • Or call specific Stepper servo control commands if the skill supports them. See the Stepper servo skill manual for ControlCommand usage and the virtual port mapping.
  • Each ARC virtual servo maps to a BUS_ID in the Stepper servo skill; the Stepper servo robot skill handles acceleration when configured in the skill.

Useful links

Next steps / Questions

  • Tell me whether the buttons are hardware or in ARC UI and how you want the buttons to behave (move-to-max & move-to-0, or continuous jog while pressed, or step/jog increments).
  • If hardware: supply which Arduino pins you want to use and your exact max step counts for both motors and I’ll adapt the code.
  • If ARC UI: tell me your Stepper servo virtual ports (v1, v2) and the ARC max servo position (default 180 or something larger) and I’ll write sample ARC JavaScript control scripts and show how to add UI buttons in ARC (including configuring the robot skill kebab menu if you want button-specific settings).

Would you like the alternate "jog while pressed" Arduino code instead?


I am a customer support GPT-powered AI and still learning. If you have doubts about my response, please use the support documentation to verify my answer.