Button control stepper motor forward and backward

Used two buttons to control the stepper motor forward and backward by the sketch attached, it was OK. I tried to stop the motor by changed the myStepper.setSpeed(motorSpeed); into myStepper.setSpeed(0); and used BTStop button, the motor can't restart again even pressed the Forward button after BTStop pressed. why? how to use button control the running stepper motor?

Thanks

//20200528 test GOOD!

const int BTSMForward  = A2;  
const int BTSMBackward = A3;

int BTSMForwardState = 0;
int BTSMBackwardState = 0;

const int BTStop = A4;

int BTStopState = 0;

#include <Stepper.h>

const int stepsPerRevolution = 200;  /

Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);

int stepCount = 0;  // number of steps the motor has taken

void setup() {

  Serial.begin(9600);

  pinMode(BTSMForward, INPUT_PULLUP);
  pinMode(BTStop, INPUT_PULLUP);

} // close setup

void loop() {

  button();

}

void button() {

  BTStopState = digitalRead(BTStop);

  if (!BTStopState) {

    Stop();
  }

  BTSMForwardState = digitalRead(BTSMForward);
  if (BTSMForwardState) {

    ForwardSM();
  }

  BTSMBackwardState = digitalRead(BTSMBackward);
  if (BTSMBackwardState) {

    BackwardSM();
  }
}
// close void loop

void ForwardSM() {

  // read the sensor value:
  int sensorReading = analogRead(A0);
  // map it to a range from 0 to 100:
  int motorSpeed = map(sensorReading, 0, 1023, 0, 100);
  // set the motor speed:
  if (motorSpeed > 0) {
    myStepper.setSpeed(motorSpeed);
    // step 1/100 of a revolution:
    myStepper.step(stepsPerRevolution / 100);
  }
}

void BackwardSM() {
  // read the sensor value:
  int sensorReading = analogRead(A0);
  // map it to a range from 0 to 100:
  int motorSpeed = map(sensorReading, 0, 1023, 0, 100);
  // set the motor speed:
  if (motorSpeed > 0) {
    ///  myStepper.setSpeed(motorSpeed);

    myStepper.setSpeed(0);

    myStepper.setSpeed(motorSpeed);

    // step 1/100 of a revolution:
    myStepper.step(-stepsPerRevolution / 100);
  }
}

void Stop() {

  // read the sensor value:
  int sensorReading = analogRead(A0);
  // map it to a range from 0 to 100:
  int motorSpeed = map(sensorReading, 0, 1023, 0, 100);
  // set the motor speed:
  if (motorSpeed > 0) {
    myStepper.setSpeed(0);
    // step 1/100 of a revolution:
    myStepper.step(-stepsPerRevolution / 100);
  }
  Serial.print("stop");
  //  Serial.print();
}
myStepper.setSpeed(0);
    // step 1/100 of a revolution:
    myStepper.step(-stepsPerRevolution / 100); // this can't happen with speed set to 0,
                                                // your code probably hangs here

This is not the right way to go about it

void button() {

  BTStopState = digitalRead(BTStop);

  if (!BTStopState) {

    Stop();
  }

  BTSMForwardState = digitalRead(BTSMForward);
  if (BTSMForwardState) {

    ForwardSM();
  }

  BTSMBackwardState = digitalRead(BTSMBackward);
  if (BTSMBackwardState) {

    BackwardSM();
  }
}

You have three separate variables but logically the motor can only do one thing so you should have a single variable let's call it motorState and depending on which button is pressed it should have the values 'S' for stop, 'F' for forward and 'B' for backward.

And then the code in the action functions can just check that variable to decide if they should work - for example

void ForwardSM() {
    if (motorState != 'F') {
         return)
    }
    // the rest of the code
}

and the functions ForwardSM() etc should be called from loop() like this

void loop() {
  button();
  ForwardSM();
  // etc
}

...R

  • don't you need a pinMode for BTSMBackward?

  • your Forward(), Backward() and Stop() are very similar. why not have just one function that uses global variables for speed or direction and recognize that speed == 0 implies stop

  • in button, why not set parameters for speed: 0, + or -, instead of calling unique functions

  • do you need to capture a button press so the motor function is only called once.

Robin2:
This is not the right way to go about it

void button() {

BTStopState = digitalRead(BTStop);

if (!BTStopState) {

Stop();
  }

BTSMForwardState = digitalRead(BTSMForward);
  if (BTSMForwardState) {

ForwardSM();
  }

BTSMBackwardState = digitalRead(BTSMBackward);
  if (BTSMBackwardState) {

BackwardSM();
  }
}




You have three separate variables but logically the motor can only do one thing so you should have a single variable let's call it motorState and depending on which button is pressed it should have the values 'S' for stop, 'F' for forward and 'B' for backward.

And then the code in the action functions can just check that variable to decide if they should work - for example



void ForwardSM() {
    if (motorState != 'F') {
        return)
    }
    // the rest of the code
}




and the functions ForwardSM() etc should be called from loop() like this


void loop() {
  button();
  ForwardSM();
  // etc
}




...R

Thanks, you are right, I was planning to use three buttons like you mentioned, F for forward, B-backward, S-stop, in the third Subroutine I coded: myStepper.setSpeed(0) works , the stepper motor stop when I pressed the S button.
The problem is the motor can never restart again, even pressed F or B.
Best

JCA34F:

myStepper.setSpeed(0);

// step 1/100 of a revolution:
    myStepper.step(-stepsPerRevolution / 100); // this can't happen with speed set to 0,
                                                // your code probably hangs here

Thanks

myStepper.step(-stepsPerRevolution / 100); this make the motor reverse only;
myStepper.setSpeed(0); this make the motor stop.
Best

gcjr:

  • don't you need a pinMode for BTSMBackward?

  • your Forward(), Backward() and Stop() are very similar. why not have just one function that uses global variables for speed or direction and recognize that speed == 0 implies stop

  • in button, why not set parameters for speed: 0, + or -, instead of calling unique functions

  • do you need to capture a button press so the motor function is only called once.

Thanks, you are right, I need a pinMode for BTSMBackward? but the code work well on Arduino UNO, and the F/B buttons work well. problem came as long as I added S button.

Yes, I'll learn to config the button and try to use just one.
Best