Setting a starting speed with slow aceleration.

1,549 views
Skip to first unread message

Jaime Roldan

unread,
May 6, 2015, 3:49:49 PM5/6/15
to accels...@googlegroups.com
Hi, i'm new here and haven't found the solution to my problem.
I'm using the AccelStepper library to driver a linear (captive) stepper. (http://www.omc-stepperonline.com/threaded-rod-nema-17-external-linear-stepper-motor-48mm-body-300mm-t635-x-2-p-225.html) and a TB6600 microstepping driver (set to 16 microsteps per step).
For my case i need the stepper to start a minimum speed (usually around 30 or 40 steps per second) and accelerate very very slowly (0.001 or less steps/s^2) until and endstop is activated.
I have tried runSpeed() to start at a constant speed but it overrides the setAcceleration() command, and using run() start at 0 steps per second. 
Am i missing something? Is there a work around? Or is there any other library that could do this more easily?
Feedback would be very much appreciated.
Best Regards: Jaime.

Sandy Noble

unread,
May 6, 2015, 4:25:06 PM5/6/15
to accels...@googlegroups.com
Hi Jaime, no, there's no simple way around this one. Accelstepper is made to either do acceleration, OR to do steady speeds, preset speeds, and it's hard to mix the two.

That said, if you are able to handle the acceleration yourself (just by incrementing the speed, for instance), you could easily use the "steady speed" functions of accelstepper.


void setup() {
  stepper.setMaxSpeed(1000);
}

void loop() {
  stepper.setSpeed(40);
  while (!endStopHit()) {
    stepper.setSpeed(stepper.speed()*1.01);
    stepper.runSpeed();
  }
}

This still gives you the benefits of accelstepper's speed control and non-blocking-ness.

sn


--
You received this message because you are subscribed to the Google Groups "accelstepper" group.
To unsubscribe from this group and stop receiving emails from it, send an email to accelstepper...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Sandy Noble

Jaime Roldan

unread,
May 6, 2015, 4:54:20 PM5/6/15
to accels...@googlegroups.com
Sandy, thank you for the input.
I'm wondering if the very small increments in the speed are reliable enough movement-wise.
Can runSpeed() output a reliable signal for speeds in the order of say 61.105 steps per second?
I will work around your suggestion, Thank you very much.
Jaime


Sandy Noble

unread,
May 7, 2015, 4:12:58 AM5/7/15
to accels...@googlegroups.com
Should be able to. Well, I'm not sure of the accuracy as I've never needed to have very accurate speeds before, but that precision is certainly available. In terms of maths, it's all floating-point internally, so fractional speeds (0.0001 steps per second) are no problem.

Each call to runSpeed() results in 0 or 1 motor step being fired off. at 60 steps per second, if (1000ms / 60)ms has elapsed since the last time you called runSpeed(), then it'll trigger another step, otherwise runSpeed() will just do nothing. So it doesn't really output a signal as such - or at least it doesn't output a timed stream of pulses. You just call it a lot, and sometimes it triggers a step, sometimes it doesn't.

As long as you are calling runSpeed() much more frequently than you would expect your motor to make steps, you should be ok. Usually, in a loop like the one in the code, runSpeed() will be running at least a few thousand times per second. If you crammed so much other stuff into that loop (LCD writes, or serial reads, or other blocking code) that runSpeed() only got hit 60 times a second, then it it would limit the motor speed to 60 steps per second maximum.

sn

--
You received this message because you are subscribed to the Google Groups "accelstepper" group.
To unsubscribe from this group and stop receiving emails from it, send an email to accelstepper...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Sandy Noble

Mike McCauley

unread,
May 7, 2015, 7:00:56 AM5/7/15
to accels...@googlegroups.com
An excellent summary. 
Cheers



Sent from my iPhone

Jaime Roldan

unread,
May 7, 2015, 10:53:08 AM5/7/15
to accels...@googlegroups.com
That information cleared a lot of my doubts.
I'm wondering if i could use a LUT (look up table) to setSpeed instead of incrementing the speed by a given amount or a given factor.
The problem is that if the stepper is going to be moving for times longer than 1 hour or so, the LUT would be gigantic (considering the 16MHz clock speed on the Arduino MEGA i'm currently using).
Is there any non obtrusive way (in the sense that i would not mess up the runSpeed call) to call setSpeed with the corresponding LUT value every defined amount of time, probably every 1ms-200ms, so i can keep the size of the LUT to a reasonable value?


Sandy Noble

unread,
May 7, 2015, 3:54:24 PM5/7/15
to accels...@googlegroups.com
.setSpeed() is it really, there's no difference between grabbing a value from a lookup and generating it there on the fly.

  float speedLut = {20.0f, 21.001f, 22.023 ... etc };

  long iteration = 0;
  long lastSpeedUpdate = millis();

  while (!endStopHit()) {
    if (millis() > (lastSpeedUpdate + 200)) {
        stepper.setSpeed(speedLut[iteration]);
        iteration++;
        lastSpeedUpdate = millis();
    }
    stepper.runSpeed();
  }

You might be familiar with the kind of pattern above, and maybe that's not what you meant. Essentially here, you keep measuring the time using millis() (which returns the number of milliseconds since the arduino started), and each time another 200 have passed, you will increment your motor speed.

I'm sure you have a good reason for wanting to use a LUT, rather than writing a function, but you're right that it's fairly impractical for arduino - memory is very limited on these chips, and unless there's a truly monumental calculation to make, or you have so much other I/O to do in the same loop, I'd try hard to hammer your algorithm into a function that will calculate it on the fly. OR, you are counting on being able to achieve very high speeds (4000 steps per second+).

#include <AccelStepper.h>

long startTime;
AccelStepper stepper;

void setup() {
  stepper.setMaxSpeed(1000);
}

float generateNewSpeed() {
    long timeSince = millis() - startTime;
    // clever algorithm here
    float newSpeed = stepper.speed() * (timeSince / (timeSince - startTime));
    return newSpeed;
}

void loop() {
  startTime = millis();
  stepper.setSpeed(40);

  while (!endStopHit()) {
    stepper.setSpeed(generateNewSpeed());
    stepper.runSpeed();
  }
}

boolean endStopHit() {
  return false;
}



Not tested, so not sure if it works, but compiles ok.


--
You received this message because you are subscribed to the Google Groups "accelstepper" group.
To unsubscribe from this group and stop receiving emails from it, send an email to accelstepper...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Sandy Noble

Jaime Roldan

unread,
May 7, 2015, 10:11:37 PM5/7/15
to accels...@googlegroups.com
I'm not really sure if the calculation is cumbersome enough to be a problem, i will have to test it.
The goal of accelerating the stepper so slowly (and accurately) is to generate a constant angular speed in a barn door tracker (for long exposure astrophotography).
The type of tracker i'm making is a single-arm drive, (http://dianajuncher.dk/astrophoto/wp-content/uploads/2011/02/bdtracker.jpg)
Since single arm-drive trackers do not have a bended lead screw, the relation between the stepper speed at a given time and the angular speed are not always equal.
Thats the main reason behind the small acceleration, which in theory compensates the system, and allows a constant angular speed.
I haven't calculated the function of the stepper speed in relation to the time, but i do have the function of the distance vs the time, which after derivation becomes the stepper speed.
I'm not an expert in microcontroller calculation cycles, but all trigonometric functions (and their  and to a lesser extent the square root are very expensive on the microcontroller(cycle count wise), hence the idea of the LUT.

Sandy Noble

unread,
May 8, 2015, 4:46:47 PM5/8/15
to accels...@googlegroups.com
I'd definitely give it a shot, with the calculation in situ, and being done in real time. If the speed is fairly low and the calculation is truly huge, then you can always do the thing where you only recalculate the speed every 100ms instead of continuously.

good luck!
sn

--
You received this message because you are subscribed to the Google Groups "accelstepper" group.
To unsubscribe from this group and stop receiving emails from it, send an email to accelstepper...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Sandy Noble

Donny M

unread,
Oct 12, 2015, 7:54:17 PM10/12/15
to accelstepper
I know this is a old post but its a new problem to me.
I need to control a stepper motor by setting a speed value. I need this to be able to ramp up when started and ramp down when set to off. I need it to run for many days at high speed so I think setting a destination value might be a problem.
I am new to programming. I tried playing with the code Sandy posted with the while statement but could not get it to do what I needed. I would like it to accelerate from zero to the set value over a few seconds. Once it hits the speed run at that speed till the speed is changed or till a stop is called.
I have a function called pump1Disable that calls stepper.Stop(); but the while is a bool and it won't let me use that.
Can someone point me in the right direction.

Donny

Mike McCauley

unread,
Oct 12, 2015, 8:41:49 PM10/12/15
to accels...@googlegroups.com
Hi. That's not  really a use case that  AccelStepper was designed to meet. 

I think they only way it might work for you guys do to set a really large target position. Depending on your stepping rate it might do. 4 billion is rather a lot. 

Sent from my iPhone
Reply all
Reply to author
Forward
0 new messages