Moving Motor Back and Forth , changing speed using potentiometer - Accelstepper

Hello,

I am using Arduino Uno, Stepper Motor Nema 17, and 250k pot.

The library I am using Accelstepper.

I got motor to change speed using potentiometer, but I am not able to change direction.

What I am trying to get is :-

  1. A motor to run at position 1000 and come back to 0
  2. Ability to change speed while it is moving back and forth.

I have inserted the code. I tried and tested different methods learning from the examples of accelstepper library and after long try, I am asking for help.

#include <AccelStepper.h>

int pos = 500;

AccelStepper stepper1(1, 7, 8);

int homeButton = 10;
const int ledPin = 13;
byte hBval;

#define SPEED_PIN A0

//Scale Pot to these
#define MAX_SPEED 500
#define MIN_SPEED 0.1  

void setup() {
  // put your setup code here, to run once:
  stepper1.setMaxSpeed(10000.0);
  //stepper1.setMaxSpeed(200); //nice and slow for testing
  //stepper1.moveTo(-3200);
  //stepper1.setAcceleration(500);
  
  pinMode(homeButton, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  stepperHome(); //runs routine to home motor

}

void loop() {
  // put your main code here, to run repeatedly:
static float current_speed=0.0;         //holds current motor speed in steps/second
static int analog_read_counter=1000;    //Counts down to 0 to fire analog read
static char sign= 0;                     //Holds -1, 1 or 0 to turn the motor on/off and control direction
static int analog_value=0;              //Holds raw analog value

if (analog_read_counter>0){
  analog_read_counter--;
}

else {
  analog_read_counter = 3000;
  //Now read the pot (from 0 to 1023)
  analog_value = analogRead(SPEED_PIN);

  //Give the stepper a chance to step if it needs to
  stepper1.runSpeed();
  
if (stepper1.distanceToGo()==0){
  //And Scale the pot's value from min to max speeds
  current_speed = ((analog_value/1023.0)*(MAX_SPEED-MIN_SPEED))+MIN_SPEED;
  delay(500);
  pos=-pos;
  stepper1.moveTo(pos);
  stepper1.run();
}


  //Update the stepper to run at this new speed
  stepper1.setSpeed(current_speed);
  
}

stepper1.runSpeed();
/*stepper1.moveTo(1000); // random position to end for testing
stepper1.runToPosition();
delay(200);
stepper1.moveTo(0);
stepper1.runToPosition();
delay(200);*/



}


void stepperHome(){ //this routine should run the motor
  hBval = digitalRead(homeButton);
  while (hBval == HIGH)
  {
    //backwards slowly till it hits the switch and stops
    stepper1.moveTo(-5000);
    stepper1.run();
    digitalWrite(ledPin, LOW); //indicates it's doing something
    hBval = digitalRead(homeButton);
  }
  digitalWrite(ledPin, HIGH); //indicates it's doing something
  stepper1.setCurrentPosition(0); //should set motor position to zero and go back to main routine

}

Obravim:
What I am trying to get is :-

  1. A motor to run at position 1000 and come back to 0
  2. Ability to change speed while it is moving back and forth.

Getting it to run back and forth should be straightforward - when the distanceToGo() becomes 0 give it an instruction to go to the other position.

I don't know if Accelstepper responds to speed changes (i.e. calls to setSpeed() ) while it is in the middle of a move. I can see how that would be difficult for moves that use acceleration. It would be very easy to write a program to test that.

If it cannot do what you want it is not difficult to write your own code without the library. Have a look at this Simple Stepper Code - especially the second example. The first example, using delay() is just for simple tests.

...R
Stepper Motor Basics

Hi Robin,

Thank you for the response.

Accelstepper does not respond to speed changes when moving back and forth. But it does respond to speed changes while in the middle of the movement. I could not figure out how to give instruction because Accelstepper library has all these functions moveTo, distanceToGo, Target…when I was reading about it, they all seem to work same. I was not sure what the difference was between each function and hence, I gave up.

So, I took your advice looking at the Simple Stepper Code program you built and now, I am trying to making it work to what I need.
Motor is moving back and forth, but the speed is slow, very slow. I could not figure out, how to map the values. May be someone can help me out here.
Mapping function is inside ‘getAnalogData’ within the code.

// testing a stepper motor with a Pololu A4988 driver board or equivalent
// on an Uno the onboard led will flash with each step
// this version uses delay() to manage timing

byte directionPin = 8;
byte stepPin = 7;
int numberOfSteps = 250; //distance you want to cover
byte ledPin = 13;
int pulseWidthMicros = 20;  // microseconds
static float millisbetweenSteps= 0; // milliseconds - or try 1000 for slower steps. decrease and increase the speed of the motor
  static int analog_value = 0;              // Holds raw analog value.
 static int analog_read_counter = 1000;

#define  MAX_SPEED 500
#define  MIN_SPEED 0.1

#define  SPEED_PIN A0


void setup() { 

  Serial.begin(9600);
  Serial.println("Starting StepperTest");
  digitalWrite(ledPin, LOW);
  
  delay(2000);

  pinMode(directionPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  pinMode(ledPin, OUTPUT);
  
 //pinMode(homeButton,INPUT_PULLUP);
 //stepperHome(); //runs routine to home motor

}

void loop() { 


   getAnalogData();
   Serial.println("HIGH DIRECTION PIN SPEED");
   Serial.print(millisbetweenSteps);
   
    digitalWrite(directionPin, HIGH);
  for(int n = 0; n < numberOfSteps; n++) {
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(pulseWidthMicros); // this line is probably unnecessary
    digitalWrite(stepPin, LOW);
    
    delay(millisbetweenSteps);
    
    digitalWrite(ledPin, !digitalRead(ledPin));
  }

  
  delay(3000);

  getAnalogData();
  digitalWrite(directionPin, LOW);
  for(int n = 0; n < numberOfSteps; n++) {
    digitalWrite(stepPin, HIGH);
    // delayMicroseconds(pulseWidthMicros); // probably not needed
    digitalWrite(stepPin, LOW);
    
    delay(millisbetweenSteps);
    
    digitalWrite(ledPin, !digitalRead(ledPin));
  }

}

void getAnalogData()
{
analog_value = analogRead(SPEED_PIN);
millisbetweenSteps = ((analog_value/1023.0) * (MAX_SPEED - MIN_SPEED)) + MIN_SPEED;

}

What is the lowest number of milliseconds between steps and what is the highest number that you require?

...R

Lowest number 25
Highest number 500

So I change the Max and Min values and got the motor working at correct speed back and forth.

Now, I am trying to get Pot working while the motor is moving just like Accelstepper library.

So I did this:

// testing a stepper motor with a Pololu A4988 driver board or equivalent
// on an Uno the onboard led will flash with each step
// this version uses delay() to manage timing

byte directionPin = 8;
byte stepPin = 7;
int numberOfSteps = 1000; //distance you want to cover
byte ledPin = 13;
int pulseWidthMicros = 20;  // microseconds
static float millisbetweenSteps= 0; // milliseconds - or try 1000 for slower steps. decrease and increase the speed of the motor
  static int analog_value = 0;              // Holds raw analog value.
 static int analog_read_counter = 1000;

#define  MAX_SPEED 1
#define  MIN_SPEED 300

#define  SPEED_PIN A0

int homeButton = 10;
byte hBval;

void setup() { 

  Serial.begin(9600);
  Serial.println("Starting StepperTest");
  digitalWrite(ledPin, LOW);
  
  delay(2000);

  pinMode(directionPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  pinMode(ledPin, OUTPUT);
  
 //pinMode(homeButton,INPUT_PULLUP);
 //stepperHome(); //runs routine to home motor

}

void loop() { 

if (analog_read_counter > 0) {
    analog_read_counter--;
  }
  else {
        analog_read_counter = 3000;

   getAnalogData();
   Serial.println("HIGH DIRECTION PIN SPEED");
   Serial.print(millisbetweenSteps);
   
    digitalWrite(directionPin, HIGH);
  for(int n = 0; n < numberOfSteps; n++) {
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(pulseWidthMicros); // this line is probably unnecessary
    digitalWrite(stepPin, LOW);
    
    delay(millisbetweenSteps);
    
    digitalWrite(ledPin, !digitalRead(ledPin));
  }

  
  delay(3000);

  getAnalogData();
  digitalWrite(directionPin, LOW);
  for(int n = 0; n < numberOfSteps; n++) {
    digitalWrite(stepPin, HIGH);
    // delayMicroseconds(pulseWidthMicros); // probably not needed
    digitalWrite(stepPin, LOW);
    
    delay(millisbetweenSteps);
    
    digitalWrite(ledPin, !digitalRead(ledPin));
  }
  
}

void getAnalogData()
{
analog_value = analogRead(SPEED_PIN);
millisbetweenSteps = ((analog_value/1023.0) * (MAX_SPEED - MIN_SPEED)) + MIN_SPEED;

}

void stepperHome(){
  hBval=digitalRead(homeButton);
  
}

It didn’t change the speed.

Hi Robin, I figured everything out. Everything works perfect.

Your code was really, really useful. I wish I had started with your simple code first, I could have got it done 4 days ago. :slight_smile:

Thank you so much.

Ob

Thank you for your kind words.

...R