delayed reaction to stop(), moveTo(), setMaxSpeed(), ...

654 views
Skip to first unread message

gregor

unread,
Sep 14, 2014, 3:23:53 AM9/14/14
to accels...@googlegroups.com
i have the following problem:

when using accelsteper to move the steppers at higher speeds (e.g. 2 steppers at 500 steps / second) i experience a delayed reaction to the commands stop(), moveTo() and setMaxSpeed().
usually stop() is called by an external interrupt, but this also happens if stop() is called directly in the loop() (the same with moveTo() and setMaxSpeed() ). I2C communication speed is set to 400kHz.

the longer the steppers move, the longer the delay becomes (10s movement - 1s delay, 30s movement - 4s delay, ...) . there is no noticable delay when moving at low speeds (~100steps / second).
i can reproduce the behaviour with this code:
#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>

Adafruit_MotorShield AFMStop(0x60); // Default address, no jumpers

// Connect two steppers with 200 steps per revolution (1.8 degree)
// to the top shield
Adafruit_StepperMotor *myStepper1 = AFMStop.getStepper(200, 1);
Adafruit_StepperMotor *myStepper2 = AFMStop.getStepper(200, 2);

// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
// wrappers for the first motor!
void forwardstep1() {  
  myStepper1
->onestep(FORWARD, SINGLE);
}
void backwardstep1() {  
  myStepper1
->onestep(BACKWARD, SINGLE);
}
// wrappers for the second motor!
void forwardstep2() {  
  myStepper2
->onestep(FORWARD, DOUBLE);
}
void backwardstep2() {  
  myStepper2
->onestep(BACKWARD, DOUBLE);
}

// Now we'll wrap the 2 steppers in an AccelStepper object
AccelStepper stepper1(forwardstep1, backwardstep1);
AccelStepper stepper2(forwardstep2, backwardstep2);

void setup()
{  
 
AFMStop.begin(); // Start the top shield
 
 
Serial.begin(9600);
   
  stepper1
.setMaxSpeed(500.0);
  stepper1
.setAcceleration(100.0);
  stepper1
.moveTo(5000000);
   
  stepper2
.setMaxSpeed(500.0);
  stepper2
.setAcceleration(100.0);
  stepper2
.moveTo(5000000);
 
  pinMode
(13, OUTPUT);
  digitalWrite
(13, HIGH);    //switch led on
  pinMode
(2, INPUT_PULLUP);
 
  attachInterrupt
(0, interrupt, FALLING);
  TWBR
= ((F_CPU / 400000l) - 16) / 2;  //set I2C communication speed to 400kHz
}

void loop()
{
    stepper1
.run();
    stepper2
.run();
}

void interrupt()
{
  stepper1
.stop();
  stepper2
.stop();
  digitalWrite
(13, LOW);
}
when i let the steppers run for ~30s, i push the button, the led turns off, after ~4s the motors start spinning down.
when i let the steppers run for ~6s only, the delay about 1s.

Mike McCauley

unread,
Sep 17, 2014, 11:20:06 PM9/17/14
to accels...@googlegroups.com
Hello,

Not sure how immune accel stepper is to interrupt level execution.

suggest you try a system where the interrupt does not call accelstepper code
directly, but sets a flag for the next time through the loop.

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

gregor

unread,
Sep 18, 2014, 6:10:27 AM9/18/14
to accels...@googlegroups.com
hi,

i changed my code:

#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>

Adafruit_MotorShield AFMStop(0x60); // Default address, no jumpers

// Connect two steppers with 200 steps per revolution (1.8 degree)
// to the top shield
Adafruit_StepperMotor *myStepper1 = AFMStop.getStepper(200, 1);
Adafruit_StepperMotor *myStepper2 = AFMStop.getStepper(200, 2);

bool stopSteppers;

 
if (stopSteppers)
 
{
    stepper1
.stop();
    stepper2
.stop();
 
}
    stepper1
.run();
    stepper2
.run();
}

void interrupt()
{
  digitalWrite
(13, LOW);
  stopSteppers
= true;
}



i also tried handling the button state inside the loop():

#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>

Adafruit_MotorShield AFMStop(0x60); // Default address, no jumpers

// Connect two steppers with 200 steps per revolution (1.8 degree)
// to the top shield
Adafruit_StepperMotor *myStepper1 = AFMStop.getStepper(200, 1);
Adafruit_StepperMotor *myStepper2 = AFMStop.getStepper(200, 2);

bool stopSteppers;

 
  TWBR
= ((F_CPU / 400000l) - 16) / 2;  //set I2C communication speed to 400kHz
}

void loop()
{
 
if (digitalRead(2) == LOW)
 
{
    digitalWrite
(13, LOW);
    stepper1
.stop();
    stepper2
.stop();
 
}
    stepper1
.run();
    stepper2
.run();
}


but none of those solve the problem.

Mike McCauley

unread,
Sep 18, 2014, 10:24:31 PM9/18/14
to accels...@googlegroups.com
Hello,

I dont have a AF motor shield V2, but when I test your code on a Uno, when pin
2 is pulled low, the steppers appear to decelerate starting immediately, no
delay.

Cheers.

gregor

unread,
Sep 22, 2014, 4:48:18 PM9/22/14
to accels...@googlegroups.com
hello,

i have not yet found a solution for this problem, but i created a thread in the adafruit support forums.

when i prevent myStepper1->onestep() and myStepper2->onestep() from being called (for example by entering an infinite loop on button press) the steppers stop instantly.
i also tried connecting a joystick to my arduino and using setSpeed() and move(), this always works without delay:
        //x axis
   
if (xSpeed >= 0) direction = 1;
   
else direction = -1;
    stepper1
.move(direction);
   
stepper1.setSpeed(xSpeed);

   
//y axis
   
if (ySpeed >= 0) direction = 1;
   
else direction = -1;
   
stepper2.move(direction);
   
stepper2.setSpeed(ySpeed);

   
stepper1.runSpeed();
   
stepper2.runSpeed();
xSpeed and ySpeed are the readings from the joystick in a range of -512 to 512.



On Friday, September 19, 2014 4:24:31 AM UTC+2, mikem wrote:
Hello,

gregor

unread,
Sep 26, 2014, 9:11:53 AM9/26/14
to accels...@googlegroups.com
hi,
i found the solution, it's a classic pebkac problem (problem exists between keyboard and chair).
the motor shield v2 can only achieve achieve about 660 steps/s combined for all steppers (it is possible to increase that, tough). trying to run the steppers with a speed above that (e.g. 500 steps/s for each stepper) will yield in about 330 steps/s for each stepper, while accelstepper thinks the speed is 500 steps/s.
obviously, calling stop() will decelerate the steppers from a speed of 500 steps/s, but no actual deceleration will happen until accelstepper has decelerated to the real stepper speed, causing a virtual delay.

Mike McCauley

unread,
Sep 26, 2014, 9:24:18 AM9/26/14
to accels...@googlegroups.com
Hi,

Yes, that makes sense.

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

Reply all
Reply to author
Forward
0 new messages