Arduino to control stepper motor with the use of a potentiometer (to control the speed) and 2 limit switches (to control the direction)

There seems to be an error with my sketch when I add the potentiometer reading, because the limit switches do not respond. If I were to add a constant speed, the limit switches would work, meaning that the issue is with the part I added for the potentiometer.

#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 stepper(AccelStepper::FULL4WIRE, 3, 4, 7, 8);

int stepperState = 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

  stepper.setMaxSpeed(200.0);   // set the maximum speed
  stepper.setCurrentPosition(0); // set position
}

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

  int sensorReading = analogRead(A2);
  // map it to a range from 0 to 100:
  int motorSpeed = map(sensorReading, 0, 1023, 0, 100);
  // set the motor speed:
  if (motorSpeed > 0) {
    stepper.setSpeed(motorSpeed);
    // step 1/100 of a revolution:
    stepper.runSpeed();
    
  if (limitSwitch_1.isPressed()) {
    stepperState = STATE_CHANGE_DIR;
    Serial.println(F("The limit switch 1: TOUCHED"));
  }

  if (limitSwitch_2.isPressed()) {
    stepperState = STATE_CHANGE_DIR;
    Serial.println(F("The limit switch 2: TOUCHED"));
  }

  switch (stepperState) {
    case STATE_CHANGE_DIR:
      direction *= -1; // change direction
      Serial.print(F("The direction -> "));
      if (direction == DIRECTION_CW)
        Serial.println(F("CLOCKWISE"));
      else
        Serial.println(F("ANTI-CLOCKWISE"));

      stepperState = STATE_MOVE; // after changing direction, go to the next state to move the motor
      break;

    case STATE_MOVE:
      targetPos = direction * MAX_POSITION;
      stepper.setCurrentPosition(0); // set position
      stepper.moveTo(targetPos);
      stepperState = 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 (stepper.distanceToGo() == 0) { // if motor moved to the maximum position
        stepper.setCurrentPosition(0);   // reset position to 0
        stepper.moveTo(targetPos);       // move the motor to maximum position again
      }
      break;
  }
  }

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

Hi,
post the code that works without the potentiometers.

1 Like
#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 stepper(AccelStepper::FULL4WIRE, 3, 4, 7, 8);

int stepperState = 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

  stepper.setMaxSpeed(200.0);   // set the maximum speed
  stepper.setAcceleration(50.0); // set acceleration
  stepper.setSpeed(200);         // set initial speed
  stepper.setCurrentPosition(0); // set position
}

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

  if (limitSwitch_1.isPressed()) {
    stepperState = STATE_CHANGE_DIR;
    Serial.println(F("The limit switch 1: TOUCHED"));
  }

  if (limitSwitch_2.isPressed()) {
    stepperState = STATE_CHANGE_DIR;
    Serial.println(F("The limit switch 2: TOUCHED"));
  }

  switch (stepperState) {
    case STATE_CHANGE_DIR:
      direction *= -1; // change direction
      Serial.print(F("The direction -> "));
      if (direction == DIRECTION_CW)
        Serial.println(F("CLOCKWISE"));
      else
        Serial.println(F("ANTI-CLOCKWISE"));

      stepperState = STATE_MOVE; // after changing direction, go to the next state to move the motor
      break;

    case STATE_MOVE:
      targetPos = direction * MAX_POSITION;
      stepper.setCurrentPosition(0); // set position
      stepper.moveTo(targetPos);
      stepperState = 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 (stepper.distanceToGo() == 0) { // if motor moved to the maximum position
        stepper.setCurrentPosition(0);   // reset position to 0
        stepper.moveTo(targetPos);       // move the motor to maximum position again
      }
      break;
  }

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

Do the motors move at all when add the potentiometer? Have you added a Serial.println to print the speed? If I auto-format your code the state machine does not execute unless motorSpeed is greater than 0. See below:

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

  int sensorReading = analogRead(A2);
  // map it to a range from 0 to 100:
  int motorSpeed = map(sensorReading, 0, 1023, 0, 100);
  // set the motor speed:
  if (motorSpeed > 0) {
    stepper.setSpeed(motorSpeed);
    // step 1/100 of a revolution:
    stepper.runSpeed();

    if (limitSwitch_1.isPressed()) {
      stepperState = STATE_CHANGE_DIR;
      Serial.println(F("The limit switch 1: TOUCHED"));
    }

    if (limitSwitch_2.isPressed()) {
      stepperState = STATE_CHANGE_DIR;
      Serial.println(F("The limit switch 2: TOUCHED"));
    }

    switch (stepperState) {
      case STATE_CHANGE_DIR:
        direction *= -1; // change direction
        Serial.print(F("The direction -> "));
        if (direction == DIRECTION_CW)
          Serial.println(F("CLOCKWISE"));
        else
          Serial.println(F("ANTI-CLOCKWISE"));

        stepperState = STATE_MOVE; // after changing direction, go to the next state to move the motor
        break;

      case STATE_MOVE:
        targetPos = direction * MAX_POSITION;
        stepper.setCurrentPosition(0); // set position
        stepper.moveTo(targetPos);
        stepperState = 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 (stepper.distanceToGo() == 0) { // if motor moved to the maximum position
          stepper.setCurrentPosition(0);   // reset position to 0
          stepper.moveTo(targetPos);       // move the motor to maximum position again
        }
        break;
    }
  }

  stepper.run(); // MUST be called in loop() function
}
1 Like

The motor runs and the potentiometer works perfectly with the use of the map command. On the other hand, there doesn't seem to be a response from the limit switches. This is with the aid of the accelstepper library to enable me to change the direction of the motor upon hitting the limit switch, hence the code you observe.

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