gin66 / FastAccelStepper

A high speed stepper library for Atmega 168/328p (nano), Atmega32u4, Atmega 2560, ESP32, ESP32S2, ESP32S3, ESP32C3 and Atmel SAM Due
MIT License
282 stars 67 forks source link

new feature request:runSpeed(int speed); like AccelStepper #248

Closed ChinaBurn closed 2 months ago

ChinaBurn commented 2 months ago

I was wondering if it would be possible to add a method that runs based on a given speed

gin66 commented 2 months ago

runSpeed() from AccelStepper is not using acceleration. So not sure, if this is requested.

A possible implementation (without error checking and not compiler tested):

func runSpeedInHz(int32_t speed_in_Hz, FastAccelStepper *stepper) {
    if (speed == 0) {
         stepper->stopMove();
    }
    else {
         if (stepper > 0) {
              stepper->setSpeedInHz(speed_in_Hz);
              stepper->runForward();
         }
         else {
              stepper->setSpeedInHz(-speed_in_Hz);
              stepper->runBackward();
         }
    }
}

Now this implementation for every setSpeedInXxx() variant (without stepper parameter) and maintaining another variable for the user callled setSpeedInXxx() for the absolute maximum speed.

ChinaBurn commented 2 months ago

Thank you for your reply. I have just tried the idea you mentioned. It can basically achieve the function, but compared to accelstepper's runspeed(), the motor movement is delayed.

gin66 commented 2 months ago

which is the delay ?

Any change in speed takes approx. 10ms for being applied (forward planning in 4ms cyclic task). From one speed value to the next value, acceleration/deceleration is performed, which can take even longer.

ChinaBurn commented 2 months ago

It may be more than 10ms. I visually estimated that the corresponding delay is between 20~50ms. Although I adjusted the acceleration very large, the delay was still not reduced. I am using the as5600 magnetic encoding chip to obtain the angular velocity. The delay under runSpeed() is very small, and it can almost be considered a real-time response. Part of your code is as follows:

if ((int)FinalMotorSpeed == 0) {
    stepper->stopMove();
  } else {
    if ((int)FinalMotorSpeed > 0) {
      stepper->setSpeedInHz((int)FinalMotorSpeed);
      stepper->runForward();
    } else {
      stepper->setSpeedInHz(-(int)FinalMotorSpeed);
      stepper->runBackward();
    }
  }
gin66 commented 2 months ago

I had the forward planning time incorrectly in mind. It is actually 20ms.

There could be now two options:

  1. Forward planning time could be a configurable option. Perhaps down to 5ms. This could cause issues on slower AVR parts or on esp32 due to task blocking.
  2. There is kind of an equivalent to runSpeed() by using low level API calls on queue level. But this is more difficult to be controlled by application and requires, that the application ensures, that the queue does not run out of commands. Acceleration and deceleration from ramp generator would not be available anymore. If queue filling is ensured, then the reaction time can come down to two times the command length.
gin66 commented 2 months ago

First point 1 is tracked here: #253

For point 2, there has not been any update.

=> Close this issue