Control 2 stepper with 2 limit switch

Hi everyone,

I’m new to Arduino and been trying to get some code working for making 2 limit switches control 2 stepper motors. I have copied parts of code from other setups but I know I must be doing something wrong!

I run the simulation but the 2 steppers rotate in opposite direction and doesn't change the direction when one of the switches in on.

the Goal is the rotate in same direction and change direction when one of the switches is pressed

here is the Code below:

// C++ code for the upper body control two steppers with two switches and dc motor
// final code for upper body
#include <ezButton.h>
#include <AccelStepper.h>

#define DIRECTION_CCW -1
#define DIRECTION_CW   1

#define STATE_CHANGE_DIR 1
#define STATE_MOVE       2
#define STATE_MOVING     3


#define MAX_POSITION 0x7FFFFFFF // maximum of position we can set (long type)


ezButton limitSwitch_1(A0); // create ezButton object that attach to pin A0;
ezButton limitSwitch_2(A1); // create ezButton object that attach to pin A1;

AccelStepper stepper1(AccelStepper::FULL4WIRE, 7, 6, 5, 4);
AccelStepper stepper2(AccelStepper::FULL4WIRE, 12, 11, 10, 9);

int stepper1State = STATE_MOVE;
int stepper2State = STATE_MOVE;
int direction    = DIRECTION_CW;
long targetPos   = 0;


void setup() {
  Serial.begin(9600);

  limitSwitch_1.setDebounceTime(50); // set debounce time to 50 milliseconds
  limitSwitch_2.setDebounceTime(50); // set debounce time to 50 milliseconds

  stepper1.setMaxSpeed(500.0);   // set the maximum speed for Stepper1
  stepper1.setAcceleration(50.0); // set acceleration for Stepper1
  stepper1.setSpeed(100);         // set initial speed for Stepper1
  stepper1.setCurrentPosition(0); // set position for Stepper1

  stepper2.setMaxSpeed(500.0);   // set the maximum speed for Stepper2
  stepper2.setAcceleration(50.0); // set acceleration for Stepper2
  stepper2.setSpeed(100);         // set initial speed for Stepper2
  stepper2.setCurrentPosition(0); // set position for Stepper2
}

void loop() {
  limitSwitch_1.loop(); // MUST call the loop() function first
  limitSwitch_2.loop(); // MUST call the loop() function first

  if (limitSwitch_1.isPressed()) {
    stepper1State = STATE_CHANGE_DIR;
    stepper2State = STATE_CHANGE_DIR;
   
  }

  if (limitSwitch_2.isPressed()) {
    stepper1State = STATE_CHANGE_DIR;
    stepper2State = STATE_CHANGE_DIR;
    
  }

  switch (stepper1State) {
    case STATE_CHANGE_DIR:
      direction *= -1; // change direction
      stepper1State = STATE_MOVE; // after changing direction, go to the next state to move the motor
      break;

    case STATE_MOVE:
      targetPos = direction * MAX_POSITION;
      stepper1.setCurrentPosition(0); // set position
      stepper1.moveTo(targetPos);
      stepper1State = STATE_MOVING; // after moving, go to the next state to keep the motor moving infinity
      break;

    case STATE_MOVING: // without this state, the move will stop after reaching maximum position
      if (stepper1.distanceToGo() == 0) { // if motor moved to the maximum position
        stepper1.setCurrentPosition(0);   // reset position to 0
        stepper1.moveTo(targetPos);       // move the motor to maximum position again
      }
      break;
  }
  stepper1.run(); // MUST be called in loop() function

  switch (stepper2State) {
    case STATE_CHANGE_DIR:
      direction *= -1; // change direction
      stepper2State = STATE_MOVE; // after changing direction, go to the next state to move the motor
      break;

    case STATE_MOVE:
      targetPos = direction * MAX_POSITION;
      stepper2.setCurrentPosition(0); // set position
      stepper2.moveTo(targetPos);
      stepper2State = STATE_MOVING; // after moving, go to the next state to keep the motor moving infinity
      break;

    case STATE_MOVING: // without this state, the move will stop after reaching maximum position
      if (stepper2.distanceToGo() == 0) { // if motor moved to the maximum position
        stepper2.setCurrentPosition(0);   // reset position to 0
        stepper2.moveTo(targetPos);       // move the motor to maximum position again
      }
      break;
  }

  stepper2.run(); // MUST be called in loop() function

}

On a general note I'd recommend to simplify things and do some simple debugging.

State machines are a nice thing, but I feel the approach is overly complicating things here with this trivial task. Your state sequence is linear, you can replace it with a much simpler conditional structure. Also, start with one stepper, add the second if it works.

And most importantly, throw in a number of Serial.print() statements for debugging at critical places to see if the variables are what you expect them to be.

I suspect you'll find that one problem is that the button presses don't do what you expect. I don't now the library you used, but I imagine that isPressed() will be true as long as the button is pressed. If that is true, you'll need the code to look for flanks, not states, i.d. don't evaluate isPressed() again, before the button has been released in between.

Edit: I forgot, stepper1.setCurrentPosition(0); usually is used only once during setup or after calibration/homing, so maybe it does not what you think it does.

To change a stepper's initial direction, you can just change the wiring or use AccelStepper::setPinsInverted() in software.

Jan

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.