I am trying to run three stepper motors simultaneously, with each stepper motor having a different number of steps to move. Right now, that means a loop for each motor, that repeats as many times as the variable needs counting up to a number, each loop triggering a pin high, then low, to perform one step of the stepper motor.
When I do it that way, the first motor loop runs, moving that motor the desired number of steps, stops, then the next loop runs, moving the second motor the desired number of steps. The result is undesirable because each motor moves separately.
What I would like, is for all three motors to start moving at the same time. Naturally, the motor with no movement or least movement will stop moving first.
Any suggestions on how to structure a loop so that the three variables count one step each, then second step each, and so on, with each one stopping as its count is reached?
What I would like, is for all three motors to start moving at the same time.
The AccelStepper library supports that requirement. What it does not do is assure that all three motors work together to move the tool tip in a straight line.
The MultiStepper library does.
Any suggestions on how to structure a loop so that the three variables count one step each, then second step each, and so on, with each one stopping as its count is reached?
By far, the simplest way is to NOT use a for loop. The loop() function already loops. On any given iteration through loop(), it may, or may not, be necessary to move the X stepper, the Y stepper, or the Z stepper. And, on any given pass through loop(), it may, or may not, be time to step the X stepper, the Y stepper, or the Z stepper.
You do not post any code, so it is hard to see where you fail. The task should be fairly easy, though, since you only need one for loop and in that loop you check if the steppers have reac..
#define STEPPER1_MAX 20
#define STEPPER2_MAX 50
#define STEPPER3_MAX 100
int pos = 0;
bool incrementing = true;
void loop() {
if (incrementing)
{
byte done = 0;
pos++;
if (pos < STEPPER1_MAX) setStepper1(pos);
else done++;
if (pos < STEPPER2_MAX) setStepper2(pos);
else done++;
if (pos < STEPPER3_MAX) setStepper3(pos);
else done++;
if (done == 3) incrementing = false;
} else {
pos--;
if (pos < STEPPER1_MAX) setStepper1(pos);
if (pos < STEPPER2_MAX) setStepper2(pos);
if (pos < STEPPER3_MAX) setStepper3(pos);
if (pos == 0) incrementing = true;
}
//delay(100);
}
Thanks, I had no idea that those libraries existed.
That makes sense about using the loop() for that purpose. Here I had structured it with a function that contained three loops. Dumb on my part. Diverting the program to a loop that ties it up while it moves the steppers.
No laughter please! :o I couldn't post the whole code as it was too long. This is the function called to in the void loop:
void motorMove () {
// Firstly for base motor J1
if (AngleThetaOne <= 180) J1newPosition = (110 - AngleThetaOne) * StepsPerDegreeOne;
if (AngleThetaOne > 180) J1newPosition = (470 - AngleThetaOne) * StepsPerDegreeOne;
if (J1position < J1newPosition) {
J1move = (J1newPosition - J1position);
digitalWrite(J1dirPin, HIGH); // clockwise
}
if (J1position >= J1newPosition) {
J1move = (J1position - J1newPosition);
digitalWrite(J1dirPin, LOW); // counter clockwise
}
for ( X = 0; X < J1move; X ++) // adjust position by J1move
{
digitalWrite(J1stepPin, LOW);
delayMicroseconds(500);
digitalWrite(J1stepPin, HIGH);
}
J1position = J1newPosition; // reset J1postion to new
// end code for base motor J1
// Secondly for J2
J2newPosition = (99 - AngleThetaTwo) * StepsPerDegreeTwo;
if (J2position < J2newPosition) {
J2move = J2newPosition - J2position;
digitalWrite (J2dirPin, LOW); // forward
digitalWrite (J3dirPin, LOW); // J3 to follow
}
if (J2position >= J2newPosition) {
J2move = J2position - J2newPosition;
digitalWrite (J2dirPin, HIGH); // arm back
digitalWrite (J3dirPin, HIGH); // J3 to follow
}
for ( Y = 0; Y < J2move; Y ++) // adjust position by J2move // also J3 to follow
{
digitalWrite(J2stepPin, LOW);
digitalWrite(J3stepPin, LOW); // J3 to follow
delayMicroseconds(500);
digitalWrite(J2stepPin, HIGH);
digitalWrite(J3stepPin, HIGH); // J3 to follow
}
J2position = J2newPosition; // reset J2 position to new
// end code for J2
// code for J3
// note still need to make J3 corrected by J2 movement
J3newPosition = (abs(AngleThetaThree) -80 ) * StepsPerDegreeThree;
if (J3position < J3newPosition) {
J3move = J3newPosition - J3position;
digitalWrite (J3dirPin, LOW); // forward
}
if (J3position >= J3newPosition) {
J3move = J3position - J3newPosition;
digitalWrite (J3dirPin, HIGH); // arm back
}
for ( Z = 0; Z < J3move; Z ++) // adjust position by J3move
{
digitalWrite(J3stepPin, LOW);
delayMicroseconds(500);
digitalWrite(J3stepPin, HIGH);
}
J3position = J3newPosition; // reset J3 position to new
// end code for J3
Serial.print ("Steps to move J1 from start ");
Serial.println (J1position);
Serial.print ("Steps to move J2 from start ");
Serial.println (J2position);
Serial.print ("Steps to move J3 from start ");
Serial.println (J3position);
}
The AccelStepper library has a good way of doing it: one function sets the destination and another does a 1-step move towards the destination.
Look at doing that in your code: step all 3 steppers as required but return quickly to the main loop (after each step) so the main loop can check the sensors and make decisions.
With run() do you have to keep looping through it to move each step?
With runspeedtoposition() does it only need to read that line once and it keeps moving towards the specified position?
How do you zero the position? Is there a command to zero the current position?
With run() do you have to keep looping through it to move each step?
You should call run() on every pass through loop(), for every stepper. The run() method will determine if the stepper needs to step, and, if so, if it is time to step again.
With runspeedtoposition() does it only need to read that line once and it keeps moving towards the specified position?
Pretend that it is necessary to proof-read your questions, to make sure that they make sense. Because it IS.
The question is ambiguous, because NOTHING "reads that line" but the compiler, which is long done by the time the Arduino starts running. There is NO runspeedtoposition() method. There IS one with a similar name, but soMe capItaL letters ranDomlY placed in the nAme. THAT method only needs to be called once, because it blocks until the stepper motor has gotten to the commanded position.