Hey so i have two stepper motors wired up through two drivers and onto an arduino uno. I am trying to get my robot (powered by the two stepper motors) to complete a number of track movements. I have tried to use the accelstepper library but just cant get the hang of all the commands; so i am trying to do it step by step just using for loops.
In the code below what I thought would happen is it runs through the first for loop, completes it, moves outside it and collects that information then moves into the next for loop. Unfortunately it seems to start at the delay, go through the second for loop and do the 3200 steps then immediately go to the first for loop and then back to the delay. (**NOTE: the code is for one stepper motor as i am just trying to get one working first).
So basically what i want to know is...
Why is it starting with the second for loop when i turn the power on (this will also solve the problem of not delaying between the two for loops)
Help
int Dir = 2;
int Step = 3;
int x = 0;
void setup() {
pinMode(Dir,OUTPUT);
pinMode(Step,OUTPUT);
digitalWrite(Dir, LOW);
digitalWrite(Step, LOW);
}
void loop()
{
for (x; x<=6400; x++)
{
digitalWrite(Step, HIGH);
delayMicroseconds(50);
digitalWrite(Step, LOW);
delayMicroseconds(50);
}
delay(1000);
x=0;
for (x; x<=3200; x++)
{
digitalWrite(Step, HIGH);
delayMicroseconds(100);
digitalWrite(Step, LOW);
delayMicroseconds(100);
}
x=0;
}
The usual way to do a FOR loop is for (int x = 0; x <= 6400; x ++) {
I've never tried it your way so I have no idea whether it should work or not.
For testing it would make sense to do a small number of steps (perhaps 100) and increase the second delay to slow the motor - 50 microseconds is very very short. Also note that the first delay should be very short (perhaps 20 microseconds). Indeed it it not really necessary for most stepper driver boards as the time taken by digitalWrite is usually enough. That would make your FOR loop look like this
for (int x = 0; x <= 100; x++)
{
digitalWrite(Step, HIGH);
delayMicroseconds(20);
digitalWrite(Step, LOW);
delay(5); // milliseconds
}
When it comes to making a real program you will need to replace the delay()s with the technique in the Blink Without Delay example sketch.
Why is it starting with the second for loop when i turn the power on
I don't think it is. There is not much difference between the two loops anyway. The first runs faster than the second.
Try putting on the LED on pin 13 during the first loop and off for the second. I think you will find it doesn't not do the second loop first.
The program is definitely looping through the entire "void loop" section rather than working through the for loops. How do i have to write it so that it goes through the first for loop, finishes it, and then moves on to the next for loop and finishes that one before moving on to the next one and so on?
Your code DOES run through both "fors", there is no doubt about that. But it WILL be looping thru loop() again and again, since that's exactly what loop() does. If you only want it to happen once, move it all into setup().
I took your code and added debug prints as suggested in an earlier post. I reduced the 6400 and 3200 to 6 and 3 for debug purposes. I put a while(1) at the bottom just to "stop" the code and prevent it returning to the top of loop() to let me get only one debug screen full. Here's my debug prints which show without any doubt that both "fors" are being activated with your exact code.
In setup
At top of loop
In 1st for
In 1st for
In 1st for
In 1st for
In 1st for
In 1st for
In 1st for
between the fors
In 2nd for
In 2nd for
In 2nd for
In 2nd for
at bottom of loop
Here's your code intact except for debug prints and the pausing "while" at the bottom:
int Dir = 2;
int Step = 3;
int x = 0;
void setup() {
pinMode(Dir,OUTPUT);
pinMode(Step,OUTPUT);
digitalWrite(Dir, LOW);
digitalWrite(Step, LOW);
Serial.begin(9600); //new
Serial.println("In setup"); //new
}
void loop()
{
Serial.println("At top of loop"); //new
for (x; x<=6; x++) //changed to 6 for debugging
{
Serial.println("In 1st for"); //new
digitalWrite(Step, HIGH);
delayMicroseconds(50);
digitalWrite(Step, LOW);
delayMicroseconds(50);
}
Serial.println("between the fors"); //new
delay(1000);
x=0;
for (x; x<=3; x++) //changed to 3 for debug
{
Serial.println("In 2nd for"); //new
digitalWrite(Step, HIGH);
delayMicroseconds(100);
digitalWrite(Step, LOW);
delayMicroseconds(100);
}
x=0;
Serial.println("at bottom of loop"); //new
while(1){}; //to prevent it looping to limit debug screen
}
EDIT... changed the code slightly to print x as well, which may be useful to see what values are used at the ends of the "for"..
In setup
At top of loop
In 1st for x= 0
In 1st for x= 1
In 1st for x= 2
In 1st for x= 3
In 1st for x= 4
In 1st for x= 5
In 1st for x= 6
between the fors
In 2nd for x= 0
In 2nd for x= 1
In 2nd for x= 2
In 2nd for x= 3
at bottom of loop
Stomper90:
The program is definitely looping through the entire "void loop" section rather than working through the for loops. How do i have to write it so that it goes through the first for loop, finishes it, and then moves on to the next for loop and finishes that one before moving on to the next one and so on?
Please do not call it a void loop. It is a loop function the void is just an indication that it returns no value.
So as I said your code does not do what you think it in fact goes through the first loop first and then the second loop second and then repeates that over and over.
What you have to ask yourself is why you thought otherwise. Please say why you made this mistake as it will help us help others who have a similar misconception.
Stomper90:
Thanks JimboZA, that helped a lot with the understanding.
I merely wrote down what i observed the stepper motors doing just btw ^^
You're welcome.
If the stepper driven by the top "for" isn't doing what you expect (ie, not moving) that might be a wiring fault, or the stepper may be broken, and that would lead you to think the top "for" wasn't activating.
Apart from the valuable debug prints, the suggestion above somewhere to have an led turn on in the top "for" and off in the bottom one would also have shown both were active. (Or a red one on in only the top "for" and a green one on only in the other one, might be a more positive way of showing where the path through the code has gone.)
Surely those of us with experience need to encourage and attempt to help here.. . Lets review what the replys have said..
Declaration of the for loop control variable is not standard in the for statement in any of the ISO standards for C or C ++ it is optional but in fact professional programmers and teaching estsablishments tend to avoid declarations of variables within code segements since documentation is difficult hence maintenance becomes a problem.
Agree don't use Globals AT ALL in fact in a real development enviroment rather than the fiddled Arduino IDE it is generaly not possible to declare Globals.. In test Sketch solutions use them but always beware of code side effects.
Does it matter if we call the loop void answer it majes no difference and to a newbie programmer the fact there is a void in the declaration means its a natural name to give it.
My beef here is that there is no need for prototypes in the IDE you can compile anything the whole essence of C /C++ tight type control has been lost.
For loops are running but running fast, proven by print statements which would distort all meaningful measurements.
Come on chaps lets try and help people on this forum, Arduino is a great teach / learning tool, it also is finding good markets in fast product prototyping the subject of my latest book..
In this case its fairly obvious that the guys got his hardware screwed up, its not a programming problem you can't not execute a for loop unless you fo the clasic
for(; ; ; )
which I suppose some one is going to tell me is invalid but in fact in K&H original bible on C language this the way to create a stop !
Lets ask the question whats the step rate specified for the motors? its probably much slower than his for loop execution and the hardwares simply not responding..
tgsuperspec:
Surely those of us with experience need to encourage and attempt to help here.. . Lets review what the replys have said..
Declaration of the for loop control variable is not standard in the for statement in any of the ISO standards for C or C ++ it is optional but in fact professional programmers and teaching estsablishments tend to avoid declarations of variables within code segements since documentation is difficult hence maintenance becomes a problem.
It is usually regarded as good practice to declare variables with only the scope that they need. Hencefor (int x = 0; x < 255; x++)Where the value of x is unimportant outside of the for loop.
Agree don't use Globals AT ALL in fact in a real development enviroment rather than the fiddled Arduino IDE it is generaly not possible to declare Globals.. In test Sketch solutions use them but always beware of code side effects.
Despite what I said above I believe that globals have a place in the Arduino environment. Not least to avoid the need to pass multiple parameters to functions and to complicate returning multiple results. What is important is sensible and consistent variable names.
Does it matter if we call the loop void answer it majes no difference and to a newbie programmer the fact there is a void in the declaration means its a natural name to give it.
Yes it matters. Calling a function a void shows a fundamental misunderstanding of what a function is
My beef here is that there is no need for prototypes in the IDE you can compile anything the whole essence of C /C++ tight type control has been lost.
How does the lack of function prototypes remove tight type control. If prototypes are important to you then use them. Oh, and you cannot, of course, "compile anything"
For loops are running but running fast, proven by print statements which would distort all meaningful measurements.
The primary problem here was testing whether the for loops were running. Precise timing, if necessary, was a secondary objective.
Come on chaps lets try and help people on this forum, Arduino is a great teach / learning tool, it also is finding good markets in fast product prototyping the subject of my latest book..
What was not helpful in this thread ? Arduino is a great learning tool but it is at its best when you try new things for yourself based on something that worked. When things don't behave as expected then the fun, and much of the learning starts.
In this case its fairly obvious that the guys got his hardware screwed up, its not a programming problem
Not obvious at all
Lets ask the question whats the step rate specified for the motors? its probably much slower than his for loop execution and the hardwares simply not responding..
Hey I've got two stepper motors that I am trying to code through some track movements using the AccelStepper library. I want both stepper motors to go at the same time (apparently they cant actually go at the exact same time) since they are connected to a wheel each and in order to travel in a straight line they need to turn together. What this code is doing is running the first stepper and then the second. I am a newbie so easy on the jargon. I have a feeling it is something to do with the "moveTo" function being blocking? Any way to get them both going at the same time using the AccelStepper library?
Cheers.
Code is below. I removed most of the comments i had made for myself so that it is less clustered for you guys.
Note: I am using two 400 step/rev stepper motors connected to a bigEasy driver each (16 microstep/step default) and then onto an aruino uno board. (Hence the 6400 for the set speed is 1 rev/s)
#include <AccelStepper.h>
// Define a stepper and the pins it will use
AccelStepper stepper1(1, 3, 2); // Left stepper motor with two output pins. 3=step, 2=direction
AccelStepper stepper2(1,5,4); // Right stepper motor with two output pins. 5=step, 4=direction
//setup and initialize speeds and accelerations to be used
void setup()
{
stepper1.setSpeed(6400);
stepper2.setSpeed(6400);
stepper1.setAcceleration(1000);
stepper2.setAcceleration(1000);
}
void loop()
{
//Accelerate off the start line and move in a straight line to the transition zone
stepper1.moveTo(32000);
stepper2.moveTo(32000); // Other motor move to the same place
while (stepper1.currentPosition() != 32000) // Full speed up to 32000
stepper1.run();
stepper2.run();
stepper1.stop();
stepper2.stop();
stepper1.runToPosition();
stepper2.runToPosition();
}
I have a feeling it is something to do with the "moveTo" function being blocking?
No, it isn't. The problem is that you UNCONDITIONALLY stop on every pass through loop. Why? You don't seem to understand what the AccelStepper library does.
The moveTo() method defines a position that the motor is going to try to get to. Then, it returns, without moving the motor AT ALL.
The run() method tells the motor to take a step, if it is not at the destination position, and then it returns.
Then, you stop() both motors. Then, you call a blocking function to make one motor at a time go to it's commanded position.
If you are going to use runToPosition(), you might as well not use AccelStepper.
What you need to do is to, on any given pass through loop(), determine if a new position needs to be sent to the motor (because it got to it's last position). If so, give it a new position to go to. Otherwise, just call run() to step one motor, then the other.
What, exactly, is it you are moving? It doesn't seem like stepper motors are the proper choice.
You shouldn't reset the moveTo position in each iteration of loop(). All that should be in loop() is run
I have no idea what this is supposed to do
while (stepper1.currentPosition() != 32000) // Full speed up to 32000
For testing, try it like this
#include <AccelStepper.h>
// Define a stepper and the pins it will use
AccelStepper stepper1(1, 3, 2); // Left stepper motor with two output pins. 3=step, 2=direction
AccelStepper stepper2(1,5,4); // Right stepper motor with two output pins. 5=step, 4=direction
//setup and initialize speeds and accelerations to be used
void setup()
{
stepper1.setSpeed(6400);
stepper2.setSpeed(6400);
stepper1.setAcceleration(1000);
stepper2.setAcceleration(1000);
stepper1.moveTo(32000);
stepper2.moveTo(32000); // Other motor move to the same place
}
void loop()
{
stepper1.run();
stepper2.run();
}
I don't intend to get into a Semantics / Syntax discussion.
But..
control variables in a for loop do not constitute a scope requirement, if you impose this on the compiler you have to declare them in each loop leading to wasted memory recovery (garbage collection) code which in an Embeded solution wastes resorces.
the usual responce is use a Register control of loops, have you written a compiler? what machines have enough registers to utilise register control idea on loop control variables. None you need to back to virtual register machines or more specifically MM architectures such as the much loved by us old boys the PDP11 from` DEC , but at that time BasIc CoboL / Fortran were king see where I am going things come round..
Protypes are fundimental to any OO Language such as C++ any Professional IDE won't even let the compile stage start unless it can identify prototype and check parameter types.
Globals lead to unstable code, side effects on solutions beyond a few hundred code lines are inevitable.
C++ has no true `Syntax' to allow Global ( out of object scope variable access). Yes they can be fiddled
Obviously a newbie programmer will undoubtable bodge code, until they are shown the light.
But as a professional developer, a lecturer in Software Science, member of the IOS committee on language extensions I have a different view a purest view if we let software development to start to degrade as it did in the 1970/80 spagetti stage that had to be recovered following the demise of Assembler and the rise of original Dartmouth Basic which had ...GOTO .. aH.... Where we get to Block structure then leads to OO and we are back to what we should have know..
Anyway enough on this pointless topic, it does not help someone whose Steppers are not working...