stepper motor control using button

Hi, I would like to know if I can:

1 - start the motor at first push

2 - stop the motor pushing again

3 - rewind the motor holding the button pushed

  • concerning the rotation speed I have seen function as delay and millis, what would you recommend?
  • I have seen that there are dedicated libraries such as stepper and accelstep, which should I use?

1 Yes
2 Yes
3 Yes

millis()
Start by using the stepper library and get the examples working so that you know that your wiring is OK

How will you be powering the ARduino and the stepper ?

The state change detection example shows you how to determine when the switch BECOMES pressed, rather than IS pressed, or BECOMES released. Based on the time when the switch becomes pressed and when it becomes released, you can determine how long it was pressed.

Does a long press count as a press, too?

These links may also be of interest
Stepper Motor Basics
Simple Stepper Code

...R

UKHeliBob:
How will you be powering the ARduino and the stepper ?

I am going to use a 12 v power supply which will be regulated at 5 v using this device.

The stepper will be powered by the 12 v power supply, I am also using a A4988 Stepper Motor Driver.

So far I have written this code but unfortunately I haven't had any responce from the stepper

float pressLength_milliSeconds = 0;
 
// Define the *minimum* length of time, in milli-seconds, that the button must be pressed for a particular option to occur
int optionOne_milliSeconds = 100;
int optionTwo_milliSeconds = 2000;        
 
//The Pin your button is attached to
int buttonPin = 2;
 
//Pin your LEDs are attached to
int directionPin = 6;
int stepPin = 10;


unsigned long curMillis;
unsigned long prevStepMillis = 0;
unsigned long millisBetweenSteps = 25; // milliseconds
 
void setup(){

  Serial.begin(9600); //Start serial communication 
  Serial.println("Starting Stepper Demo with millis()");
 
  // Initialize the pushbutton pin as an input pullup
  (buttonPin, INPUT_PULLUP);     
 
  //set the driver pins as outputs
  pinMode(directionPin, OUTPUT); 
  pinMode(stepPin, OUTPUT); 
 

                                  
 
} // close setup
 
 
void loop() {

  curMillis = millis();
  actOnButtons();
 
  //Record *roughly* the tenths of seconds the button in being held down
  while (digitalRead(buttonPin) == HIGH ){ 
 
    delay(100);  //if you want more resolution, lower this number 
    pressLength_milliSeconds = pressLength_milliSeconds + 100;   
 
    //display how long button is has been held
    Serial.print("ms = ");
    Serial.println(pressLength_milliSeconds);
 
  }//close while
 //every time through the loop, we need to reset the pressLength_Seconds counter
  pressLength_milliSeconds = 0;

  
 
} // close void loop
 
  //Different if-else conditions are triggered based on the length of the button press
  //Start with the longest time option first

void actOnButtons(){
  //Option 2 - Execute the second option if the button is held for the correct amount of time
  if (pressLength_milliSeconds >= optionTwo_milliSeconds){
 digitalWrite(directionPin, HIGH);
 singleStep();{
    digitalWrite(stepPin,HIGH);
    delayMicroseconds(20);
    digitalWrite(stepPin,LOW);
    delayMicroseconds(20);
  }
 }
  
 
  //option 1 - Execute the first option if the button is held for the correct amount of time
  if(pressLength_milliSeconds >= optionOne_milliSeconds){
 digitalWrite(directionPin, LOW);
 singleStep();{
    digitalWrite(stepPin,HIGH);
    delayMicroseconds(1000);
    digitalWrite(stepPin,LOW);
    delayMicroseconds(1000);
  }
 }
 }
  
 
 void singleStep() {
 if (curMillis - prevStepMillis >= millisBetweenSteps) {
 prevStepMillis += millisBetweenSteps;
 digitalWrite(stepPin, HIGH);
 digitalWrite(stepPin, LOW);
 }
 }

Any idea where I'm wrong?

I know that the wiring is correct because using this other code the stepper works

// testing a stepper motor with a Pololu A4988 driver board or equivalent

// this version uses millis() to manage timing rather than delay()
// and the movement is determined by a pair of momentary push switches
// press one and it turns CW, press the other and it turns CCW

byte directionPin = 6;
byte stepPin = 10;

byte buttonCWpin = 2;
//byte buttonCCWpin = 11;

boolean buttonCWpressed = true;
//boolean buttonCCWpressed = false;

byte ledPin = 13;

unsigned long curMillis;
unsigned long prevStepMillis = 0;
unsigned long millisBetweenSteps = 25; // milliseconds

void setup() { 

  Serial.begin(9600);
  Serial.println("Starting Stepper Demo with millis()");

  pinMode(directionPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  pinMode(ledPin, OUTPUT);
  
  pinMode(buttonCWpin, INPUT_PULLUP);
  //pinMode(buttonCCWpin, INPUT_PULLUP);
  
}

void loop() { 
 
 curMillis = millis();
 readButtons();
 actOnButtons();
 
}

void readButtons() {
 
 buttonCWpressed = false;
 buttonCWpressed = true;
 
 if (digitalRead(buttonCWpin) == HIGH) {
 buttonCWpressed = false;
 }
 if (digitalRead(buttonCWpin) == LOW) {
 buttonCWpressed = true;
 }
}

void actOnButtons() {
 if (buttonCWpressed == true) {
 digitalWrite(directionPin, HIGH);
 singleStep();{
    digitalWrite(stepPin,HIGH);
    delayMicroseconds(20);
    digitalWrite(stepPin,LOW);
    delayMicroseconds(20);
  }
 }
 if (buttonCWpressed == false) {
 digitalWrite(directionPin, LOW);
 singleStep();{
    digitalWrite(stepPin,HIGH);
    delayMicroseconds(1000);
    digitalWrite(stepPin,LOW);
    delayMicroseconds(1000);
  }
 }
}

void singleStep() {
 if (curMillis - prevStepMillis >= millisBetweenSteps) {
 prevStepMillis += millisBetweenSteps;
 digitalWrite(stepPin, HIGH);
 digitalWrite(stepPin, LOW);
 }
}
  // Initialize the pushbutton pin as an input pullup
  (buttonPin, INPUT_PULLUP);

Something missing there? Seems like you would need to use a function to actually accomplish that.

Your code is trying to read the state of a pin and act on that state. If you can't move the stepper, then there is a distinct possibility that there is a problem with the code that reads the state of the switch and acts upon the information that it got. So, ditch that code. The loop() function should do nothing more than make the stepper step 10 times, then pause for 250 milliseconds.

Why are you not using the Stepper library?

PaulS:

  // Initialize the pushbutton pin as an input pullup

(buttonPin, INPUT_PULLUP);



Something missing there? Seems like you would need to use a function to actually accomplish that.

I dont know how but I have lost a part of that line, it is actually this

pinMode(buttonPin, INPUT_PULLUP);

PaulS:
Why are you not using the Stepper library?

I have implemented stepper library but nothing changed.

I have implemented stepper library but nothing changed.

Not without changing your code. When you change code, you need to re-post it.

Have you also (greatly) simplified the sketch to try to isolate the problem?

PaulS:
Not without changing your code. When you change code, you need to re-post it.

I have decided to start over, to be honest my first sketch wasn't so clear so I have decided to make a step back, as I was saying in my previous post this code works well:

int directionPin = 6;
int stepPin = 10;

int buttonpin = 2;


boolean buttonpressed; //false or true


int ledPin = 13;

unsigned long curMillis;
unsigned long prevStepMillis = 0;
unsigned long millisBetweenSteps = 25; // milliseconds

void setup() { 

  Serial.begin(9600);
  Serial.println("Starting Stepper Demo with millis()");

  pinMode(directionPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  pinMode(ledPin, OUTPUT);

//If a pull-down resistor is used, the input pin will be LOW when the switch is open and HIGH when the switch is closed.
//If a pull-up resistor is used, the input pin will be HIGH when the switch is open and LOW when the switch is closed.
  
  pinMode(buttonpin, INPUT_PULLUP);

    
}

void loop() { 
 
 curMillis = millis();
 readButtons();
 actOnButtons();
 
}

void readButtons() {
 
 buttonpressed = false; //false is defined as 0 (zero), THE SWITCH IS OPEN
 buttonpressed = true; //Any integer which is non-zero is true, THE SWITHCH IS CLOSED

 if (digitalRead(buttonpin) == LOW) { // low means 0V
 buttonpressed = true;
 }
 if (digitalRead(buttonpin) == HIGH) { // high menas 5V
 buttonpressed = false;
 }
}

void actOnButtons() {
if (buttonpressed == false) 
 {
 digitalWrite(directionPin, LOW);
 singleStep();{
    digitalWrite(stepPin,HIGH);
    delayMicroseconds(1000);
    digitalWrite(stepPin,LOW);
    delayMicroseconds(1000);
  }
 }

 if (buttonpressed == true) 
 {
 digitalWrite(directionPin, HIGH);
 singleStep();{
    digitalWrite(stepPin,HIGH);
    delayMicroseconds(20);
    digitalWrite(stepPin,LOW);
    delayMicroseconds(20);
  }
 }
 
}

void singleStep() {
 if (curMillis - prevStepMillis >= millisBetweenSteps) {
 prevStepMillis += millisBetweenSteps;
 digitalWrite(stepPin, HIGH);
 digitalWrite(stepPin, LOW);
 }
}

but on my new test using accelstepper library I haven't got the same satisfaction, the stepper doesn't move at all, do you have any advice?

#include <AccelStepper.h>
#include <MultiStepper.h>


AccelStepper Stepper1(1,6,10); //use pin 6 and 10 for dir and step, 1 is the "external driver" mode (A4988)
int dir = 1; //used to switch direction

/*float pressLength_milliSeconds = 0;
int optionOne_milliSeconds = 100;
int optionTwo_milliSeconds = 2000;*/


void setup() {
  Stepper1.setMaxSpeed(3000); //set max speed the motor will turn (steps/second)
  Stepper1.setAcceleration(13000); //set acceleration (steps/second^2)
}

void loop() {
  if(Stepper1.distanceToGo()==0){ //check if motor has already finished his last move
    Stepper1.move(1600*dir); //set next movement to 1600 steps (if dir is -1 it will move -1600 -> opposite direction)
    dir = dir*(-1); //negate dir to make the next movement go in opposite direction
    delay(1000); //wait 1 second
  }
  
  Stepper1.run(); //run the stepper. this has to be done over and over again to continously move the stepper
}

case:
but on my new test using accelstepper library I haven't got the same satisfaction, the stepper doesn't move at all, do you have any advice?

Start your tests with a very much lower speed and acceleration - try 20 steps per second and 10 for acceleration.

...R

Robin2:

  • try 20 steps per second and 10 for acceleration.

...R

unfortunately still not moving

Are you sure you have the connections correct.

In your code you have this

AccelStepper Stepper1(1,6,10); //use pin 6 and 10 for dir and step

but the library treats the second value as "step" and the third as "dir"

...R

Robin2:
Are you sure you have the connections correct.

but the library treats the second value as "step" and the third as "dir"

...R

U the best

Hi, I have done some steps forward trying to use a button.

So far the code I have written is this:

#include <AccelStepper.h>
#include <MultiStepper.h>

AccelStepper Stepper1(1,10,6); //use pin 6 and 10 for dir and step, 1 is the "external driver" mode (A4988)
int dir = 1; //used to switch direction

boolean ShortPress;
boolean State;                               
int ButtonPin = 2;



void setup() {

  Stepper1.setMaxSpeed(3200); //set max speed the motor will turn (steps/second)
  Stepper1.setAcceleration(200); //set acceleration (steps/second^2)
  pinMode(ButtonPin, INPUT_PULLUP);                 
}

void loop() {
 readButtons();
 actOnButtons();  
}

void readButtons() {

ShortPress = true;
ShortPress = false;
int i = 0;
while (digitalRead(ButtonPin))
{
i++;  // how much the button has been held
}

if (i<100)
  { ShortPress=true;}
else{ShortPress = false;}

}

  
  
void actOnButtons() {

if (ShortPress == true && State == true){
  Stepper1.distanceToGo()==0; { //check if motor has already finished his last move
   Stepper1.move(9600*dir); 
    
  }

  //Stepper1.moveTo(200);
  Stepper1.run(); //run the stepper. this has to be done over and over again to continously move the stepper
}

else if (ShortPress == false){
  Stepper1.stop();
}
}

Using this code the stepper works only if I keep the button held, while the button is unpressed the motor is quiet.

what I want to do is to use a kind of a code like this

if (ShortPress $ state) { !state-> first press}
elseif {!state  ->second press}
if (!ShortPress) {Long Press, reset}
  • to start the motor after one single short push
  • to stop the motor after a second short push
  • to rewind the motor after that the button has been hel for a while

any tips?

  ShortPress = true;
  ShortPress = false;

Can't make your mind up, it seems

  pinMode(ButtonPin, INPUT_PULLUP);
  while (digitalRead(ButtonPin))
  {
    i++;  // how much the button has been held
  }

The input will be HIGH (ie true) most of the time so i will increase very rapidly. Is that what you want to happen ? Will ShortPress be true or false most of the time ?

What do you intend the State variable to do considering that it start off as 0 (ie false) and is never changed ?

int i = 0;
while (digitalRead(ButtonPin))
{
i++;  // how much the button has been held
}

How much what? Chocolate ice cream? That code is NOT measuring HOW LONG the switch was held down.