Controlling the speed of a stepper using stepper.h

Hey guys,
I have a bit of code that I have pieced together from several different projects. In this particular case I have a stepper motor that I would like to open and close a door based ldr (light dependent resistor) readings.

I have everything working pretty good....the homing sequence of the motor is good and everything is going in the right direction and moving when it should.

But the thing I am struggling with is the motor speed.... as it is now the motor runs very slowly and is very loud. If I change the "int speed=60; //motor speed" it doesn't seem to so much change the speed as make it miss steps.

However if I change the "stepsPerRevolution" to around 1000 (which I know is not the proper thing to do) it speeds up the motor and quiets is down nicely but only seems to have that effect in one direction only which is in the clockwise direction called at the bottom of the code.

thanks
Al

#include <Stepper.h>

const int stepsPerRevolution = 200;  //number of steps per revolution (change according to ur motor)

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

#define ldr_pin A0
#define button 2
#define ENA 7
#define ENB 6
int ldr_value=0;
int ldr_average=0;
int total=0;

int speed=60; //motor speed
int threshold=700;  //change me
int lock=0; 

unsigned long duration=1*1*1;//1000*60*5; // 5min average duration  
unsigned long currentTime=0;
int numReadings=0;

void setup() {
 
  myStepper.setSpeed(speed);
  Serial.begin(9600);
  pinMode(button,INPUT_PULLUP);
  pinMode(ENA,OUTPUT);
  pinMode(ENA,OUTPUT);
 myStepper.setSpeed(speed); //set motor speed
 
  //Homing Sequence
 //Turn motor CCW once until it hits limit switch
 digitalWrite(ENA,HIGH);
 digitalWrite(ENB,HIGH);
 while(digitalRead(button)){
   myStepper.step(-1);
   delay(5);
  }
 digitalWrite(ENA,LOW);
 digitalWrite(ENB,LOW);
  Serial.println("Home Sequence Complete");
  
}

void loop() {

ldr_value=analogRead(ldr_pin);
total=total+ldr_value;
ldr_average=total/numReadings;
Serial.print("Average Value LDR: ");
Serial.println(ldr_average);
Serial.print("Value LDR: ");
Serial.println(ldr_value);
numReadings++;
delay(500);

if (millis()-currentTime>duration){
  currentTime=millis();
  numReadings=0;
  ldr_average=0;
  total=0;
  
  // if door is locked ....wait for daylight
if (lock==1){
  if (ldr_value>threshold){
     Serial.println("Day");
     lock=0; //unlocked
  //anticlockwise rotation
  Serial.println("counterclockwise");
  digitalWrite(ENA,HIGH);
 digitalWrite(ENB,HIGH);
 while(digitalRead(button)){
   myStepper.step(-1);
   delay(5);
  }
 digitalWrite(ENA,LOW);
 digitalWrite(ENB,LOW);
}
    
    }

    //if door is unlocked-----wait for night
  else{
    if (ldr_value<threshold)
{
  lock=1; //locked
  Serial.println("Night");
  // clock wise rotation 
  Serial.println("clockwise");
   digitalWrite(ENA,HIGH);
 digitalWrite(ENB,HIGH);
  myStepper.step(stepsPerRevolution);
  
  delay(500);
   digitalWrite(ENA,LOW);
 digitalWrite(ENB,LOW);
}
    }
  }

}

There's one mistake i seen, tho i don't know if it effects your problem you mentioned.

void setup() {
 
  myStepper.setSpeed(speed);
  Serial.begin(9600);
  pinMode(button,INPUT_PULLUP);
  pinMode(ENA,OUTPUT);
  pinMode(ENA,OUTPUT);
 myStepper.setSpeed(speed); //set motor speed

in your pinmodes, you accidentally listed ENA twice instead of ENA and ENB

another issue might be here.

  // if door is locked ....wait for daylight
if (lock==1){
  if (ldr_value>threshold){
     Serial.println("Day");
     lock=0; //unlocked
  //anticlockwise rotation
  Serial.println("counterclockwise");
  digitalWrite(ENA,HIGH);
 digitalWrite(ENB,HIGH);
 while(digitalRead(button)){
   myStepper.step(-1);
   delay(5);

at the bottom, you have it moving at 1 step at a time. which is fine, but the delay below that is the speed at which the steps are taken. try lowering it down to 1, and if that's not fast enough. try changing it to delayMicroseconds(); in which 1000 equals a delay of 1

Hi,

i am working at an simmilar project i think your problem is solved pretty easy.
Try removing the "delay(5)" in your while loops, else your maximum step count is 200 steps/second which is like 1 revolution per second.

Let me know if it fixed your problem.

:slight_smile:

greetings

Have you built a simple sketch, no switch reading, no LDR reading, to test the stepper BY ITSELF?

Just step some number of times clockwise and some number of times counterclockwise. Use the proper number of steps per revolution.

Does you stepper work properly, with the proper speed and quietly?

Many thanks to Wildcat and Mogg!

Playing a little hookie at lunch I was able to fix the enable duplication that Wildcat spotted....good catch the motor is running much smoother!

It does seem to be binding up a bit when it goes into the clockwise mode.....but that may be a bit of physical binding that I will address tonight when I get more time to play with the setup.

How would I make the motor/door move a predetermined amount of steps or revolutions in the clockwise direction in that last section of code? Change the myStepper. step(stepsPerRevolution)....?

It is running an 8mm 4 lead screw that has a 2mm pitch....so if one revolution gains me 2mm I need it to run around 450mm (18 inches)....so I will need it to make 225 revolutions give or take.

thanks guys!
Al

This code

 Serial.println("counterclockwise");
  digitalWrite(ENA,HIGH);
 digitalWrite(ENB,HIGH);
 while(digitalRead(button)){
   myStepper.step(-1);
   delay(5);
  }

is not using the speed setting for the motor - the speed is determined by the delay(5);

See how it differs from this part

 Serial.println("clockwise");
   digitalWrite(ENA,HIGH);
 digitalWrite(ENB,HIGH);
  myStepper.step(stepsPerRevolution);

It seems strange (but not impossible) that you happen to want to make the motor move the same number of steps as are in the variable stepsPerRevolution.

What type of stepper motor and stepper motor driver are you using?

Separately, if you use the AutoFormat tool to indent your code consistently it will be much easier to read.

...R
Stepper Motor Basics
Simple Stepper Code

Thank you so much! You guys have been a great help!

The combination of fixing the enabling pin and reducing the delay time has things working much better....I am still getting that bit of hesitation when the door is actually sitting on the limit switch and is called to reverse direction and go in the clockwise direction....but I'm not going to blame the code until I am sure it is not a physical issue.

Would using "Half-Step" mode give the motor more torque to possibly over come any minor misalignments?

And to answer Robin2's question I am using a bipolar stepper with an L298n driver....I have read your comments about this particular driver and all I can say is the only reasons I have for using it is that for one I have a box full of them from a previous project and that it has an onboard 5v regulator that simplifies the wiring a bit. I found a listing for some A4988's with a regulator but for some reason they were discontinued.

Again thanks a lot guys.....and let me know if you think half-stepping will help.

And Paul....I did take your advice and ran the oneRevolution sample code on the motor and it was much quieter....but of course this was before we knew about the enable pin.

al_duino_nano:
The combination of fixing the enabling pin and reducing the delay time has things working much better....I am still getting that bit of hesitation when the door is actually sitting on the limit switch and is called to reverse direction and go in the clockwise direction....but I'm not going to blame the code until I am sure it is not a physical issue.

Without seeing the latest version of your code and (perhaps) a short YouTube video to illustrate the problem) it is impossible to comment.

Would using "Half-Step" mode give the motor more torque to possibly over come any minor misalignments?

In general full-steps provide the most torque but the smoother running with half-steps might be beneficial. Experiment!

...R

al_duino_nano:
Thank you so much! You guys have been a great help!

The combination of fixing the enabling pin and reducing the delay time has things working much better....I am still getting that bit of hesitation when the door is actually sitting on the limit switch and is called to reverse direction and go in the clockwise direction....but I'm not going to blame the code until I am sure it is not a physical issue.

Would using "Half-Step" mode give the motor more torque to possibly over come any minor misalignments?

And to answer Robin2's question I am using a bipolar stepper with an L298n driver....I have read your comments about this particular driver and all I can say is the only reasons I have for using it is that for one I have a box full of them from a previous project and that it has an onboard 5v regulator that simplifies the wiring a bit. I found a listing for some A4988's with a regulator but for some reason they were discontinued.

Again thanks a lot guys.....and let me know if you think half-stepping will help.

And Paul....I did take your advice and ran the oneRevolution sample code on the motor and it was much quieter....but of course this was before we knew about the enable pin.

what kind of hesitation are you talking about? like a time delay type of hesitation? or the stepper engages, but there's a hesitation in the beginning of the cycle? and how big of door are you opening and closing?

another question i had after looking at your code. You have 1 stepper listed. but you have 2 enable pins? one enable is for the stepper, but what's the other enable pin controlling?

Wildcat.... It seems like a hesitation right at the beginning. If you give the lead screw a spin by hand it will take off and run fairly smoothly. The door is 18" tall and is being actuated but an 8mm lead screw like you would find on a 3d printer.

I did take everything off of the motor to see if I noticed a change in behavior.... It did not hesitate or stall (of course there was no load on it) but there was a noticeable difference in the sound.

I have been changing this factor in the last segment of code....

myStepper.step(stepsPerRevolution);

To change the distance the door travels....is this correct?

what kind of stepper motor are you using? and what kind of amperage does it take? it almost sounds like your stepper motor may be on the small side, or your driver doesn't supply enough current to account for the extra torque it needs at the beginning to get the door moving. but it's also possible that the leadscrew may be binding a little when it's in that position.

A couple of pics would be nice if possible.

The stepper is a 14HS20-1504S and the driver is an L298n hence the second enable pin....for some reason it has one enable per coil. Probly because this driver is commonly used to run dual dc motors on robots and I think it gives you PWM on both sides.

Let me get it all back together and I will take some pics and maybe a video....but first I'm going to modify the motor mount to fix the alignment.

your stepper and driver should be fine for that application, so it's probably a binding issue, especially if it's tight whenever the leadscrew nut is closest to the motor, and it binds as the nut is pushed away. if there's any misalignment between the leadscrew and it's nut it will bind up for the first couple rotations.... and then there's enough slack in the threads for free rotation. which sounds like your situation.

Ok....I have established that there is no physical binding issue. If I change....const int stepsPerRevolution = 200;....to...const int stepsPerRevolution = 800;...it runs smooth as silk in both directions.

But I was assuming this was a setting that should be based off of the motors datasheet and should remain set at 200....but none of the other factors seem to have the desired effect on the motor....changing int speed=60; does nothing....changing the delay times does nothing.

I just get the feeling that this is not the proper way to fix this and will probably jump up and bite me somewhere down the road.

Please help me speed up the motor a bit and quiet it down as well.

Here is the current code....and I will attach a link to a Fritzing drawing of the system.....

http://fritzing.org/media/fritzing-repo/projects/s/sliding-door/images/door%20opener_1.3.png

/*
 * Change Log
 * 3/16-Changed stepsPerRevolution to 800....motor runs smoothly

*/

#include <Stepper.h>

const int stepsPerRevolution = 800;  //number of steps per revolution (change according to ur motor)

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

#define ldr_pin A0
#define button 2
#define ENA 7
#define ENB 6
int ldr_value=0;
int ldr_average=0;
int total=0;

int speed=60; //motor speed
int threshold=700;  //change me
int lock=0; 

unsigned long duration=1*1*1;//1000*60*5; // 5min average duration  
unsigned long currentTime=0;
int numReadings=0;

void setup() {
 
  myStepper.setSpeed(speed);
  Serial.begin(9600);
  pinMode(button,INPUT_PULLUP);
  pinMode(ENA,OUTPUT);
  pinMode(ENB,OUTPUT);
 myStepper.setSpeed(speed); //set motor speed
 
  //Homing Sequence
 //Turn motor CCW once until it hits limit switch
 digitalWrite(ENA,HIGH);
 digitalWrite(ENB,HIGH);
 while(digitalRead(button)){
   myStepper.step(-1); //<----changed from step(-1)
   delay(1);
  }
 digitalWrite(ENA,LOW);
 digitalWrite(ENB,LOW);
  Serial.println("Home Sequence Complete");
  
}

void loop() {

ldr_value=analogRead(ldr_pin);
total=total+ldr_value;
ldr_average=total/numReadings;
Serial.print("Average Value LDR: ");
Serial.println(ldr_average);
Serial.print("Value LDR: ");
Serial.println(ldr_value);
numReadings++;
delay(500);

if (millis()-currentTime>duration){
  currentTime=millis();
  numReadings=0;
  ldr_average=0;
  total=0;
  
  // if door is locked ....wait for daylight
if (lock==1){
  if (ldr_value>threshold){
     Serial.println("Day");
     lock=0; //unlocked
  //anticlockwise rotation
  Serial.println("counterclockwise");
  digitalWrite(ENA,HIGH);
  digitalWrite(ENB,HIGH);
 while(digitalRead(button)){
   myStepper.step(-1); //<----changed from step(-1)
  delayMicroseconds(10); //delay(1);  
  }
  digitalWrite(ENA,LOW);
  digitalWrite(ENB,LOW);
}
    
    }

    //if door is unlocked-----wait for night
  else{
    if (ldr_value<threshold)
{
  lock=1; //locked
  Serial.println("Night");
  // clock wise rotation 
  Serial.println("clockwise");
    digitalWrite(ENA,HIGH);
    digitalWrite(ENB,HIGH);
  myStepper.step(8000);
    
    delayMicroseconds(10); //delay(1);
    digitalWrite(ENA,LOW);
    digitalWrite(ENB,LOW);
}
    }
  }

}

Ok. So i could be completely wrong on this, but it would be something i'd check considering i don't know a lot about code at the moment and it's an easy experiment. here's how i see it. when you tried to set your speed you used an "int speed=60". i've always thought of an int as a personal name for an int. but in this case, the word "speed" is an arduino command and changed colors. you could be very well right on this command, but "speed" isn't listed under the stepper.h library. There's a setSpeed, but no speed. So i'd change it to myspeed or something similar and see if that has any effect on the speed.

about your 200 steps. changing it to anything higher would be microstepping, which i'm not sure your driver is capable of that, but it could be.