# Helical interpolation problem using MultiStepper

Hello to all

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

``````// Steppers
AccelStepper xAxis(1, xStepPin, xDirPin);
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
``````

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
``````

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

// Array with axis values for multi stepper function
long xDist = -21000L;
boolean interpolation_ends = false;

// Steppers
AccelStepper xAxis(1, xStepPin, xDirPin);
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);
}

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);

}

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?