Timing of two stepper motors movement

Hi
I'm trying to make a little camera rig. It's basically one stepper motor moving the camera left and right along a track and another panning it.
In my code I can set three positions for the two motors and move between the positions with button presses.
What I can't seem to figure out is how to get the two motors to reach their destinations at the same time.
I submit my code for perusal and ridicule. It's most likely fairly poorly written.
Tips on other general improvements on the code is also appreciated.

#include <Bounce2.h>
#include <AccelStepper.h>

AccelStepper dolly(1, 9, 8);
AccelStepper pan(5, 26, 27, 28, 29);
Bounce limitRightState = Bounce();
Bounce limitLeftState = Bounce();
Bounce buttonOneState = Bounce();
Bounce buttonTwoState = Bounce();
Bounce buttonThreeState = Bounce();
Bounce buttonFourState = Bounce();
int dollyAcc = 300;
int dollySpeed = 300;
int panAcc = dollyAcc;
int panSpeed = dollySpeed;
int fullLeft = 0;
int fullRight = 0;
int middle = 0;
int lookHome = 0;
int lookAway = 0;
int lookMiddle = 0;
int dollyReturnPosition = 0;
int panReturnPosition = 0;
boolean isReturnPositionSet = false;
boolean bounce = false;
boolean ledOn = LOW;
boolean isHomeSet = false;
boolean isAwaySet = false;
boolean calibrated = false;
boolean finalCal = false;
boolean oneLastState = LOW;
boolean twoLastState = LOW;
boolean threeLastState = LOW;
boolean fourLastState = LOW;
boolean limitRightLastState = HIGH;
boolean limitLeftLastState = HIGH;
const int ledPin = 13;
const int buttonOnePin = 31;
const int buttonTwoPin = 32;
const int buttonThreePin = 33;
const int buttonFourPin = 34;
const int limitRightPin = 30;
const int limitLeftPin = 35;

void setup() 
{
  pinMode (buttonOnePin, INPUT);
  pinMode (buttonTwoPin, INPUT);
  pinMode (buttonThreePin, INPUT);
  pinMode (buttonFourPin, INPUT);
  pinMode (limitRightPin, INPUT);
  pinMode (limitLeftPin, INPUT);
  limitRightState.attach(limitRightPin);
  limitLeftState.attach(limitLeftPin);
  buttonOneState.attach(buttonOnePin);
  buttonTwoState.attach(buttonTwoPin);
  buttonThreeState.attach(buttonThreePin);
  buttonFourState.attach(buttonFourPin);
  limitRightState.interval(5);
  limitLeftState.interval(5);
  buttonOneState.interval(5);
  buttonTwoState.interval(5);
  buttonThreeState.interval(5);
  buttonFourState.interval(5);
  pinMode (ledPin, OUTPUT);
  dolly.setMaxSpeed(1000);
  dolly.setAcceleration(500);
  pan.setMaxSpeed(1000);
  pan.setAcceleration(500);
 }
   
 void loop()
 { 
   buttonOneState.update();
   buttonTwoState.update();
   buttonThreeState.update();
   buttonFourState.update();
   limitLeftState.update();
   limitRightState.update();
   
   if (buttonFourState.rose() == HIGH && isHomeSet == false && isAwaySet == false)
   {
     if (buttonFourState.read() != fourLastState)
     {
       dolly.move(50000);
     }
   }
   
   if (buttonFourState.rose() == HIGH && isHomeSet == true && isAwaySet == false)
   {
     if (buttonFourState.read() != fourLastState)
     {
       dolly.move(-50000);
     }
   }
   
   if (buttonFourState.rose() == HIGH && calibrated == true)
   {
     if(buttonFourState.read() != fourLastState)
     {
       bounce = !bounce;
       ledOn = ! ledOn;
       
       if (isReturnPositionSet == true)
       {
        isReturnPositionSet = false;
       }
     }
   }
   
   if (limitLeftState.fell() == HIGH && isHomeSet == true && isAwaySet == false)
   {
     if (limitLeftState.read() != limitLeftLastState)
     {
       dolly.setAcceleration(10000);
       dolly.stop();
       dolly.runToPosition();
       dolly.move(100);
       dolly.runToPosition();
       fullLeft = dolly.currentPosition();
       isAwaySet = true;
       middle = fullLeft/2;
     }
   }
   
   if (limitRightState.fell() == HIGH && isHomeSet == false && isAwaySet == false)
   {
     if (limitRightState.read() != limitRightLastState)
     {
       dolly.setAcceleration(10000);
       dolly.stop();
       dolly.runToPosition();
       dolly.move(-100);
       dolly.runToPosition();
       dolly.setCurrentPosition(0);
       fullRight = dolly.currentPosition();
       isHomeSet = true;
     }
   }
   
   if (buttonOneState.rose() == HIGH && isHomeSet == true && isAwaySet == true && calibrated == false && finalCal == true)
   {
     if (buttonOneState.read() != oneLastState)
     {
       lookMiddle = pan.currentPosition();
       digitalWrite(13, HIGH);
       delay(1000);
       digitalWrite(13, LOW);
       calibrated = true;
       dolly.setAcceleration(dollyAcc);
       pan.setAcceleration(panAcc);
       dolly.setMaxSpeed(dollySpeed);
       pan.setMaxSpeed(panSpeed);
     }
   }
   
   if (buttonOneState.rose() == HIGH && isHomeSet == true && isAwaySet == false)
   {
     if (buttonOneState.read() != oneLastState)
     {
       pan.setCurrentPosition(0);
       lookHome = pan.currentPosition();
       digitalWrite(ledPin, HIGH);
       delay(500);
       digitalWrite(ledPin, LOW);
       delay(500);
       digitalWrite(ledPin, HIGH);
       delay(500);
       digitalWrite(ledPin, LOW);
     }
   }
   
   if (buttonOneState.rose() == HIGH && isHomeSet == true && isAwaySet == true && calibrated == false && finalCal == false)
   {
     if (buttonOneState.read() != oneLastState)
     {
       lookAway = pan.currentPosition();
       digitalWrite(ledPin, HIGH);
       delay(500);
       digitalWrite(ledPin, LOW);
       delay(500);
       digitalWrite(ledPin, HIGH);
       delay(500);
       digitalWrite(ledPin, LOW);
       delay(500);
       digitalWrite(ledPin, HIGH);
       delay(500);
       digitalWrite(ledPin, LOW);
       dolly.moveTo(middle);
       finalCal = true;
     }
   }
   
   if (buttonTwoState.rose() == HIGH && calibrated == false)
   {
     if(buttonTwoState.read() != twoLastState)
    {
     pan.move(-100);
    }
   }
  
   if (buttonThreeState.rose() == HIGH && calibrated == false)
   {
     if(buttonThreeState.read() != threeLastState)
    {
     pan.move(100);
    }
   }
   
   if (buttonTwoState.rose() == HIGH && calibrated == true)
   {
     if(buttonTwoState.read() != twoLastState)
    {
     dolly.moveTo(middle);
     pan.moveTo(lookMiddle);
     
     if (bounce == true)
     {
       dollyReturnPosition = dolly.currentPosition();
       panReturnPosition = pan.currentPosition();
       
       isReturnPositionSet = true;
       }
     }
   }
  
   if (buttonThreeState.rose() == HIGH && calibrated == true)
   {
     if(buttonThreeState.read() != threeLastState)
    {
     dolly.moveTo(fullRight);
     pan.moveTo(lookHome);
     
     if (bounce == true)
     {
       dollyReturnPosition = dolly.currentPosition();
       panReturnPosition = pan.currentPosition();
       
       isReturnPositionSet = true;
       }
    }
   }
   
   if (buttonOneState.rose() == HIGH && calibrated == true)
   {
     if(buttonOneState.read() != oneLastState)
    {
     dolly.moveTo(fullLeft);
     pan.moveTo(lookAway);
     
     if (bounce == true)
     {
       dollyReturnPosition = dolly.currentPosition();
       panReturnPosition = pan.currentPosition();
       
       isReturnPositionSet = true;
       }
    }
   }
   
   if (bounce == true && isReturnPositionSet == true)
   {
     if (dolly.distanceToGo()== 0)
     {
      dolly.moveTo(dollyReturnPosition);
      dollyReturnPosition = dolly.currentPosition();
     }
     if (pan.distanceToGo()== 0)
     {
      pan.moveTo(panReturnPosition);
      panReturnPosition = pan.currentPosition();
     }
   }
   digitalWrite(ledPin, ledOn);
   dolly.run();
   pan.run();
}

Put in some Serial.prints and use it to tell you what is happening, rather than what you think is happening. You should be able to debug it that way. You may want to only print every say, 1 second since you're in a tight loop.

So something like (untested):

unsigned long lastmillis;

void loop()
{
 if (millis() - lastmillis > 1000)
 {
      lastmillis = millis; 
      serial.print("useful data");
 }
}

I have been looking at some data from the steppers. My query is more about how I implement this data.
The motors need to move different amounts of steps, but arrive at their destination at the same time.
For example.
I reset stepper position and set position one for the steppers.
Then I move to position two and set it.
For stepper one, this is 1200 steps.
For stepper two, this is 80 steps.
Now I need stepper two to do its 80 steps in the same amount of time as stepper one uses on its 1200 steps.
I hope I'm not misunderstanding something in your answer.

I have the same issue with code for my small CNC system. The solution I have found is to calculate the time the motor with the most steps will need to reach its destination.

Say it needs 534 steps with 5 millisecs between steps - that means a total of 2670 msecs.
If the other motor needs to make 233 steps in the same time then each of its steps must happen at 2670/233 msec intervals or 11.46 msecs per step - use microsecs if great accuracy is required.

Then set up a timing process (using millis() or micros() as appropriate) to figure out the time when each step should be taken. The timing process I use is the same as illustrated in several things at a time. It works just as well using micros() when necessary.

Note that this means that your code gets the motor to move one step at a time rather than giving a number of steps to the AccelStepper library which is not intended for this type of application.

...R

I figured out how to get it to work by mapping the values to the same interval and then slaving the second stepper to the first.
Stepper ones 0-1200 steps are mapped to 0-1000.
Stepper twos 0-80 are also mapped to 0-1000 and slaved.
I don't know if this makes any sense.

I did this and it works.

dollyCentMap = map(dolly.currentPosition(), 0, dollyDistance, 0, 1000);
panFollow = map(dollyCentMap, 0, 1000, 0, panDistance);

-

pan.moveTo(panFollow);

Can you show all the code - or at least all that is necessary to get the steppers to move ?

It may be useful for others.

...R