Helical interpolation problem using MultiStepper

Hello to all

Building an helical interpolation under MultiStepper.h using XA axes:

// Steppers
AccelStepper xAxis(1, xStepPin, xDirPin);
AccelStepper aAxis(1, aStepPin, aDirPin);
MultiStepper XAaxes;

Based on a 105 milimeters distance for X and -64,7º for A, that results on the following target positions based on real steps:

// Array with axis values for multi stepper function
long xDist = -21000L; // Steps for x axis
long aDist = -40747L; // Steps for a axis
long posXA[2] = {xDist, aDist};

And the following motion function:

XAaxes.moveTo(posXA);
// Interpolate until all axes reaches its targets positions
while(xAxis.currentPosition() != posXA[0] || aAxis.currentPosition() != posXA[1]){
  XAaxes.run();
}

A problem arises:

Helical motion is executed until the following XA position:

X pos at end of interpolation: -20374 (but target is -21000)
A pos at end of interpolation: -40747 (= target position)

And then moves X axis alone, breaking the helix, until their target pos (-21000).

I can fix this last not interpolated X motion, changing “||” condition by “&&” inside motion function, making steppers stop when interpolation ends at X(-20374) A(-40747):

XAaxes.moveTo(posXA);
// Interpolate only while any axis reaches its end
while(xAxis.currentPosition() != posXA[0] && aAxis.currentPosition() != posXA[1]){
  XAaxes.run();
}

But even though this avoid the non interpolation motion, the executed helicoidal motion from XA {0,0} to XA {-20374, -40474} does not generate the correct helix, because interpolation must execute -40474 A axis steps for -21000 X axis steps, not -20374.

So my question is:

Why MultiStepper.cpp does not interpolate A through all X travel? Have MultiStepper some kind of error? Does anyone know how to fix this?

I leave the full test program in a file below, if anyone want to test it. It use serial monitor. These are the serial monitor prints

***************
moveToRunXA:
***************

INIT interpolated movement
init X pos (currentPos): 0   target X pos (posXA[0]): -21000
init A pos (currentPos): 0   target A pos (posXA[1]): -40747

END interpolated movement
current X pos: -20374
current A pos: -40747
From here, the movement is not interpolated..

END of a single axis motion
end X pos: -21000
end A pos: -40747

Many thanks in advance.

helicoidal_interpolation.ino (2.57 KB)

#include <AccelStepper.h>
#include <MultiStepper.h>
#include <math.h>

// Stepper pins
#define xStepPin 14
#define xDirPin 15
#define aStepPin 7
#define aDirPin 1

// Array with axis values for multi stepper function
long xDist = -21000L;
long aDist = -40747L;
long posXA[2] = {xDist, aDist};
boolean interpolation_ends = false;

// Steppers
AccelStepper xAxis(1, xStepPin, xDirPin);
AccelStepper aAxis(1, aStepPin, aDirPin);
MultiStepper XAaxes;


void setup(){
  delay(1000);
  Serial.begin(9600);
  delay(1000);
  initPins();
  initSteppers();
  
  // Execute multi stepper function
  moveToRunXA();
}

void loop(){ 
}

void initPins(){
  pinMode(xStepPin, OUTPUT);
  pinMode(xDirPin, OUTPUT);
  pinMode(aStepPin, OUTPUT);
  pinMode(aDirPin, OUTPUT);
}

void initSteppers(){
  xAxis.setMaxSpeed(2000);
  xAxis.setSpeed(2000);
  xAxis.setAcceleration(2000);
  xAxis.setCurrentPosition(0);
  xAxis.setMinPulseWidth(5);
  
  aAxis.setMaxSpeed(1800);
  aAxis.setSpeed(1800);
  aAxis.setAcceleration(1800);
  aAxis.setCurrentPosition(0);
  aAxis.setMinPulseWidth(5);
  
  XAaxes.addStepper(xAxis);
  XAaxes.addStepper(aAxis);
}

void moveToRunXA(){
  serialMonitorPrint1();
  XAaxes.moveTo(posXA);
  // Interpolate onlye while any axis reaches its end
  while(xAxis.currentPosition() != posXA[0] || aAxis.currentPosition() != posXA[1]){
    XAaxes.run();
    if(!interpolation_ends){
      if(xAxis.currentPosition() == posXA[0] || aAxis.currentPosition() == posXA[1]){
        serialMonitorPrint2();
        interpolation_ends = true;
      }
    }
  }
  serialMonitorPrint3();
}

void serialMonitorPrint1(){
  Serial.println("\n***************\nmoveToRunXA:\n***************");
  Serial.println("");
  Serial.println("INIT interpolated movement");
  Serial.print("init X pos (currentPos): ");
  Serial.print(xAxis.currentPosition());
  Serial.print("   target X pos (posXA[0]): ");
  Serial.println(posXA[0]);
  Serial.print("init A pos (currentPos): ");
  Serial.print(aAxis.currentPosition());
  Serial.print("   target A pos (posXA[1]): ");
  Serial.println(posXA[1]);
  Serial.print("\n");  
}

void serialMonitorPrint2(){
  Serial.println("END interpolated movement");
  Serial.print("current X pos: ");
  Serial.println(xAxis.currentPosition());
  Serial.print("current A pos: ");
  Serial.println(aAxis.currentPosition());
  Serial.println("From here, the movement is not interpolated..");
}

void serialMonitorPrint3(){
  Serial.println("\nEND of a single axis motion");
  Serial.print("end X pos: ");
  Serial.println(xAxis.currentPosition());
  Serial.print("end A pos: ");
  Serial.println(aAxis.currentPosition());
}

You are setting fixed speeds for each axis. Those speeds need to be tightly coordinated.

Concerted multi-axis movement is a harder problem than you think - the acceleration ramping
has to be coordinated too, otherwise the spatial relationships will be lost.

MarkT:
You are setting fixed speeds for each axis. Those speeds need to be tightly coordinated.

Concerted multi-axis movement is a harder problem than you think - the acceleration ramping
has to be coordinated too, otherwise the spatial relationships will be lost.

About the speeds: So, what should I do in order not to set a fixed speed? Uncomment .setMaxSpeed(), .setSpeed() and/or .setAcceleration()?

About the accelerations: MultiStepper::moveTo method executes a non accelerated movements. Each axis starts and ends at his MultiStepper::moveTo precalculated speed. At least for me. There is someway to make MultiStepper::moveTo accelerated?