Accel Stepper, Sequential Stepper Motor Movements

I am using the Accelstepper library in order to control four stepper motors that are responsible for precise vehicle movement.

Using this library I have created functions that work when called individually and make the motors perform certain actions. When these functions are called sequentially as shown in the attached code I think the motors are receiving all of the signals from the functions at the same time. In other words, it's not waiting for one function to complete before moving onto the next function.

I have tried troubleshooting this with no luck!

I need to be able to call each function sequentially as the robot vehicle is moving different directions on a track in a certain order.

Any help would be greatly appreciated!

Master.cpp (5.91 KB)

OP's code so others don't have to download the file

/*

// Vehicle Displacement
	Wheels are 6cm in diameter, therefore 1 wheel revolution = a vehicle displacement of 18.85cm
	therefore forward backward movement of 1m requires 1061 motor steps. Testing will be needed for horizontal and diagonal motion
*/

#include <Arduino.h>
#include <AccelStepper.h>
#include <stdio.h>
#include <avr/io.h>
#include <stdlib.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <string.h>
#include <MHZ19.h> //Serial

#define pin 10

const int steps = 200;  	//Steps of 1.8 degrees, 360/1.8 = 200 steps per full rotation

// Create Instance of Stepper library
AccelStepper stepperFL(AccelStepper::FULL4WIRE, 8, 9, 10, 11);        				//Front Left Stepper
AccelStepper stepperFR(AccelStepper::FULL4WIRE, 7, 6, 5, 4);        				//Front Right Stepper
AccelStepper stepperBL(AccelStepper::FULL4WIRE, PIN_A0, PIN_A1, PIN_A2, PIN_A3);    //Back Left Stepper
AccelStepper stepperBR(AccelStepper::FULL4WIRE, 0, 1, 2, 3);        				//Back Right Stepper


//Function Prototypes
void moveLateral(float, int);
void moveAxial(float, int);
void rotate(int, int);
void trigger(void);

int n = 0;

void setup()
{
	//Motors
		//Set the acceleration(steps per second)
	int accel = 600;
	stepperFL.setAcceleration(accel);
	stepperBL.setAcceleration(accel);
	stepperFR.setAcceleration(accel);
	stepperBR.setAcceleration(accel);

	//Trigger function
	pinMode(2, OUTPUT);
	digitalWrite(2, LOW);
}


void loop()
{

//Warman
	int speed = 300;

	//Move out of the garage towards the ocean compound
	moveLateral(1, 10);

	//Lower elevator into compound
	trigger();


	moveLateral(-1.5, speed);
	_delay_ms(100);

	//Move along the compound & scoop up balls
	moveAxial(1, speed);
	_delay_ms(100);

	//Raise elevator out of compound
	trigger();

	//Move to the right of the compound to allow room for rotation
	moveLateral(0.5, speed);
	_delay_ms(100);

	//Rotate 90 degrees to face inland compound
	rotate(90, speed);

	//Move toward inland compound stopping with enough room to allow for rotation
	moveAxial(3, speed);
	_delay_ms(100);

	//Rotate to align balls with inland compound
	rotate(90, speed);
	_delay_ms(100);

	//Align adjacent to inland compound
	moveLateral(-0.5, speed);
	_delay_ms(100);

	//Lower elevator to be flush with inland compound
	trigger();

	//Release payloads
	trigger();

	//Reset
	delay(5000);
	trigger();

}


//Function that commands the vehicle to move forwards or backward depending on inputs
	//POSITIVE and NEGATIVE distance values will move the robot FORWARDS and BACKWARDS respectively.
void moveAxial(float distance, int speed)
{

	//Determine necessary steps for input distance
	int reqSteps = distance * 1061;

	//Command motors to move required amount of steps at desired rpm
	stepperFL.moveTo(reqSteps);
	stepperBL.moveTo(reqSteps);
	stepperFR.moveTo(reqSteps);
	stepperBR.moveTo(reqSteps);

	// set the speed at input rpm:
	stepperFL.setMaxSpeed(speed);
	stepperBL.setMaxSpeed(speed);
	stepperFR.setMaxSpeed(speed);
	stepperBR.setMaxSpeed(speed);

	//Run steppers
	for(int i = 0; i < abs(reqSteps); i++)
	{
		stepperFL.run();
		stepperFR.run();
		stepperBL.run();
		stepperBR.run();
	}

}


//Function that commands the vehicle to move right or left depending on inputs
	//POSITIVE and NEGATIVE distance values will move the robot RIGHT and LEFT respectively.
void moveLateral(float distance, int speed)
{

	//Determine necessary steps for input distance
	int reqSteps = 1000; //formula needs to be determined through testing------------------------------------------------------------------------

	// set the speed at input rpm:					//Speed ramping may be necessary
	stepperFL.setMaxSpeed(speed);
	stepperBL.setMaxSpeed(speed);
	stepperFR.setMaxSpeed(speed);
	stepperBR.setMaxSpeed(speed);

	//Determine which direction motors need to spin
	if (distance > 0)
	{
	//Command vehicle to rotate CW by making left motors run forwards and right motors run backwards
	stepperFL.moveTo(reqSteps);
	stepperBL.moveTo(-reqSteps);
	stepperFR.moveTo(-reqSteps);
	stepperBR.moveTo(reqSteps);

	//Run steppers
		for(int i = 0; i < abs(reqSteps); i++)
		{
			stepperFL.run();
			stepperBL.run();
			stepperFR.run();
			stepperBR.run();
		}
	}

	else
	{
	//Command vehicle to rotate CCW by making right motors run forwards and left motors run backwards
	stepperFL.moveTo(-reqSteps);
	stepperBL.moveTo(reqSteps);
	stepperFR.moveTo(reqSteps);
	stepperBR.moveTo(-reqSteps);

	//Run steppers
		for(int i = 0; i < abs(reqSteps); i++)
		{
			stepperFL.run();
			stepperBL.run();
			stepperFR.run();
			stepperBR.run();
		}
	}
}

//Function that commands the vehicle to rotate CW or CCW depending on inputs
	//POSITIVE and NEGATIVE degree values will move the robot CW and CCW respectively.
void rotate(int degrees, int speed)
{

	//Determine necessary steps for input distance
	int reqSteps = 1000; //formula needs to be determined through testing------------------------------------------------------------------------

	// set the speed at input rpm:					//Speed ramping may be necessary
	stepperFL.setMaxSpeed(speed);
	stepperBL.setMaxSpeed(speed);
	stepperFR.setMaxSpeed(speed);
	stepperBR.setMaxSpeed(speed);

	//Determine which direction motors need to spin
	if (degrees > 0)
	{
	//Command vehicle to rotate CW by making left motors run forwards and right motors run backwards
	stepperFL.moveTo(reqSteps);
	stepperBL.moveTo(reqSteps);
	stepperFR.moveTo(-reqSteps);
	stepperBR.moveTo(-reqSteps);

		//Run steppers
		for(int i = 0; i < abs(reqSteps); i++)
		{
			stepperFL.run();
			stepperBL.run();
			stepperFR.run();
			stepperBR.run();
		}
	}

	else
	{
	//Command vehicle to rotate CCW by making right motors run forwards and left motors run backwards
	stepperFL.moveTo(-reqSteps);
	stepperBL.moveTo(-reqSteps);
	stepperFR.moveTo(reqSteps);
	stepperBR.moveTo(reqSteps);

		//Run steppers
		for(int i = 0; i < abs(reqSteps); i++)
		{
			stepperFL.run();
			stepperBL.run();
			stepperFR.run();
			stepperBR.run();
		}
	}
}

void trigger()
{
	digitalWrite(pin, HIGH);
	delay(10);
	digitalWrite(pin, LOW);
}

...R

You should not be using delay() or FOR (or WHILE) with AccelStepper. All of those block the Arduino.

Just put stepper.run() for each motor in loop()

If you need to check that a motor has completed a movement use stepper.distanceToGo() - it will be 0 when the stepper move is complete.

If stepperB is to start when stepperA finishes you could use code something like this

if (stepperA.distanceToGo() = 0) {
   stepperAStopped = true;
}
if (stepperBStopped == true and stepperAStopped == true) {
   stepperB.move(XXXX);
   stepperBStopped = false;
}

...R

It depends how far you are going with this project. If this is all the functions it is going to do (move lateral, axial etc) then you could make those blocking functions. Just use while(stepperFL.distanceToGo()>0 && ...) Instead of for().

But every project grows. Maybe you are going to add some blinky lights or sensors to avoid objects. Then you must avoid blocking functions and rewrite it more like Robin's suggestions.

deanocko:
I am using the Accelstepper library in order to control four stepper motors that are responsible for precise vehicle movement.

Using this library I have created functions that work when called individually and make the motors perform certain actions. When these functions are called sequentially as shown in the attached code I think the motors are receiving all of the signals from the functions at the same time. In other words, it's not waiting for one function to complete before moving onto the next function.

Yes, AccelStepper is like that, it does all the work in the background via the run() method. You are responsible for sequencing and timing the calls to set the movement target (moveTo(), move()).

So you'll need to do something, either checking with millis() when the next task needs to start, or using something like:

void wait_for_stepper_completion()
{
  while (stepperFL.distanceToGo() != 0 ||
         stepperFR.distanceToGo() != 0 ||
         stepperBL.distanceToGo() != 0 ||
         stepperBR.distanceToGo() != 0)
  {
    stepperFL.run();
    stepperFR.run();
    stepperBL.run();
    stepperBR.run();
  }
}

That's pretty neat. Intermediate between the two approaches already suggested. It removes a lot of copy-paste code and makes one function.

Additional blinky lights could be put into that function if required.

Thanks for all of the help so far, that last reply worked perfectly and is allowing me to do sequential movements.

I've since run into a different problem which I think is again due to my poor understanding of how AccelStepper works. When I call a movement function (lateral/axial) or the lift function individually they work as intended. If I integrate the lift motor into the movement functions, all five motors will run together, so it's not an issue with power. When trying to run a movement function followed by the lift function the lift fails to run. The motor is audibly attempting to run although it isn't able to.

Again, thanks for the help!

#include <Arduino.h>
#include <AccelStepper.h>
#include <stdio.h>
#include <avr/io.h>
#include <stdlib.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <string.h>
#include <MHZ19.h> //Serial

#define pin 12

const int steps = 200;  	//Steps of 1.8 degrees, 360/1.8 = 200 steps per full rotation

// Create Instance of Stepper library
AccelStepper stepperFL(AccelStepper::FULL4WIRE, 14, 15, 16, 17);        //Front Left Stepper
AccelStepper stepperFR(AccelStepper::FULL4WIRE, 8, 9, 10, 11);        	//Front Right Stepper
AccelStepper stepperBL(AccelStepper::FULL4WIRE, 0, 1, 2, 3);    		//Back Left Stepper
AccelStepper stepperBR(AccelStepper::FULL4WIRE, 7, 6, 5, 4);        	//Back Right Stepper
AccelStepper stepperLift(AccelStepper::FULL4WIRE, 12, 13, 19, 18);  //Front Left Stepper

int defaultSpeed = 300;
int speed = 300;
int accel = 60000;
int liftSpeed = 600;

//Function Prototypes
void moveLateral(float, int=defaultSpeed);
void moveAxial(float, int=defaultSpeed);
void rotate(int, int=defaultSpeed);
void waitForCompletion(void);
void waitForElevator(void);
void moveLift(float distance, int speed=defaultSpeed);
void setPosition();
void trigger(void);
void stop();

void setup()
{
	//Motors
		//Set the acceleration(steps per second)
	stepperFL.setAcceleration(accel);
	stepperBL.setAcceleration(accel);
	stepperFR.setAcceleration(accel);
	stepperBR.setAcceleration(accel);
	stepperLift.setAcceleration(accel);

	//Trigger function
	pinMode(pin,OUTPUT);
	pinMode(LED_BUILTIN,OUTPUT);
	digitalWrite(pin, LOW);
	digitalWrite(LED_BUILTIN, LOW);
}

void loop()
{

	//Move out of the garage towards the ocean compound
	delay(3000);
	moveLateral(0.5);
	delay(3000);
	moveLift(0.5);
	delay(1000);
	stop();

}


void moveAxial(float distance, int speed=defaultSpeed)
{

	//Determine necessary steps for input distance
	int reqSteps = 1000; //formula needs to be determined through testing------------------------------------------------------------------------

	// set the speed at input rpm:					//Speed ramping may be necessary
	stepperFL.setMaxSpeed(speed);
	stepperBL.setMaxSpeed(speed);
	stepperFR.setMaxSpeed(speed);
	stepperBR.setMaxSpeed(speed);

	//Test
	stepperLift.setMaxSpeed(speed);

	//Determine which direction motors need to spin
	if (distance > 0)
	{

	stepperFL.move(reqSteps);
	stepperBL.move(-reqSteps);
	stepperFR.move(-reqSteps);
	stepperBR.move(reqSteps);

	}

	else
	{

	stepperFL.move(-reqSteps);
	stepperBL.move(reqSteps);
	stepperFR.move(reqSteps);
	stepperBR.move(-reqSteps);

	}

	//Run steppers
	waitForCompletion();
}

//Function that commands the vehicle to move right or left depending on inputs
	//POSITIVE and NEGATIVE distance values will move the robot RIGHT and LEFT respectively.
void moveLift(float distance, int speed=defaultSpeed)
{

	//Determine necessary steps for input distance
	int reqSteps = 1000; //formula needs to be determined through testing------------------------------------------------------------------------

	// set the speed at input rpm:					//Speed ramping may be necessary
	stepperLift.setMaxSpeed(speed);

	//Determine which direction motors need to spin
	if (distance > 0)
	{
	//Test
	stepperLift.move(reqSteps);
	}

	else
	{

	//Test
	stepperLift.move(-reqSteps);
	}

	//Run steppers
	waitForCompletion();
}

//Function that commands the vehicle to rotate CW or CCW depending on inputs
	//POSITIVE and NEGATIVE degree values will move the robot CW and CCW respectively.
void rotate(int degrees, int speed=defaultSpeed)
{

	//Determine necessary steps for input distance
	int reqSteps = 1000; //formula needs to be determined through testing------------------------------------------------------------------------

	// set the speed at input rpm:					//Speed ramping may be necessary
	stepperFL.setMaxSpeed(speed);
	stepperBL.setMaxSpeed(speed);
	stepperFR.setMaxSpeed(speed);
	stepperBR.setMaxSpeed(speed);

	//Determine which direction motors need to spin
	if (degrees > 0)
	{
	//Command vehicle to rotate CW by making left motors run forwards and right motors run backwards
	stepperFL.moveTo(reqSteps);
	stepperBL.moveTo(reqSteps);
	stepperFR.moveTo(-reqSteps);
	stepperBR.moveTo(-reqSteps);

	}

	else
	{
	//Command vehicle to rotate CCW by making right motors run forwards and left motors run backwards
	stepperFL.moveTo(-reqSteps);
	stepperBL.moveTo(-reqSteps);
	stepperFR.moveTo(reqSteps);
	stepperBR.moveTo(reqSteps);

	}
	//Run steppers
	waitForCompletion();

}

void waitForCompletion()
{
  while (stepperFL.distanceToGo() != 0 ||
         stepperFR.distanceToGo() != 0 ||
         stepperBL.distanceToGo() != 0 ||
		 stepperLift.distanceToGo() != 0 ||
         stepperBR.distanceToGo() != 0)
  {
    stepperFL.run();
    stepperFR.run();
    stepperBL.run();
    stepperBR.run();

	//Test
	stepperLift.run();
  }
}


void trigger()
{
  digitalWrite(pin, HIGH);
  digitalWrite(LED_BUILTIN, HIGH);
  delay(10);
  digitalWrite(pin, LOW);
  delay(90);
  digitalWrite(LED_BUILTIN, LOW);
}

void stop()
{
	delay(1000000);
}

/*void setPosition()
{
	stepperFL.setCurrentPosition(stepperFL.currentPosition());
    stepperFR.setCurrentPosition(stepperFR.currentPosition());
    stepperBL.setCurrentPosition(stepperBL.currentPosition());
    stepperBR.setCurrentPosition(stepperBR.currentPosition());
	stepperLift.setCurrentPosition(stepperLift.currentPosition());
}*/

You are saying that moveLateral followed by moveLift doesn't work but moveLift followed by moveLateral does work?

Test it, please.

I suspect the lift motor needs different max speed and/or acceleration settings as its mechnically different.

Thanks again for the replies. This was for the 2019 Warman challenge project as a part of a university subject.
Turns out the issue was with the power which I find baffling because all five steppers could be run simultaneously but trying to run one on it's own wouldn't work?? Seems I need to improve my understanding of electronics.

Thanks, everyone!