accelstepper not taking the new speed

Hi all,

I am using accellstepper and multistepper to move 2 steppers to a predefined destination. During this move I have to constantly change the speed.

Situation: steppers are Moving constantly with the "moveTo" command. Both steppers should arrive at the same time. If I do not change the speed, then it works perfectly.

Then I try to change the speed every second with this code:

        steppertheta.setMaxSpeed(maxStepsPerSecond);
        stepperrho.setMaxSpeed(maxStepsPerSecond);

Nothing happens. According to the documentation, when setMaxSpeed is called, it should automatically call computeNewSpeed();.

so i tried this:

   steppertheta.setMaxSpeed(maxStepsPerSecond);
   stepperrho.setMaxSpeed(maxStepsPerSecond);
   steppers.moveTo(positions);

and pass the "positions" like before. This updates the speed properly, but it messes with the movement. If I keep calling the moveTo, the motion is not linear anymore. one motor arrives way before the other.

How am i suposed to do in order to update the speed of my motors while they are running?

Thank you!"

Best reagrds
Igor

The setMaxSpeed() function is used with acceleration. MultiStepper does not use acceleration. Have you tried the setSpeed() function?

Please post code that is verifiable and shows the problem.

Thank you for your answer!

its my understanding that the multistepper calculates the speeds when you call the moveTo() command. Whne it calculates these, the calculated values are capped by the values set with setMaxSpeed(). I have been able to test and confirm this, So since the values are calculated automatically, I can use the setMaxSpeed, and the motor that will run faster of the both will use this speed.

The problem is that if i just change "setMaxSpeed()" while the motors are already running, nothing happens. I would need it to calculate the new speed for both motors, but without calling moveTo() again.

My code is too long to post and contains tons of irrelevant things, so I would have to clean it up and post a "testcode".. Will do it ASAP..

Thank you for your time!

best regards

Igor

ok, here is the samplecode…

all the calculations are corerct, so just ignore the functions that calculate the needed values…
how it works: the motors move on a circle, and have a certain distance to the center point (currRadius). whenever the currRadius increases by 1, i want to update the speed of the motors. that is what the “updateSpeed()” function does.

the cunction “updateSpeed()” itself works, but sometimes, (like in this sample) if i Call updateSpeed then one motor drives to the end, and then the other drives to the end. they do not move simultaneously…

#include <SPI.h>
#include <SD.h>
#include <AccelStepper.h>
#include <MultiStepper.h>
#include <WiFi.h>
#include <fauxmoESP.h>

File myFile;

#define MOTOR_STEPS 200
#define GEAR_MULTIPLIER 4
#define MICROSTEPS 16
#define FULLARMLENGTH 200.0
int stepsPer01mm;

double destinationTheta = 0;
double destinationRho = 0;
double Speed = 10; //mm / s
double currRadius;
double currAngle;
double spiralSlope;
double spiralRotation;
double spiralRotationRad;
double nextDestTheta;
double nextDestRho;
double nextRadDestTheta;
double next01DestRho;
double ballspeed;
double maxStepsPerSecond;
double maxStepsPerSecondLimit = 5000;
double maxStepsPerSecondLimitInner = 2000;
double distCurrStep;
double prevDestTheta = 0;

int oldRadius;

unsigned long myTime;
fauxmoESP fauxmo;

bool getNextDestination = true;
bool hasFile = false;
bool runtable = true;
bool runtableold = true;
bool iscircle = false;
bool setZero = false;
bool gotValidLine = false;
File root;
int tempcounter = 0;

int temp = 0;

AccelStepper stepperrho(AccelStepper::DRIVER, 26, 27);
AccelStepper steppertheta(AccelStepper::DRIVER, 32, 33);
MultiStepper steppers;

int thetaPos = 34;
int rhoPos = 35;
int disableSteppers = 25;
int updateSpeedCounter = 0;
int speedchangeCounter = 0;
int currRadiusInt = 0;

long startPosTheta = 0;
long startPosRho = 0;
long endPosTheta = 0;
long endPosRho = 0;
long startPosThetaMm = 0;
long startPosRhoMm = 0;
long endPosThetaMm = 0;
long endPosRhoMm = 0;


long positions[2]; // Array of desired stepper positions


String readString;

void setup() {
  // put your setup code here, to run once:

  pinMode(thetaPos, INPUT);
  pinMode(rhoPos, INPUT);
  pinMode(disableSteppers, OUTPUT);

  
  steppertheta.setMaxSpeed(1000);
  stepperrho.setMaxSpeed(1000);
  steppertheta.setSpeed(1000);
  stepperrho.setSpeed(1000);
  //reset positions

  ballspeed = 50; //mm/s
  // Then give them to MultiStepper to manage

  steppers.addStepper(steppertheta);
  steppers.addStepper(stepperrho);



  nextDestTheta = 360*25;
  nextDestRho = 1;
  PolarToSteps(nextDestTheta, nextDestRho);
  startPosTheta = destinationTheta;
  startPosRho = destinationRho;
  positions[0] = destinationTheta;
  positions[1] = destinationRho;
  steppers.moveTo(positions);
  while (steppers.run())
  {
      updatespeed();
  }

}

/////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////LOOOOOOOPPPPP!!!!!!!/////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////

void loop() {




}

void updatespeed()
{


  curPosToThetaRho(steppertheta.currentPosition(), stepperrho.currentPosition());
  currRadiusInt = ceil(currRadius);
  if (oldRadius != currRadiusInt)
  {
    speedchangeCounter ++;
  }
  else
  {
    speedchangeCounter = 0;
  }

  if (speedchangeCounter > 2)
  {
    curPosToThetaRho(steppertheta.currentPosition(), stepperrho.currentPosition());
    setBallSpeed();
    steppertheta.setMaxSpeed(maxStepsPerSecond);
    stepperrho.setMaxSpeed(maxStepsPerSecond);
    steppers.moveTo(positions);


    oldRadius = currRadiusInt;
    speedchangeCounter = 0;

  }
}

void curPosToThetaRho (double currThetaSteps, double currRhoSteps)
{
  //takes the current stepper positions and calculates the theta and rho values in degrees and mm.

  double deltasteppers = currThetaSteps - currRhoSteps;
  if (deltasteppers == 0)
  {
    currRadius = 0;
  }
  else if (deltasteppers == 6400)
  {
    //fully stretched
    currRadius = FULLARMLENGTH;
  }
  else
  {
    double beta =  (deltasteppers * 360) / (MOTOR_STEPS * GEAR_MULTIPLIER * MICROSTEPS) ;
    double alpha = (180 - beta) / 2;

    currRadius = (FULLARMLENGTH / 2 * sin(beta * PI / 180)) / sin(alpha * PI / 180);

  }
  currAngle = 360.0 * (currThetaSteps - (deltasteppers / 2)) / (MOTOR_STEPS * GEAR_MULTIPLIER * MICROSTEPS);

  /* Serial.println("currAngle **** ");
    Serial.println(currAngle);*/
}

void PolarToSteps(double theta, double rho)
{
  //calculates the destination of the steppers in steps.

  //calculate angle from rho
  double radius = rho * FULLARMLENGTH;
  double beta;
  if (rho > 0) {
    if (rho == 1)
    {
      beta = 180;
    }
    else
    {
      // alpha = acos(((radius * radius) / (2 * radius * 100))*PI/180) * 180 / PI;
      beta = acos(((((FULLARMLENGTH / 2) * (FULLARMLENGTH / 2)) * 2 - (radius * radius)) / (2 * (FULLARMLENGTH / 2) * (FULLARMLENGTH / 2)))) * 180 / PI;

    }
  }
  else
  {
    beta = 0;
  }


  double destinationThetaDegTemp = theta + beta / 2;
  double destinationRhoDegTemp = destinationThetaDegTemp - beta ;
  destinationTheta = destinationThetaDegTemp / 360 * MOTOR_STEPS * GEAR_MULTIPLIER * MICROSTEPS;
  destinationRho = destinationRhoDegTemp / 360 * MOTOR_STEPS * GEAR_MULTIPLIER * MICROSTEPS;
}





void setBallSpeed()
{

  double radiusCalc = currRadius;
  if (radiusCalc == 0)
  {
    radiusCalc = 0.1;
  }
  //calculate the diameter where the ball is:
  double circumference = radiusCalc * 2 * PI;

  //calculate steps/mm horizontally
  int stepsOneTurn = (MOTOR_STEPS * GEAR_MULTIPLIER * MICROSTEPS);
  double stepsMmH = stepsOneTurn / circumference;

  //calculate the max Steps if we move purely horizontally
  double maxStepsPerSecondH = ballspeed * stepsMmH;


  //calculate the radius where the ball will be in 1 mm, Assumption: we are always moving outwards. it does not make much difference in real life.
  if (radiusCalc > 198)  //just to be safe on the outer ring
  {
    radiusCalc = 198;
  }
  double radiusNew = radiusCalc + 1;


  //calulate the steps/mm vertically
  double steps90Deg = (MOTOR_STEPS * GEAR_MULTIPLIER * MICROSTEPS) / 4;
  double currAngle = acos((radiusCalc * radiusCalc) / (2 * 100 * radiusCalc));
  double nextAngle = acos((radiusNew * radiusNew) / (2 * 100 * radiusNew));
  double deltaAngleRad = currAngle - nextAngle;
  double deltaAngleDeg = deltaAngleRad / PI * 180;

  double stepsMmV = (steps90Deg / 90.0) * deltaAngleDeg;

  //calculate the max Steps if we move purely vertically
  double maxStepsPerSecondV = ballspeed * stepsMmV;


  //calculate the angle we are moving to.
  //  long delta_theta = abs(endPosTheta - startPosTheta);
  //  long delta_rho = abs(endPosRho - startPosRho);
  long delta_theta = abs(endPosThetaMm - startPosThetaMm);
  long delta_rho = abs(endPosRhoMm - startPosRhoMm);
  double angleRad = atan2(delta_rho, delta_theta);
  double angleDeg = angleRad / PI * 180;

  double HxV = (maxStepsPerSecondH * maxStepsPerSecondV);
  double HSq = (maxStepsPerSecondH * maxStepsPerSecondH);
  double sinSq = (sin(angleRad) * sin(angleRad));
  double VSq = (maxStepsPerSecondV * maxStepsPerSecondV);
  double cosSq = (cos(angleRad) * cos(angleRad));
  double HSqXsinSq = HSq * sinSq;
  double VSqXcosSq = VSq * cosSq;
  double SqrtHV = sqrt(HSqXsinSq + VSqXcosSq);

  maxStepsPerSecond = HxV / SqrtHV;

  if (currRadius<100)
  {
  if (maxStepsPerSecond > maxStepsPerSecondLimitInner)
  {
    maxStepsPerSecond = maxStepsPerSecondLimitInner;
  }
    
  }
  else
  {
  if (maxStepsPerSecond > maxStepsPerSecondLimit)
  {
    maxStepsPerSecond = maxStepsPerSecondLimit;
  }
  }
 
}

Update! if I lower the distance it has to travel it works… also if I remove the line

 currRadius = (FULLARMLENGTH / 2 * sin(beta * PI / 180)) / sin(alpha * PI / 180);

it also works. I just have to change one of the two things and it works… so it looks like if I am running out of memory… Could that be?

the calculation above has all perfectly valid values and returns a reasonable value.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.