Easy Driver with Variable Speed and POT

Hi all, I have stepper moter + Easy Driver and Potentiometer all wired here and am having a little bit of trouble making the speed a variable to use with the potentionmeter

I can - display the pot value on the LCD while turning the POT as well as change direction <50 Rev / 50> forward :slight_smile:
What I would like have happen is the have the POT define the speed of the stepper, so the closer you get to 50, the slower speed, and at the other end of the dial the faster 50 always being almost a stop.

Any ideas? here is the code I currently have

//////////////////////////////////////////////////////////////////
//©2011 bildr
//Released under the MIT License - Please reuse change and share
//Using the easy stepper with your arduino
//use rotate and/or rotateDeg to controll stepper motor
//speed is any number from .01 -> 1 with 1 being fastest - 
//Slower Speed == Stronger movement
/////////////////////////////////////////////////////////////////
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

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

#define DIR_PIN 2
#define STEP_PIN 3

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

void setup() {
  pinMode(DIR_PIN, OUTPUT);
  pinMode(STEP_PIN, OUTPUT);
  lcd.begin(16, 2);
} 

void loop(){ 
  // read the sensor value:
  int sensorReading = analogRead(A0);
  // map it to a range from 0 to 100:
  int knobReading = map(sensorReading, 0, 1023, 0, 100);
  // set the motor speed:
  
  if (knobReading > 50) {
    ////////////   REVERSE  /////////////////
    lcd.setCursor(0, 0);
    lcd.print("Rev:" );
    lcd.print(knobReading);
    steps++;
    lcd.setCursor(8, 0);
    lcd.print("SPD:");
    lcd.setCursor(0, 1);
    lcd.print("STEPS:");
    lcd.setCursor(6, 1);
    lcd.print(steps);
    rotate(-1600., .1);
  } else {
    if (knobReading < 50){
      ////////////// FORWARD   /////////////////
      lcd.setCursor(0, 0);
      lcd.print("Fwd:" );
      lcd.print(knobReading);
      lcd.setCursor(8, 0);
      lcd.print("SPD:");
      steps++;
      lcd.setCursor(0, 1);
      lcd.print("STEPS:");
      lcd.setCursor(6, 1);
      lcd.print(steps);
      rotate(1600., 1);
    }
  }  
}

void rotate(int steps, float speed){
  //rotate a specific number of microsteps (8 microsteps per step) - (negitive for reverse movement)
  //speed is any number from .01 -> 1 with 1 being fastest - Slower is stronger
  int dir = (steps > 0)? HIGH:LOW;
  steps = abs(steps);

  digitalWrite(DIR_PIN,dir); 

  float usDelay = (1/speed) * 70;

  for(int i=0; i < steps; i++){
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(usDelay); 

    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(usDelay);
  }
} 

void rotateDeg(float deg, float speed){
  //rotate a specific number of degrees (negitive for reverse movement)
  //speed is any number from .01 -> 1 with 1 being fastest - Slower is stronger
  int dir = (deg > 0)? HIGH:LOW;
  digitalWrite(DIR_PIN,dir); 

  int steps = abs(deg)*(1/0.225);
  float usDelay = (1/speed) * 70;

  for(int i=0; i < steps; i++){
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(usDelay); 

    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(usDelay);
  }
}

What I would like have happen is the have the POT define the speed of the stepper, so the closer you get to 50, the slower speed, and at the other end of the dial the faster 50 always being almost a stop.

So, why do you have this, then:

    rotate(-1600., .1);
      rotate(1600., 1);

Hardcoding the speed is not the way to make the speed dependent on the potentiometer setting.

Also, why are you passing a float as the first argument to this function?
void rotate(int steps, float speed){

It was example code that I use to get it running, and then added the POT. I understand the POT definres the speed :slight_smile:

I have this code working but am having trouble with the math to gain a wider range of speed.
Specifically this:
myStepper.setSpeed((knobReading-50) * 5);
// step 1/100 of a revolution:
myStepper.step(stepsPerRevolution/5);

Here is the sketch

#include <Stepper.h>
#include <LiquidCrystal.h>

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

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
// initialize the stepper library on pins 3 through 6:
Stepper myStepper(stepsPerRevolution, 2, 3);            

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

void setup() {
  // initialize the serial port:
  Serial.begin(9600);
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  // Print a message to the LCD.
  // lcd.print("GRAPHECTIONS");
}
// Run the LCD here


// Run the Stepper here
void loop() {
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(0, 0);
  // print the number of seconds since reset:

  // read the sensor value:
  int sensorReading = analogRead(A0);
  // map it to a range from 0 to 100:
  int knobReading = map(sensorReading, 0, 1023, 0, 100);
  // set the motor speed:

  lcd.print("Steps:" );
  lcd.print(stepCount); 
  lcd.setCursor(8, 1); 
  lcd.print(millis()/1000);  
  if (knobReading > 50) {
    myStepper.setSpeed((knobReading-50) * 5);
    // step 1/100 of a revolution:
    myStepper.step(stepsPerRevolution/5);
    lcd.setCursor(0, 1);
    lcd.print("Rev:" );
    lcd.print(knobReading);
    stepCount++;

  } 
  else {
    if (knobReading < 50){
      myStepper.setSpeed((50 - knobReading) * 5);
      // step 1/100 of a revolution:
      myStepper.step(-stepsPerRevolution/5);
      lcd.setCursor(0, 1);
      lcd.print("Fwd:" );
      lcd.print(knobReading);
      stepCount++;
    }
  } 
}

This may be what you're looking for...

http://arduino.cc/en/Reference/map

For example: myStepper.setSpeed(map(knobReading,0,1023,0,180)); Will map your analog reading (0-1023) to the set speed (0-180).

Modify as you need it.

Thanks so much!

I am a little confused though do I still need to call the rotate loop?
Here is what I have, with original speed setting commented out as well as the float speed. I can get it change direction when it hits 127, thats about it though.

#include <Stepper.h>
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
const int stepsPerRevolution = 200;
Stepper myStepper(stepsPerRevolution, 3, 2);            

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

#define DIR_PIN 2
#define STEP_PIN 3

void setup() {  
  // initialize the serial port:
  Serial.begin(9600);
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  
  //pinMode(DIR_PIN, OUTPUT);
  //pinMode(STEP_PIN, OUTPUT);
} 

void loop(){ 
  
  int val = analogRead(0);
  val = map(val, 0, 1023, 0, 255);
  //analogWrite(0, val);
 // myStepper.setSpeed(map(knobReading,0,1023,0,180));
    lcd.setCursor(0, 0);
    lcd.print(val); 
     myStepper.setSpeed(map(val,0,1023,0,180));   
      if (val > 127) {
            lcd.setCursor(0, 0);
            lcd.print(val);

            rotate(-1); //reverse
            //rotate a specific number of degrees 
           // rotateDeg(360, .5);
           // delay(1000);
      }else{
        if (val < 128) {
            lcd.setCursor(0, 0);
            lcd.print(val);
            //myStepper.setSpeed(map(val,0,1023,0,180));
            rotate(1); //forward
            }
      }
}

void rotate(int steps){
  //rotate a specific number of microsteps (8 microsteps per step) - (negitive for reverse movement)
  //speed is any number from .01 -> 1 with 1 being fastest - Slower is stronger
  int dir = (steps > 0)? HIGH:LOW;
  steps = abs(steps);

  digitalWrite(DIR_PIN,dir); 

  //float usDelay = (1/speed) * 70;

  for(int i=0; i < steps; i++){
    digitalWrite(STEP_PIN, HIGH);
    //delayMicroseconds(usDelay); 

    digitalWrite(STEP_PIN, LOW);
    //delayMicroseconds(usDelay);
  }
}

Ok so far have this working - if you think the code above is better let me know

Problem with the below is in reverse the speed is not the same as in forward (it just gets slower in the reverse direction stops)

#include <Stepper.h>
#include <LiquidCrystal.h>

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

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
// initialize the stepper library on pins 3 through 6:
Stepper myStepper(stepsPerRevolution, 2, 3);            

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

void setup() {
  // initialize the serial port:
  Serial.begin(9600);
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  // Print a message to the LCD.
  // lcd.print("GRAPHECTIONS");
}
// Run the LCD here


// Run the Stepper here
void loop() {
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(0, 0);
  // print the number of seconds since reset:

  // read the sensor value:
  int sensorReading = analogRead(A0);
  // map it to a range from 0 to 100:
  //constrain(sensorReading, 1, 10)
  int knobReading = map(sensorReading, 0, 1023, 0, 100);
  // set the motor speed:

  lcd.print("Steps:" );
  lcd.print(stepCount); 
  lcd.setCursor(8, 1); 
  lcd.print(millis()/1000);  
  if (knobReading > 50) {
    myStepper.setSpeed(knobReading);
    // step 1/100 of a revolution:
    myStepper.step(stepsPerRevolution/100);
    lcd.setCursor(0, 1);
    lcd.print("Rev:" );
    lcd.print(knobReading);
    stepCount++;

  } 
  else {
    if (knobReading < 50){
      myStepper.setSpeed(knobReading);
      // step 1/100 of a revolution:
      myStepper.step(-stepsPerRevolution/100);
      lcd.setCursor(0, 1);
      lcd.print("Fwd:" );
      lcd.print(knobReading);
      stepCount++;
    }
  } 
}

I have this code working but am having trouble with the math to gain a wider range of speed.

I hope that you realize that speed and stepper motors don't really go together. A stepper motor is for precise positioning, not speed. The actual speed that a stepper motor can obtain is a function of voltage and current, and how that voltage and current, and step interval is set.

A stepper can rotate pretty fast, but it must ramp up to speed. Look for a post by Grumpy_Mike, and look for his web site. He's got some good tutorials on motors in general, and on stepper motors in specific.

Thanks Paul, I have a good understanding of spped vs steps with stepper motors - from what I gather, if you set the steppers speed at a constant - say 70% - the actual rotation is depicted by thye delay between steps - the speed being the optimum setting bassed on the power source… right?

Currently I am using the following and hardcoding the speed to see how the stepper runs - what I would like to do is turn the speed into a variable the is defined by the pot, but keep it between .0001 and 1 - thoughts?

#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

//////////////////////////////////////////////////////////////////
//©2011 bildr
//Released under the MIT License - Please reuse change and share
//Using the easy stepper with your arduino
//use rotate and/or rotateDeg to controll stepper motor
//speed is any number from .01 -> 1 with 1 being fastest - 
//Slower Speed == Stronger movement
/////////////////////////////////////////////////////////////////

#define DIR_PIN 2
#define STEP_PIN 3

void setup() {
  lcd.begin(16, 2);
  pinMode(DIR_PIN, OUTPUT);
  pinMode(STEP_PIN, OUTPUT);
} 

void loop(){ 
  lcd.setCursor(0, 0);
  // read the sensor value:
  int sensorReading = analogRead(A0);
  //very slow .001
int verySlow = .1;
//slow .1
int Slow = .5;
//medium .5
int Medium = .7;
//fast 1
int Fast = 1;
  int theSpeed = 0;
  // map it to a range from 0 to 100:
  int knobReading = map(sensorReading, 0, 1023, 0, 100);
  theSpeed = 0;
      lcd.setCursor(9, 1);
      lcd.print(knobReading);
  // set the motor speed:  
  if (knobReading > 50) {  
    rotate(1600, .001);
    lcd.setCursor(0, 1);
    lcd.print("Fwd:" );
    lcd.print(knobReading);
    lcd.setCursor(8, 1);
    lcd.print(theSpeed);
  }else{
    if (knobReading < 50) {
    rotate(-1600, .8);  //reverse
    lcd.setCursor(0, 1);
    lcd.print("Rev:" );
    lcd.print(knobReading);
    lcd.setCursor(8, 1);
    lcd.print(theSpeed);
    }}

  //rotate a specific number of microsteps (8 microsteps per step)
  //a 200 step stepper would take 1600 micro steps for one full revolution
 // rotate(1600, .5);
 // delay(1000); 

 // rotate(-1600, .25); //reverse
 // delay(1000);
}

void speeds(){
//very slow .001
int verySlow = .001;
//slow .1
int Slow = .1;
//medium .5
int Medium = .5;
//fast 1
int Fast = 1;
}

void rotate(int steps, float speed){
  //rotate a specific number of microsteps (8 microsteps per step) - (negitive for reverse movement)
  //speed is any number from .01 -> 1 with 1 being fastest - Slower is stronger
  int dir = (steps > 0)? HIGH:LOW;
  steps = abs(steps);

  digitalWrite(DIR_PIN,dir); 

  float usDelay = (1/speed) * 70;

  for(int i=0; i < steps; i++){
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(usDelay); 

    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(usDelay);
       // lcd.setCursor(0, 0);
  //  lcd.print(i);
  }
} 

void rotateDeg(float deg, float speed){
  //rotate a specific number of degrees (negitive for reverse movement)
  //speed is any number from .01 -> 1 with 1 being fastest - Slower is stronger
  int dir = (deg > 0)? HIGH:LOW;
  digitalWrite(DIR_PIN,dir); 

  int steps = abs(deg)*(1/0.225);
  float usDelay = (1/speed) * 70;

  for(int i=0; i < steps; i++){
    digitalWrite(STEP_PIN, HIGH);
    delayMicroseconds(usDelay); 

    digitalWrite(STEP_PIN, LOW);
    delayMicroseconds(usDelay);
  }
}

I have create a new post as I have re-thought how to run this here, I would still love to hear your thoughts on the new brainstorm Sketch

http://arduino.cc/forum/index.php/topic,94576.0.html http://arduino.cc/forum/index.php/topic,94576.0.html