I've poured through the amazing resources on this amazing site. Gone through the Stepper Motor Basics topic (which is fantastic by the way). I'm still a little stumped. I'm sure it's a simple math problem but I need someone to give me a little help.
I have 3 Nema 17 Stepper motors. I am only using 1 to move a linear slide rail and am trying to get a certain speed (with no missed steps) out of the motor.
I have used the guide in the Stepper Motor Basics to determine the required torque which came out to be about 1000g.cm.
I am also using an authentic Pololu DRV8825 hooked up as seen in the attached photo.
My Power Supply is a 9V-24V 2.5A 72W Wall Adapter.
Microcontroller - Arduino Mega 2560 Rev3.
My question is this. I need to move this motor, under the specific torque, 5 revolutions forward and then 5 revolutions in reverse in a time frame of 1s. Is this possible with this setup?
Do I need a higher voltage Power Supply? Is it just too much required torque to be able to move it that fast?
When I run some tests the max I can get (without stalling and skipping steps) is running it with a 2s time frame. Here's the code I am using as well. The max speed I can get is with motor #2 and speed of 1100.
Thank you for any suggestions and/or help.
Dustin
#include <AccelStepper.h>
AccelStepper SM(1, 36, 38);
const int DistanceToMove = 20; // Input Distance in mm
const int MotorSpeed = 1100; // Motor Speed (Absolute Max 1000)
const int DistancePR = 4; // Distance (mm) per 360 degree rotation
const int StepPR = 200; // Steps per 360 degree rotation
const int Rotations = DistanceToMove*StepPR/DistancePR;
void setup() {
SM.setMaxSpeed(4000); // Set the maximum speed in steps per second:
SM.setEnablePin(3);
SM.setPinsInverted(false, false, true);
SM.disableOutputs(); //Disables Motor Driver Enable Pin
}
void loop() {
SM.enableOutputs(); //Enables Motor Driver Enable Pin
SM.setCurrentPosition(0); // Set the current position to 0 point
while(SM.currentPosition() != -Rotations) // number of steps backward
{
SM.setSpeed(-MotorSpeed); //Motor Speed backward
SM.runSpeed();
}
// delay(10);
SM.setCurrentPosition(0); //Resets current position to 0
while(SM.currentPosition() != Rotations) // number of steps forward
{
SM.setSpeed(MotorSpeed); //Motor Speed forward
SM.runSpeed();
}
SM.disableOutputs(); //Disables Motor Driver Enable Pin
delay(1000);
}
Thank you for the reply. You're correct I do not mean "specified torque". I was referring to the specific torque measured and required to move the object of interest.
Could I theoretically get higher speeds out of a Nema 23 motor?
I know all motors are going to be different but I am trying to find a solution with keeping my Arduino and setup that I have but altering Motor, Driver and software if needed.
Wondering if I'm missing something with regards to specs I should be looking for.
You need a stepper with low inductance, high amp rating, low voltage rating. 5 turns per second is no where near the limit of the stepper - if the torque is low enough. You'll most likely need a decent stepper driver and something like 36V/10A powersupply.
volkswagenbug:
Thank you for any suggestions and/or help.
A few things ...
You can't get very high step rates with the AccelStepper library because it use slow floating point maths. You should be able to adapt this Simple Stepper Code to get high step rates. The second, non-blocking example is the one you should use.
In your AccelStepper program you are using runSpeed() which does not use acceleration. The run() function is for acceleration. You must accelerate the motor if you want to get to high step rates. If necessary it is not too difficult to write your own acceleration code. See this demo simple acceleration code
For high step rates you need a high voltage. I would try your existing power supply at its max before spending money on a higher voltage power supply. By the way a 2 amp 2.1 Ohm motor requires about 8.4 watts (say 12 watts to give a bit of headroom). With a 24v power supply 12 watts just requires 0.5 amps and with a 36v power supply it would need 0.33 amps. I would round those up to 1 amp to give plenty of headroom.
You may find that an variable voltage power supply does not work well with a stepper driver because both of them will be trying to control the current at the same time.
Thank you for your insight Robin2. I really value it. I will try what you suggest and let you know what the response is.
I have tried a much simpler code in the past without any libraries and it was much slower than using the Accelstepper library. I will give this a shot.
What I am getting from your post about the motor supply is that I shouldn’t need a power supply with more than 1A rating correct?
I have already ordered 2 others on amazon that aren’t variable to test them as I can always return if they aren’t adequate.
In your experience should I be able to come up with a solution to move my motor as fast as I want with the given load? Or am I missing something key to this whole project? Thanks again.
So I've tried the non-blocking code you suggest and have tried to modify it to remove the button inputs but I can only get the motor to continuously spin in 1 direction. The smallest millisBetweenSteps I can input is 1 and it runs fine on that but it is still slower than my previous code. Not sure why it doesn't follow the code and reverse the directionPin. I would also like to control the number of steps the motor will do but when I try to add that the motor doesn't turn at all. I'll tackle the Speed first and direction second I guess.
Is using acceleration reasonable if I only want the motor to run for 1s every 5 minutes?
Here's the modified code I used which only worked in 1 direction:
// 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 = 38;
byte stepPin = 36;
unsigned long curMillis;
unsigned long prevStepMillis = 0;
unsigned long millisBetweenSteps = 1; // milliseconds
void setup() {
Serial.begin(9600);
Serial.println("Starting Stepper Demo with millis()");
pinMode(directionPin, OUTPUT);
pinMode(stepPin, OUTPUT);
}
void loop() {
curMillis = millis();
actOnButtons();
}
void actOnButtons() {
digitalWrite(directionPin, LOW);
singleStep();
digitalWrite(directionPin, HIGH);
singleStep();
}
void singleStep() {
if (curMillis - prevStepMillis >= millisBetweenSteps) {
prevStepMillis = curMillis;
// next 2 lines changed 28 Nov 2018
//prevStepMillis += millisBetweenSteps;
digitalWrite(stepPin, HIGH);
digitalWrite(stepPin, LOW);
}
}
because it will run through so quickly that only the second part will apply. The hint is in the name of the function actOnButtons(). In my program the function contained code to read buttons, but you have taken that out and if you had changed the name of the function the problem might have been more obvious.
Try commenting out the last two lines in the function and see what happens.
Obviously, using millis() for the interval between steps will limit the speed to a max of 1000 steps per second. If you want faster speeds you can use micros() - but I suggest you start with a value of at least 2000 (i.e. 500 steps per second) and gradually reduce the value. At some point the motor will start missing steps because it simply cannot jump instantly from 0 to a high speed.
Robin2:
My comments related to a single motor. You will need more amps if you want to operate more motors.
First things first ... Did my code, with no modifications (apart from pin numbers, perhaps) work in both directions?
I am only ever running a single motor so that is what I was thinking.
I did as you suggested by trying the second code from your post about Simple Stepper Program but I do not have any buttons so the code does not work. (I think I am missing something with how to try out your code)
Robin2:
Try commenting out the last two lines in the function and see what happens.
I have also commented out the last 2 lines from the actOnButtons() function from my modified code and the code works the same (only the 1 direction). I kind of figured it was running too fast to switch directions but wasn't sure how to edit out the buttons to have it work without the need for buttons.
I have also tried the 1st code in your topic and it works well but only down to 1 millisecond delay reliably. I can't get it to work any faster. Even using delayMicroseconds() it skips steps somewhere around the 800 mark. I'm wondering if my load is too heavy to have the motor move it the speed I want.
Robin2:
Obviously, using millis() for the interval between steps will limit the speed to a max of 1000 steps per second. If you want faster speeds you can use micros() - but I suggest you start with a value of at least 2000 (i.e. 500 steps per second) and gradually reduce the value. At some point the motor will start missing steps because it simply cannot jump instantly from 0 to a high speed.
This would be great to try so I can reduce the speed to a point where it is not skipping steps but I need to figure out how to get the non-blocking to work first.
zwieblum:
Most likely it's easiest to install GRBL and send some lines of gcode. If this works, go back to your code.
volkswagenbug:
I have also commented out the last 2 lines from the actOnButtons() function from my modified code and the code works the same (only the 1 direction).
Does it go in the other direction?
If so, then please describe in detail what you want to happen.
As you don't know what GRBL is, just ignore it for now. It would require a lot of learning.
Robin2:
If so, then please describe in detail what you want to happen.
I am hoping for my motor to do 5 full rotations in one direction and then 5 full rotations in the opposite direction all in 1s. This also needs to happen with the load I measured using 1000g.cm torque to move it.
volkswagenbug:
I am hoping for my motor to do 5 full rotations in one direction and then 5 full rotations in the opposite direction all in 1s. This also needs to happen with the load I measured using 1000g.cm torque to move it.
Take things in small steps.
First get the motor to do 5 rotations in one direction (start to stop) in half a second without missing any steps (I'm assuming you mean that you eventually want it to got out and back within a second - i.e. 10 rotations).
Until that works it is pointless trying anything more complicated.
volkswagenbug:
How would you suggest I go about doing this? The modified code I have tried doesn't allow for number of steps control.
You need to do some research and some thinking. The code in the first of my examples makes the motor move a specific number of steps. Have a look at that.
I'm happy to help, but I expect you to do the hard work.
Robin2:
You need to do some research and some thinking. The code in the first of my examples makes the motor move a specific number of steps. Have a look at that.
I'm happy to help, but I expect you to do the hard work.
I completely agree and that is why I did a lot of research before posting for help on these forums. I am very new to Arduino as well as Stepper Motors. I've tried several simple codes that are basically the same as your first code and they all produce the same results. I can get the delay between steps down to 1 millisecond without skipping steps. When I go below this using 500 microseconds every once in while it will act as though it stalls out on 1 of the runs through the code.
I figure my stepper does 200 steps per revolution which would be 1000 steps for 5 revolutions. If I place the delay between steps at 1 millisecond that gives me close to 1000 steps in 1 second. What I need is 1000 steps in 0.5s so logically I would think I need to have the delay set to 500 microseconds.
Here's the code I've used to try and get 5 complete rotations in 500 milliseconds. The reason I have the Enable pin turning on and off is to prevent overheating of my driver and having it shut down. I also placed the delay before pulling enable pin High because the shaft was over-rotating without it. I assume holding torque was lost due to enable being pulled high and the shaft was still spinning.
// 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 = 38;
byte stepPin = 36;
byte EN = 3;
int numberOfSteps = 1000;
byte ledPin = 13;
int pulseWidthMicros = 20; // microseconds
int microsbetweenSteps = 500; // microseconds
void setup() {
Serial.begin(9600);
Serial.println("Starting StepperTest");
digitalWrite(ledPin, LOW);
pinMode(directionPin, OUTPUT);
pinMode(stepPin, OUTPUT);
pinMode(ledPin, OUTPUT);
}
void loop() {
digitalWrite(EN, LOW);
digitalWrite(directionPin, HIGH);
for (int n = 0; n < numberOfSteps; n++) {
digitalWrite(stepPin, HIGH);
delayMicroseconds(pulseWidthMicros); // this line is probably unnecessary
digitalWrite(stepPin, LOW);
delayMicroseconds(microsbetweenSteps);
digitalWrite(ledPin, !digitalRead(ledPin));
}
delay(50);
digitalWrite(EN, HIGH);
delay(5000);
}
volkswagenbug:
When I go below this using 500 microseconds every once in while it will act as though it stalls out on 1 of the runs through the code.
That's because the motor can't go straight from stationary to 2000 steps per second. You need to start at a lower speed, increase beyond 2000 steps per second and then decelerate to a stop.
What happens when you use AccelStepper with the run() command?
Robin2:
What happens when you use AccelStepper with the run() command?
With the code I posted nothing changes using the run() command. I've been trying to use the speedystepper library as well. I can definitely get the motor to turn a lot faster but it is also unreliable. Skips steps or stalls a lot. Is there a sensible method to adjusting the speed and acceleration? I'm not very familiar with using them.
I'm thinking I may not be able to achieve the speeds I am hoping to and be able to move the slide rail at that speed. I have been testing all of this with the motor off the slide rail to just get the speed sorted out.
Here's what sort of works but is still about the same speed as my previous code:
volkswagenbug:
With the code I posted nothing changes using the run() command. I've been trying to use the speedystepper library as well.
This is an example of what I call the scatter-gun approach to debugging - change something, anything, the more things the better. It rarely works.
For all I know the speedystepper library is very good but I know nothing about it and I don't plan to learn it.
Between the code in my examples and the AccelStepper library it will be possible to debug your problem - but only if you take a very cautious systematic approach.
In which of your Replies is the code that you tried using the run() command?
Robin2:
This is an example of what I call the scatter-gun approach to debugging - change something, anything, the more things the better. It rarely works.
Fair enough. I will table the speedystepper Library for now.
Robin2:
In which of your Replies is the code that you tried using the run() command?
I tried it with my original code from the start of this thread with and without setAcceleration() added into it. Obviously without acceleration nothing changes but even with it nothing changed. I'm obviously using the Library incorrectly. Here the code again:
#include <AccelStepper.h>
AccelStepper SM(1, 36, 38);
const int DistanceToMove = 20; // Input Distance in mm
const int MotorSpeed = 1100;
const int DistancePR = 4; // Distance (mm) per 360 degree rotation
const int StepPR = 200; // Steps per 360 degree rotation
const int Rotations = DistanceToMove*StepPR/DistancePR;
void setup() {
SM.setMaxSpeed(4000); // Set the maximum speed in steps per second:
SM.setAcceleration(100);
SM.setEnablePin(3);
SM.setPinsInverted(false, false, true);
SM.disableOutputs(); //Disables Motor Driver Enable Pin
}
void loop() {
SM.enableOutputs(); //Enables Motor Driver Enable Pin
SM.setCurrentPosition(0); // Set the current position to 0 point
while(SM.currentPosition() != -Rotations) // number of steps backward
{
SM.setSpeed(-MotorSpeed); //Motor Speed backward
SM.run();
}
// delay(10);
SM.setCurrentPosition(0); //Resets current position to 0
while(SM.currentPosition() != Rotations) // number of steps forward
{
SM.setSpeed(MotorSpeed); //Motor Speed forward
SM.run();
}
SM.disableOutputs(); //Disables Motor Driver Enable Pin
delay(1000);
}
[\code]
Sent from my iPhone