How to detect completion of deceleration?

85 views
Skip to first unread message

chris Fearnley

unread,
Jan 3, 2025, 4:09:01 PMJan 3
to accelstepper
I wish to disable the motor's power as soon as movement has finished. So I need some way of detecting when the deceleration phase has completed. 
After using motor->stop() I have tried a loop of 
    motor->run();
    if (!motor->isRunning() )
         motor->disableOutputs();
but this stops the motor immediately. 
If I just do this:
   motor->stop();
   motor->disableOutputs();
then the motor stops but continues with the deceleration as soon as the motor is enabled again - when I want it to go in the other direction!
How do I test for completed movements?
Thanks for any help.


gregor christandl

unread,
Jan 3, 2025, 5:03:41 PMJan 3
to accels...@googlegroups.com
Hi,

I'd try

> while (motor->run())
> ;
>
> motor->disableOutputs();

@mikem
I'm not sure if the implementation of AccelStepper::isRunning() is
correct - the order of operations seems ambiguous to me.

> bool AccelStepper::isRunning()
> {
> return !(_speed == 0.0 && _targetPos == _currentPos);
> }


maybe rewriting it as
> bool AccelStepper::isRunning()
> {
> return !((_speed == 0.0) && (_targetPos == _currentPos));
> }

could fix this. or maybe check for the step interval as is done in
AccelStepper::runSpeed().


On 03.01.2025 22:09, chris Fearnley wrote:
> I wish to disable the motor's power as soon as movement has finished. So
> I need some way of detecting when the deceleration phase has completed.
> After using *motor->stop()* I have tried a loop of
> *    motor->run();*
> *    if (!motor->isRunning() )*
> *         motor->disableOutputs();*
> but this stops the motor immediately.
> If I just do this:
> *   motor->stop();*
> *   motor->disableOutputs();***
> then the motor stops but continues with the deceleration as soon as the
> motor is enabled again - when I want it to go in the other direction!
> How do I test for completed movements?
> Thanks for any help.
>
>
> --
> 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
> <mailto:accelstepper...@googlegroups.com>.
> To view this discussion visit https://groups.google.com/d/msgid/
> accelstepper/e890b7a1-bcc5-45af-9ae7-32efee26f0e1n%40googlegroups.com
> <https://groups.google.com/d/msgid/accelstepper/e890b7a1-
> bcc5-45af-9ae7-32efee26f0e1n%40googlegroups.com?
> utm_medium=email&utm_source=footer>.

gjgsm...@gmail.com

unread,
Jan 3, 2025, 5:47:34 PMJan 3
to accelstepper
What about...
```
   // 1. Enable outputs if not already
    stepper.enableOutputs();

    // 2. Set a new target, for example 1000 steps away
    stepper.moveTo(1000);
  }

  // 3. Keep calling run() to step the motor. (Non-blocking)
  stepper.run();

  // 4. Check if the motor has stopped
  if (!stepper.isRunning()) {
    // If the motor is no longer running, disable coils
    stepper.disableOutputs();
```

This would be non-blocking but use a 'while()' instead of 'if()' for blocking (Including stepper.run()).

Jim Larson

unread,
Jan 4, 2025, 12:04:54 AMJan 4
to accelstepper
Try this to detect if movement is over.
if (stepper.distanceToGo()==0) {
  // if no more steps to go, then movement is over
  stepper.disableOutputs();
...

Also, it seems worth making Mike's suggest mod and trying it.

             -jim

Mike McCauley

unread,
Jan 4, 2025, 1:52:21 AMJan 4
to accelstepper, Jim Larson
Hi,

On Saturday, 4 January 2025 15:04:54 AEST Jim Larson wrote:
> Try this to detect if movement is over.
> if (stepper.distanceToGo()==0) {
> // if no more steps to go, then movement is over
> stepper.disableOutputs();
> ...
>
> Also, it seems worth making Mike's suggest mod and trying it.


Im not sure thats sufficient, since its possible that the motor is still
decelerating on an overrun as it goes past the target, prior to reversing back
to the target.

Best to use isRunning(), or the return value from run() in order to tell if
the move is completely finished.


>
> -jim
>
> On Friday, January 3, 2025 at 2:47:34 PM UTC-8 gjgsm...@gmail.com wrote:
> > What about...
> > ```
> >
> > // 1. Enable outputs if not already
> >
> > stepper.enableOutputs();
> >
> > // 2. Set a new target, for example 1000 steps away
> > stepper.moveTo(1000);
> >
> > }
> >
> > // 3. Keep calling run() to step the motor. (Non-blocking)
> > stepper.run();
> >
> > // 4. Check if the motor has stopped
> > if (!stepper.isRunning()) {
> >
> > // If the motor is no longer running, disable coils
> > stepper.disableOutputs();
> >
> > ```
> >
> > This would be non-blocking but use a 'while()' instead of 'if()' for
> > blocking (Including stepper.run()).
> >
> > On Saturday, 4 January 2025 at 08:09:01 UTC+11 quil...@gmail.com wrote:
> >> I wish to disable the motor's power as soon as movement has finished. So
> >> I need some way of detecting when the deceleration phase has completed.
> >> After using *motor->stop()* I have tried a loop of
> >> * motor->run();*
> >> * if (!motor->isRunning() )*
> >> * motor->disableOutputs();*
> >> but this stops the motor immediately.
> >> If I just do this:
> >> * motor->stop();*
> >> * motor->disableOutputs();*
> >> then the motor stops but continues with the deceleration as soon as the
> >> motor is enabled again - when I want it to go in the other direction!
> >> How do I test for completed movements?
> >> Thanks for any help.


--
Mike McCauley VK4AMM mi...@airspayce.com
Airspayce Pty Ltd 9 Bulbul Place Currumbin Waters QLD 4223 Australia
http://www.airspayce.com 5R3MRFM2+X6
Phone +61 7 5598-7474



chris Fearnley

unread,
Jan 4, 2025, 5:33:46 AMJan 4
to accelstepper
This suggestion from @gregor works well:
  motor->stop();
  while (motor->run())
     // let deceleration take place
     ;
   motor->disableOutputs();

It's blocking, but only for a second or two. I will add a timer 'get-out' clause in case of any unexpected internal problems.

Both isRunning()  and distanceToGo() methods inside a non-blocking run() loop causes the motor to stop immediately, 
In the latter case the deceleration continues on the next motor activation.

Thank you for all your suggestions. I must say I am pleasantly surprised by the rapid response.
I have an associated problem using the Arduino CNC shield, which isn't about Accelstepper so I shouldn't create a new post in this group -  but but folk here may know of a solution (which i posted on the Arduino forum but nobody has responded)- 

I'm wanting to drive four steppers from the Arduino CNC shield. .The motors will be used in a remote-control device, but not all of the motors will need to run together. It's battery-operated so I need to conserve power.
I have now found that the enable pin (8) on the CNC board is the same one for all for motors. So if I want to use just one motor they all have to be enabled, wasting power .
Apart from attempting to cut tracks on the board and re-wiring to unused Arduino pins, is there a way of achieving my aim?
Reply all
Reply to author
Forward
0 new messages