Motor turns in wrong direction for a brief period upon change if direction when using acceleration

262 views
Skip to first unread message

Kevin Barron

unread,
Mar 28, 2021, 11:54:46 AM3/28/21
to accelstepper
I have a problem using acceleration. Everything works nicely except when I come to the point where the motor changes direction. The motor runs for a brief period in the wrong direction before running nicely in the correct direction. 

The code below works fine if I edit it for constant speed. However, I'm using this library because I want a nicer look to how it runs smoothly with acceleration. 
I am new to this and I have tried looking through this group for similar questions/answer to no avail.

I've stripped down my code to the bare bones below. Basically the program homes and then opens a curtain until a limit switch triggers and then closes a curtain until a limit switch triggers. Thanks for any help/thoughts.

#include "AccelStepper.h" 
AccelStepper stepperX(1, 9, 8);   
#define home_switch 2 // Pin 2 connected to Curtain Closed 
#define open_switch 3 // Pin 3 connected to Curtain Open Switch 
long TravelX = 0;  // 
long position;
int incomingByte = 0;
void setup() {
  Serial.begin(9600); 
  pinMode(home_switch, INPUT_PULLUP);
  pinMode(open_switch, INPUT_PULLUP);
  delay(5);  
  stepperX.setAcceleration(100.0);
  stepperX.setMaxSpeed(200.0);    
  stepperX.setSpeed(100.0);    
  while (digitalRead(home_switch)) {  
    stepperX.runSpeed();
    delay(5);
  }
  stepperX.setCurrentPosition(0);
  Serial.println("Curtain Homed and Closed");
}
void loop() {
  while (Serial.available() > 0)  { // Check if values are available in the Serial Buffer
    Serial.println("Curtain Open Start");
    incomingByte = Serial.read();
    while (digitalRead(open_switch)) {  // Make the Stepper move CCW to open curtain until the switch is activated   
      stepperX.moveTo(-99999);
      stepperX.run();
    }
 Serial.println("Curtain Open Finished");
//PUT PLAY CODE HERE
 Serial.println("Show is on");
 delay(2000);
 Serial.println("Curtain Close Start");
    while (digitalRead(home_switch)) {  // Make the Stepper move CW to close curtain until the switch is activated   
      stepperX.moveTo(99999);
      stepperX.run(); 
    }
    Serial.println("Curtain Closed Finished");
  }
}

 

Kevin Barron

unread,
Mar 28, 2021, 3:31:29 PM3/28/21
to accelstepper
I should point out this isn't the stepper drift that will happen. It doesn't happen if I use a constant speed. It seems to only happen when I try to use Accelerate.

gjgsm...@gmail.com

unread,
Mar 28, 2021, 6:16:54 PM3/28/21
to accelstepper
Give this a go. Just a suggestion, not tested...

A couple of points to consider:
  1. Don't put any 'serial' data transactions in a 'while' loop or any loop with the 'stepperX.run()' as this will interrupt the running of the stepper. Simple 'math' statements are ok.
  2. If you are using acceleration, setSpeed is not necessary, just use either setMaxSpeed() or setAcceleration or a combination of both to control the stepper. As an example - if you have a high 'setMaxSpeed()' and a low 'setAcceleratio()', the stepper may not get to your MaxSpeed, instead it may just accelerate slowly to the travel mid-point and then deccelerate slowly to the target.
Geoff

-------------------------------------------------------------------------------------------------------------------------------------------------------
#include "AccelStepper.h" 
AccelStepper stepperX(1, 9, 8);

#define home_switch 2 // Pin 2 connected to Curtain Closed 
#define open_switch 3 // Pin 3 connected to Curtain Open Switch

long TravelX = 0;  // 
long position;
int incomingByte = 0;


void setup()
{
  Serial.begin(9600);
  
  pinMode(home_switch, INPUT_PULLUP);
  pinMode(open_switch, INPUT_PULLUP);
   
  stepperX.setAcceleration(100.0);
  stepperX.setMaxSpeed(200.0);
 
 stepperX.moveTo(99999);
  
  while (digitalRead(home_switch))
  {  
    stepperX.run();
  }
  stepperX.setCurrentPosition(0);
  
  Serial.println("Curtain Homed and Closed");
}


void loop()
{
  Serial.println("Curtain Open Start");
  
  while (Serial.available() > 0)  // Check if values are available in the Serial Buffer
  { 
   incomingByte = Serial.read();

   stepperX.moveTo(-99999);

    while (digitalRead(open_switch))  // Make the Stepper move CCW to open curtain until the switch is activated   
   {
      stepperX.run();
    }
Serial.println("Curtain Open Finished");
Serial.println("Show is on");
delay(2000);
Serial.println("Curtain Close Start");
 
stepperX.moveTo(99999);  //   OR YOU COULD JUST USE: stepperX.moveTo(0); to go back to 'Home' position.
  
    while (digitalRead(home_switch))  // Make the Stepper move CW to close curtain until the switch is activated
   {

Kevin Barron

unread,
Mar 28, 2021, 7:40:57 PM3/28/21
to accelstepper
Thank you so much for replying. I tried your suggested code but the same thing is happening.
I'm wondering how I can explain clearly. It's at the point in the logic when I need to close the curtain (I've pasted the point in the code below - stepperX.run(); ).
The code sets the moveTo to 99999 and runs until the limit switch triggers.....however when the 2 second delay is over instead of immediately starting to turn CCW it runs CW for about a quarter of a turn and then runs correctly CCW. It's almost as if it still has some unfinished deceleration buffered command that completes and then it reverses to the correct rotational direction.

Thanks for any help.
Kevin




stepperX.moveTo(99999);  //   OR YOU COULD JUST USE: stepperX.moveTo(0); to go back to 'Home' position.
  
    while (digitalRead(home_switch))  // Make the Stepper move CW to close curtain until the switch is activated
   {
      stepperX.run(); 
    }
    Serial.println("Curtain Closed Finished");

gjgsm...@gmail.com

unread,
Mar 28, 2021, 9:01:09 PM3/28/21
to accelstepper
Accelstepper remembers the stepper motor 'step' position. See below, I have inserted a serialPrint to get the 'open' step position, it may provide a clue. This number will of course be dependant on stepper motor steps/rev (probably 200) and any driver fractional stepping setting.

Alternatively, you can clear the step position by calling -
stepperX.setCurrentPosition(0);
... after the reaching the open position.

----------------------------------------------------------------------------------------------------------------------------
void loop()
{
  Serial.println("Curtain Open Start");
  
  while (Serial.available() > 0)  // Check if values are available in the Serial Buffer
  { 
  
   incomingByte = Serial.read();
   
    stepperX.moveTo(-99999);

    while (digitalRead(open_switch))  // Make the Stepper move CCW to open curtain until the switch is activated   
{
      stepperX.run();
    }
Serial.println(stepperX(currentPosition());

//  stepperX.setCurrentPosition(0);
-------------------------------------------------------------------------------------------------------------------

Kevin Barron

unread,
Mar 29, 2021, 8:42:16 AM3/29/21
to accelstepper
Perfect. That was it. 
I inserted the position reset to zero after the limit switch trigger and now it runs smoothly...very nice.
Thank you for your help and insight....and thanks for also showing me how to debug it.




gjgsm...@gmail.com

unread,
Mar 29, 2021, 6:35:18 PM3/29/21
to accelstepper
As a suggestion...

If you want the motor to come to a stop using acceleration instead of a hard stop using the limit switch, use 'targets' instead of the limit switches.

Starting with the 'open' position, home the stepper using the limit switch and set step position to zero. Zero is now the 'open' position target. To get the 'closed' position target, run the stepper to the closed position and get the number of steps moved. This number is now the 'closed' position target (eg. 2876). This process would only need to be done once.

Now, to move stepper to the closed position:

stepperX.moveTo(2876);
stepperx.run();

You can check the position by querying the limit switch and home to the closed position if necessary, but if you are zeroing step positions everytime you go to the open position that should not be needed.

Of course, to move back to the 'open' position:

stepperX.moveTo(0);
stepperx.run();

Home the stepper again to the open position and set steps to zero. This will happen in a fraction of a second and the stepper may not even move.

Geoff
Reply all
Reply to author
Forward
0 new messages