pkerspe/ESP-FlexyStepper

Using emergencyStop(true) and releaseEmergencyStop

ba58smith opened this issue · 10 comments

I would like to be able to emergencyStop() in the middle of a "trip" (from 0 to 300mm, for example), then after a pause, releaseEmergencyStop() and have the "trip" pick up where it left off. But I see that processMovement() sets directionOfMotion to 0, and (more important) sets targetPositionInSteps = currentPositionInSteps, which terminates the original "trip".

If I want to just resume where I left off, should I use the callbacks associated with emergencyStop() and releaseEmergencyStop() to store the current position and direction and maybe speed/accel/decel, and then resume that original journey with the callback associated with releaseEmergencyStop()?

Thanks!

Hi @ba58smith,
using the callbacks should be possible, since they are called before the actual positions/parameters are reset.
I do not see that it should be part of the library to resume operation with the previous parameters, once an emergency stop is released.
Imagine a machine that is stopped due to an emergency and after a while of fixing the cause of the emergency or while still fixing it, someone releases the emergency stop: the machine would continue a possibly high velocity operation and might injure somebody who is still in the machines way.

The callback methods though should give you the right entry points to store and restore operation parameters

@pkerspe - I absolutely agree that restarting where you left off shouldn't be the default behavior. But maybe another version of emergencyStop() that WOULD save all the parameters, so that releaseEmergencyStop() COULD pick up where it left off? Or, maybe safer, always have emergencyStop() save those parameters, but have two versions of releaseEmergencyStop() - one that does exactly what it currently does, and another: releaseEmergencyStop(bool resumeStoppedJourney). If you would consider adding this to the library, I will look into making a PR for it. (But if you won't add it, I won't bother with the PR, and will just use the callbacks in my current project.)

Thanks so much for your prompt reply!

I guess the route you described, making it a separate function call to resume, could be an option.
Feel free to submit a PR.
Yet keep in mind, that once the Emergency Stop is triggered, it is of highest priority to stop ASAP, so when saving current parameters, as little CPU Cycles as necessary should be used for saving the current values. (this applies basically to the mode where the library is started as a service and the processMovement function is called by the service thread)

Understood. Right now, it does this:

void ESP_FlexyStepper::emergencyStop(bool holdUntilReleased) {
  this->holdEmergencyStopUntilExplicitRelease = holdUntilReleased;
  this->emergencyStopActive = (!this->motionComplete() || this->holdEmergencyStopUntilExplicitRelease);
  if (this->_emergencyStopTriggeredCallback) {
    this->_emergencyStopTriggeredCallback();
  }
}

If I attach a callback, I can make it do whatever I want, and it could take a long time - which would delay the stopping of the motor. Maybe modify it like this:

 if (this->_emergencyStopTriggeredCallback) {
    this->_emergencyStopTriggeredCallback();
  }
else {
   this->saveCurrentParameters();
}

void saveCurrentParameters() {
    this->saved_isOnWayToHome = this->isOnWayToHome;
    this->saved_isOnWayToLimit = this->isOnWayToLimit;

    this->saved_ currentStepPeriod_InUS = currentStepPeriod_InUS;
    this->saved_nextStepPeriod_InUS = nextStepPeriod_InUS;
    this->saved_directionOfMotion = directionOfMotion;
    this->saved_targetPosition_InSteps = targetPosition_InSteps;
}

Will saveCurrentParameters() run fast enough to not cause a problem? Because that's what my callback function will do - unless I don't need to save all of those parameters - I haven't looked at each of them closely. Those are just all of the ones that are changed at the top of processMovement() if emergencyStopActive == true.

Maybe we should add a flag to enable this saveCurrentParameter option in general. So it would be up to the user if he wants a "resume after emergency stop" mode or not. That way we could only call the "saveCurrentParameters" when the flag is true.
Also I would not call it in an else statement, since this might lead to confusion on user side that his logic with resuming only works as long as he does not attach a callback (that might have a complete different purpose than just saving the current position, e.g. users could use this to turn a warning light on or something like that, and they might want to combine that with the resume functionality)

Both good points. I'll make a flag, and then check the flag before saving, instead of always saving in the else. Thanks!

Working on the PR for this, but I may have come upon a show stopper. When emergencyStop() is called, processMovement() looks for a configured brake, and if it's not yet activated, it is now activated. The fact that there is the possibility of an external braking mechanism makes me wonder "Does the motor ever keep turning after an emergencyStop() is issued, simply because of the momentum of whatever the motor is turning?" (In my application, it's a piston going back and forth on a threaded rod.)
Because if it does, or can, keep turning after the emergencyStop() - even if it's just a few more steps - I think there's any way to know that it did that, correct? And if that's the case, resuming the previous movement after an emergencyStop() could result in the motor (or whatever the motor is moving) overrunning it's target, correct? Is there any way around this?
Thanks for your input. I'm making good progress on the PR, until I thought of this particular "gotcha".

@ba58smith You are right, if a stepper spins at high speed and maybe even has some load attached, it is very likely that an emergency stop will result in the stepper overshooting. Precision after an emergency stop does not have highest priority, but coming to the quickest possible way to come to a halt.
It is probably a good idea to perform a homing run after an emergency stop from higher speeds.
The idea of the motor brake (besides other purposes) goes in the direction to limit (or eliminate if the break is quick and strong enough) the overshooting in such a case. In general you are right though, that precision is at risk after an emergency stop.

If you are not using a closed loop stepper motor setup, your software will not know about the overshooting and you might need to re-home the setup

@pkerspe - even if you ARE using a closed loop stepper, FlexyStepper won't know about those "extra steps", will it? The motor (or the motor controller) will know, but does FlexyStepper have a way to get that info from the motor(controller)?. I don't see a way to get it. Thx. (The PR is almost ready. This question is just for the comments.)

Fleecy stepper does not care about closed loop, it the would be a basic requirement to have such system before thinking about precision :-)