Stepper Motor Not Running Continuously

Hi There,
I'm trying to make a stepper motor driven system that will run back and forth along a rail between two limit switches. Here is the current code.

#include <Stepper.h>

byte buttonA = 6;
byte buttonB = 7;

boolean buttonAPressed = false;
boolean buttonBPressed = false;
boolean AState = false;
boolean BState = false;
boolean AStateLast = false;
boolean BStateLast = false;

const int stepsPerRevolution = 2038;

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

void setup() {
  Serial.begin(9600);
  Serial.println("Turner Electrical Auto-Expose V0.1");
  Serial.println("Starting Stepper...");
  pinMode(buttonA, INPUT_PULLUP);
  pinMode(buttonB, INPUT_PULLUP);
}
void loop() {
  readButtonA();
  actOnButtons();
  stepRun();
}
void readButtonA() {
  buttonAPressed = false;
  buttonBPressed = false;
  if (digitalRead(buttonA) == LOW) {
    buttonAPressed = true;
  }
  if (digitalRead(buttonB) == LOW) {
    buttonBPressed = true;
  }
}
void actOnButtons() {
  if (buttonAPressed == true && buttonBPressed == false) {
	  myStepper.step(-stepsPerRevolution);
  }
  if (buttonBPressed == true && buttonAPressed == false) {
    myStepper.step(stepsPerRevolution);
  }
}
void stepRun() {
  if (buttonAPressed == false && buttonBPressed == false) {
    myStepper.setSpeed(20);
  }
}

The problem I am having is that the motor will run only if a limit switch is pressed. It will run in the opposite direction to the limit switch, which is good, but it will only run if the limit switch is held down.
Is there a way for changing it to do this?

All the best!

Install some temporary Serial.println at strategic places telling strategic variables.

Hi, @lorit99
Welcome to the forum.

Can you please post a copy of your circuit, a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.

Can you post some images of your project?
So we can see your component layout.

Do you have a DMM? (Digital MultiMeter)

Thanks.. Tom.. :smiley: :+1: :coffee: :australia:

Ok, but you're going to hate how it looks...


I do have an analog multimeter, but I think the problem might be in the code.

Hi,
Thanks for the images.

Where in your code are the limit switches?

Thanks.. Tom.. :smiley: :+1: :coffee: :australia:

Limit switches are defined as buttonA (pin 6) and buttonB (pin 7).
Reading them is done through void readButtonA() and sets up the boolean variables buttonAPressed and buttonBPressed, changing them from "false" to "true" when the digitalRead from their respective pins is LOW.

The idea is that when buttonAPressed is "true" and buttonBPressed is "false" then the carriage will move away from button A, and vice versa. However, the problem is that the carriage only moves when the button is held down, while I need it to move constantly, with the buttons only changing it's direction.

The switches are two-pin pushbuttons that have been repurposed, and after a little experimentation I believe are push to break.

Hi,
You need to detect the activation or change of state of the limit switch, not the continuous state of the switch.
This is because the limit will only be activated briefly when the carriage hits it then reverses direction.

Can I also suggest;
Instead of buttonA, buttonAPressed etc.
You use;
LimitAPin , LimitAPressed etc.

This makes reading your code self explanatory.

Tom... :smiley: :+1: :coffee: :australia:
PS. Going back to bed mate, 4:30am here, only awake because of hayfever.

1 Like

Alright, thanks for your help! Hope the hayfever clears up!

You're using the stepper.h library. It has an example that bounces back and forth by turning one revolution in each direction: Stepper/examples/stepper_oneRevolution/stepper_oneRevolution.ino at master · arduino-libraries/Stepper · GitHub

You might consider a simple state machine handling moving either CW or CCW, and switching to the other direction based on the states of the switches.

Here's a modification of the library's example sketch to use a state variable to change directions:

/*
  Stepper Motor Control - one revolution

  This program drives a unipolar or bipolar stepper motor.
  The motor is attached to digital pins 8 - 11 of the Arduino.

  The motor should revolve one revolution in one direction, then
  one revolution in the other direction.


  Created 11 Mar. 2007
  Modified 30 Nov. 2009
  by Tom Igoe

  Modified to use a simple two-state state machine for
  https://forum.arduino.cc/t/stepper-motor-not-running-continuously/1283598

*/

#include <Stepper.h>

const int stepsPerRevolution = 200;  // change this to fit the number of steps per revolution
// for your motor

// initialize the Stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);


int movingCW = true;

void setup() {
  // set the speed at 60 rpm:
  myStepper.setSpeed(60);
  // initialize the serial port:
  Serial.begin(9600);
}

void loop() {

  if (movingCW) {
    // step one revolution in one direction:
    Serial.println("clockwise");
    myStepper.step(stepsPerRevolution);
    movingCW = false;
  } else {
    // step one revolution in the other direction:
    Serial.println("counterclockwise");
    myStepper.step(-stepsPerRevolution);
    movingCW = true;
  }
//  delay(500);
}

You could adapt this to your purposes with a couple changes:

If instead of the unconditional change of the state variable movingCW at the end of each revolution, you could make the change dependent on the particular limit switch that should change directions.

It would also allow you to more rapidly respond to the activating the limit switch by turning less than a full turn between checking the switch. (e.g., myStepper.step(100);)

Thanks for the help, a few notes after tinkering

  1. anything over 20rpm will cause the stepper motor to vibrate angrily and not move. I think this is either a mechanical fault, or the stepper is crap.
  2. I don't quite understand how I would go about implement the switches into the state machine here. Could you elaborate further on that?
  1. Could be.

  2. You could make the unconditional change to the opposite direction be conditional on the switch. Something like this completely untested snippet:

   if(buttonAPressed == true){
      movingCW = false;
   }

...then, as long as the CW limit switch (ButtonA?) hasn't been pressed, it continues movingCW, but if it has hit the limit, it switches direction.

The stepper being crap might also explain why it gets extremely hot while running, although that might be because that AC/DC converter was designed to power something bigger. Going to try the code snippet now

For a 28BYJ-48, without acceleration, I've found the maximum RPM to be about 12 ~ 14 RPM depending on voltage (nominally 5V) and motor load.

1 Like

The supply is somewhere in the region of 12V (I think?), and the mechanical system is not exactly optimal. At 5RPM it didn't move, just made a horrible grinding noise.

Ok, this is my absolutely awful shot at implementing it.

/*
  Stepper Motor Control - one revolution

  This program drives a unipolar or bipolar stepper motor.
  The motor is attached to digital pins 8 - 11 of the Arduino.

  The motor should revolve one revolution in one direction, then
  one revolution in the other direction.


  Created 11 Mar. 2007
  Modified 30 Nov. 2009
  by Tom Igoe

  Modified to use a simple two-state state machine for
  https://forum.arduino.cc/t/stepper-motor-not-running-continuously/1283598

*/

#include <Stepper.h>

const int stepsPerRevolution = 2038;  // change this to fit the number of steps per revolution
// for your motor

// initialize the Stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);

byte buttonA = 6;
byte buttonB = 7;
int movingCW = true;
boolean buttonAPressed = false;
boolean buttonBPressed = false;

void setup() {
  // set the speed at 60 rpm:
  myStepper.setSpeed(20);
  // initialize the serial port:
  Serial.begin(9600);
}

void loop() {
  buttonAPressed = false;
  buttonBPressed = false;
  if (digitalRead(buttonA) == LOW) {
    buttonAPressed = true;
  }
  if (digitalRead(buttonB) == LOW) {
    buttonBPressed = true;
  }
  if(buttonAPressed == true){
    movingCW = false;
  }
  if (movingCW = true) {
    // step one revolution in one direction:
    Serial.println("clockwise");
    myStepper.step(stepsPerRevolution);
    movingCW = false;
  } else if (movingCW = false){
    // step one revolution in the other direction:
    Serial.println("counterclockwise");
    myStepper.step(-stepsPerRevolution);
    movingCW = true;
  }
//  delay(500);
}

I think I might be lost in my own sauce here.

Here's a simulation in Wokwi:

/*
  Stepper Motor Control - Bounce Between Limit Switches

  https://wokwi.com/projects/403962641012999169

  This program drives a unipolar or bipolar stepper motor.
  The motor is attached to digital pins 8 - 11 of the Arduino.

  The motor should revolve one revolution in one direction, then
  one revolution in the other direction.


  Created 11 Mar. 2007
  Modified 30 Nov. 2009
  by Tom Igoe

  Modified to use a simple two-state state machine for
  https://forum.arduino.cc/t/stepper-motor-not-running-continuously/1283598

*/

#include <Stepper.h>

const int stepsPerRevolution = 200;  // change this to fit the number of steps per revolution
// for your motor

// initialize the Stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);


int movingCW = true;

void setup() {
  // set the speed at 60 rpm:
  myStepper.setSpeed(60);
  // initialize the serial port:
  Serial.begin(9600);
  pinMode(A0, INPUT_PULLUP);
  pinMode(A1, INPUT_PULLUP);
}

void loop() {

  if (movingCW) {
    // step one revolution in one direction:
    myStepper.step(stepsPerRevolution/100);
    if (digitalRead(A0) == LOW) {
      movingCW = false;
      Serial.println("counterclockwise");
    }
  } else {
    // step one revolution in the other direction:
    myStepper.step(-stepsPerRevolution/100);
    if (digitalRead(A1) == LOW) {
      movingCW = true;
      Serial.println("clockwise");
    }
  }
  //  delay(500);
}

DaveX the utter legend!
Thanks for all your help, here's the final code.

/*
  Stepper Motor Control - Bounce Between Limit Switches

  https://wokwi.com/projects/403962641012999169

  This program drives a unipolar or bipolar stepper motor.
  The motor is attached to digital pins 8 - 11 of the Arduino.

  The motor should revolve one revolution in one direction, then
  one revolution in the other direction.


  Created 11 Mar. 2007
  Modified 30 Nov. 2009
  by Tom Igoe

  Modified to use a simple two-state state machine for
  https://forum.arduino.cc/t/stepper-motor-not-running-continuously/1283598

*/

#include <Stepper.h>

const int stepsPerRevolution = 2038;  // change this to fit the number of steps per revolution
// for your motor

// initialize the Stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 8, 10, 9, 11);


int movingCW = true;

void setup() {
  // set the speed at 60 rpm:
  myStepper.setSpeed(20);
  // initialize the serial port:
  Serial.begin(9600);
  pinMode(6, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
}

void loop() {

  if (movingCW) {
    // step one revolution in one direction:
    myStepper.step(stepsPerRevolution/100);
    if (digitalRead(6) == LOW) {
      movingCW = false;
      Serial.println("counterclockwise");
    }
  } else {
    // step one revolution in the other direction:
    myStepper.step(-stepsPerRevolution/100);
    if (digitalRead(7) == LOW) {
      movingCW = true;
      Serial.println("clockwise");
    }
  }
  //  delay(500);
}

Are you applying 12V to a 5V motor? Post a wiring diagram.

Thanks. It is a very simple state machine, and if one was writing it from scratch, rather than adapting the library example, one might do several things differently.

For one -- allow for more states with an enum and a switch-case. For example, if you wanted to have an STOP state, you could rename "movingCW" to "moveState" and expand the choices as needed.