Stepper running at 1 step/s only

234 views
Skip to first unread message

Julien Roy

unread,
Jun 12, 2019, 6:04:26 AM6/12/19
to accelstepper
Hello,

I’m facing a problem with the use of the AccelStepper library: whatever the speed is on the code, my stepper runs at 1 step/s.

I’m just trying to use the « Accel_ConstantSpeed » code taken from the Adafruit Motor Shield V2 Library examples, under the Arduino IDE.

I use the Arduino IDE on a MacBook Pro, with OS Sierra, to run a stepper with an Adafruit Metro card and an Adafruit Motor Shield V2.

By searching information on the Adafruit forum, I discovered a well known issue related to the speed of the I2C bus, which might limit the speed set, but increasing the I2C speed had no effect in my case.

Then, on the page of Airspayce related to the AccelStepper functions, under the description of setMaxSpeed(), I found this statement telling that the maximum speed achievable depends on the processor and clock speed, the default maxSpeed being set at 1 step/s, as my stepper runs:


Could anyone give me more information about it or tell me what could be wrong in my case?

Thank you in advance for your help.

Mike McCauley

unread,
Jun 12, 2019, 6:13:53 AM6/12/19
to accels...@googlegroups.com
Its hard to say without seeing your code, but probably you have not called
setMaxSpeed() in your setup() to set the max speed your motor is to accelerate
to.

Cheers.
--
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



gregor

unread,
Jun 12, 2019, 6:53:48 AM6/12/19
to accelstepper
The AccelStepper library linked to by Adafruit is a very old version (v1.2). you should not use it, use the most recent version instead (v1.59, you can find it here: http://www.airspayce.com/mikem/arduino/AccelStepper/ )
As mike said, do not forget to call setMaxSpeed() for all stepper motors. This is necessary for all types of movement (accelerated and constant speed). The Accel_ConstantSpeed example does not do this, therefore the speed is limited to 1 step / second. Add this
Astepper1.setMaxSpeed(50);    
somewhere before this line
Astepper1.setSpeed(50);    
in the setup() function and it should work correctly.

Julien Roy

unread,
Jun 16, 2019, 11:12:56 AM6/16/19
to accelstepper
Hello,

Thank you very much for your answers!
As mentioned by Gregor, adding the setMaxSpeed function solved the problem.
Under the Arduino IDE examples, several codes for steppers at constant speed include the line, but it’s unfortunately missing in the one I’ve chosen, under « Adafruit Motor Shield V2 »…Sorry for this.

Once this problem has been solved, and as mentioned in my previous post, I had to raise the I2C clock speed in order to see my stepper reaching higher speeds.
However, I’m still facing some problems with this..

First, with OS Sierra, editing the twi.h file to change the I2C speed has no effect. Apparently, the Arduino IDE doesn’t seem able to find the path of the file, or to read it, I don’t really know…
Therefore, adding the line dedicated to this in the code is the only way to change the bus speed.

As I’ve experienced by raising the constant speed of my stepper, a too low I2C speed has different effects depending of the step type chosen: with the SINGLE type, the stepper is subject to jitter, while with DOUBLE or INTERLEAVE (with adapted values), the speed of the stepper is lower than the one set.

In my case, raising the I2C speed works to solve this, unless the stepper speed is raised too much, or is subject to acceleration.

I’m now trying to work with this simple code:

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

Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_StepperMotor *myStepper1 = AFMS.getStepper(200, 2);

void forwardstep1()
{  
myStepper1->onestep(FORWARD, DOUBLE);
}
void backwardstep1()
{  
myStepper1->onestep(BACKWARD, DOUBLE);
}

AccelStepper stepper1(forwardstep1, backwardstep1);

void setup()
{
AFMS.begin();

TWBR = ((F_CPU /400000L) - 16) / 2;

stepper1.setMaxSpeed(500);
stepper1.setAcceleration(100);
stepper1.move(2000);
}

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


With the SINGLE type, and whatever the I2C speed is, the stepper jitters!
DOUBLE type works fine, but my stepper is heating a bit, and I would prefer to avoid that.
What should I do to make it work properly in SINGLE type?

Then, I’ve another problem with this code.
I’m just trying to put a delay in the loop. I’d like the stepper to run, stop for a while, and run again. It sounds so simple, but I don’t manage to make it work out.
I’ve tried something like this in the loop, which is obviously wrong:

void loop()
{
stepper1.run();

if (stepper1.distanceToGo() == 0)
delay(5000);
{
if (delay == 0)
stepper1.move(2000);
}
}

I don’t get how to declare a delay as a variable and make its value become a condition for the other operations of the loop.
How to do this??

Thanks for your help!

gregor

unread,
Jun 18, 2019, 8:06:09 AM6/18/19
to accelstepper


On Sunday, June 16, 2019 at 5:12:56 PM UTC+2, Julien Roy wrote:
Hello,

Thank you very much for your answers!
As mentioned by Gregor, adding the setMaxSpeed function solved the problem.
Under the Arduino IDE examples, several codes for steppers at constant speed include the line, but it’s unfortunately missing in the one I’ve chosen, under « Adafruit Motor Shield V2 »…Sorry for this.

Once this problem has been solved, and as mentioned in my previous post, I had to raise the I2C clock speed in order to see my stepper reaching higher speeds.
However, I’m still facing some problems with this..

First, with OS Sierra, editing the twi.h file to change the I2C speed has no effect. Apparently, the Arduino IDE doesn’t seem able to find the path of the file, or to read it, I don’t really know…
Therefore, adding the line dedicated to this in the code is the only way to change the bus speed.
you can use
Wire.setClock(400000L);
for this. It does the same, but is more readable and platform independent.

As I’ve experienced by raising the constant speed of my stepper, a too low I2C speed has different effects depending of the step type chosen: with the SINGLE type, the stepper is subject to jitter, while with DOUBLE or INTERLEAVE (with adapted values), the speed of the stepper is lower than the one set.
SINGLE and DOUBLE should step at the same speed. INTERLEAVE is 1/2 microstepping, MICROSTEP is 1/16 microstepping, so you would need to set 2 times / 16 times the speed to get the same RPM.

In my case, raising the I2C speed works to solve this, unless the stepper speed is raised too much, or is subject to acceleration.

I’m now trying to work with this simple code:

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

Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_StepperMotor *myStepper1 = AFMS.getStepper(200, 2);

void forwardstep1()
{  
myStepper1->onestep(FORWARD, DOUBLE);
}
void backwardstep1()
{  
myStepper1->onestep(BACKWARD, DOUBLE);
}

AccelStepper stepper1(forwardstep1, backwardstep1);

void setup()
{
AFMS.begin();

TWBR = ((F_CPU /400000L) - 16) / 2;

stepper1.setMaxSpeed(500);
stepper1.setAcceleration(100);
stepper1.move(2000);
}

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


With the SINGLE type, and whatever the I2C speed is, the stepper jitters!
DOUBLE type works fine, but my stepper is heating a bit, and I would prefer to avoid that.
What should I do to make it work properly in SINGLE type?
I assume you are using a 12V supply and 12V stepper motors? in that case, I would just ignore the heating if possible, it should not affect the motors. You can always shut off the motors when you do not need them.
stepper1.release();
releases the stepper. they are automatically reactivated when a step is taken.

Then, I’ve another problem with this code.
I’m just trying to put a delay in the loop. I’d like the stepper to run, stop for a while, and run again. It sounds so simple, but I don’t manage to make it work out.
I’ve tried something like this in the loop, which is obviously wrong:

void loop()
{
stepper1.run();

if (stepper1.distanceToGo() == 0)
delay(5000);
{
if (delay == 0)
stepper1.move(2000);
}
}

I don’t get how to declare a delay as a variable and make its value become a condition for the other operations of the loop.
How to do this??

delay is the name of the delay() function, you canoot use it as a variable.

the code below makes the stepper move 2000 steps, then pause for 2 seconds:
static const uint32_t DELAY = 2000;
void loop()
{
   
//start a new movement
    stepper1
.move(2000);

   
//step the stepper until it reaches the targetposition set with the line above
   
while(stepper1.run())
       
;

   
//wait for some time
    delay
(DELAY);
}



Thanks for your help!

Julien Roy

unread,
Jun 24, 2019, 12:12:15 PM6/24/19
to accelstepper
Hello Gregor,

Sorry for this late answer and thank you very much for your help on the different problems I’m facing.

The code for the delay works fine with one stepper!

I’ve been therefore trying to do the same with two steppers, running and stoping independently from each other.
I want my two steppers to run together, but stop at different times. They start to run together. Then, the first one stops, a LED turns on for 3 seconds, turns off, and the stepper starts to run again. Later on, the same sequence applies for the second stepper. Finally, they run again together, and both stop for 3 seconds to end the loop.
Speeds and accelerations are the same for both steppers, and the steps and delays are combined properly to synchronize the steppers at the end of the loop.

I’ve tried several codes to do this, unsuccessfully.
This is one of them:

[code]

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

Adafruit_MotorShield AFMS = Adafruit_MotorShield();

Adafruit_StepperMotor *myStepper1 = AFMS.getStepper(200, 1);
Adafruit_StepperMotor *myStepper2 = AFMS.getStepper(200, 2);

void forwardstep1()
{  
myStepper1->onestep(FORWARD, INTERLEAVE);
}
void backwardstep1()
{  
myStepper1->onestep(BACKWARD, INTERLEAVE);
}
void forwardstep2()
{  
myStepper2->onestep(FORWARD, INTERLEAVE);
}
void backwardstep2()
{  
myStepper2->onestep(BACKWARD, INTERLEAVE);
}

AccelStepper stepper1(forwardstep1, backwardstep1);
AccelStepper stepper2(forwardstep2, backwardstep2);

void setup()
{
AFMS.begin();

TWBR = ((F_CPU /400000L) - 16) / 2;

stepper1.setMaxSpeed(600);
stepper1.setAcceleration(1000);

stepper2.setMaxSpeed(600);
stepper2.setAcceleration(1000);

pinMode(10, OUTPUT);
}

static const uint32_t DELAY = 3000;

void loop(){
stepper1.move(4600);
stepper2.move(9200);
while(stepper1.run());
digitalWrite(10, HIGH);
delay(DELAY);
digitalWrite(10, LOW);
stepper1.move(6400);
while(stepper2.run());
digitalWrite(10, HIGH);
delay(DELAY);
digitalWrite(10, LOW);
stepper2.move(1800);
while(stepper1.run() && stepper2.run());
delay(DELAY);
}
[/code]

With this code, the steppers run one by one, and together only at the end. How to correct it to get the right sequence?


Regarding the frequency of the I2C bus, I’ve tried to use Wire.setClock rather than the TWBR code.
As I read on the Arduino web site, Wire.setClock admit only certain frequencies, depending also of the processor used. As I’ve experienced, TWBR may not work with some of these frequencies while admitting other ones. Does it sound correct to you?

Anyway, both ways work pretty fine to make my steppers run in DOUBLE and INTERLEAVE type. I still have problems with SINGLE, but my main problem is the use of MICROSTEP, that I would really need to use to avoid noise issues with my steppers.

With adapted values of speed and acceleration (x 16), whatever the way to set the I2C frequency is and its value, my steppers run much slower. This is the code for one stepper:

[code]

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

Adafruit_MotorShield AFMS = Adafruit_MotorShield();

Adafruit_StepperMotor *myStepper1 = AFMS.getStepper(200, 1);


void forwardstep1()
{  
myStepper1->onestep(FORWARD, MICROSTEP);
}
void backwardstep1()
{  
myStepper1->onestep(BACKWARD, MICROSTEP);
}

AccelStepper stepper1(forwardstep1, backwardstep1);

void setup()
{
//Wire.begin();
//Wire.setClock(400000L);
AFMS.begin(); // Activation du driver
TWBR = ((F_CPU /400000L) - 16) / 2;

stepper1.setMaxSpeed(4800); 
stepper1.setAcceleration(8000);
}

static const uint32_t DELAY = 3000;

void loop()
{

stepper1.move(36800);
while(stepper1.run());
delay(DELAY);
}

[/code]

That might be totally out of relationship with the use of AccelStepper, but is there something clearly wrong to you in this code?? 

By the way, I’m using a 6.2 V stepper supplied with 5 V.

Thanks again!!

Ralph Hulslander

unread,
Jun 24, 2019, 12:41:24 PM6/24/19
to accels...@googlegroups.com
re:  6.2 V stepper supplied with 5 V.

Steppers really care about Amperage you could run 12v as long as you have the suggested amperage.

Ralph

--
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.
To view this discussion on the web visit https://groups.google.com/d/msgid/accelstepper/7204a876-8587-43df-a23e-14aa02cf8a37%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

gregor

unread,
Jun 24, 2019, 6:42:18 PM6/24/19
to accelstepper
Hi, 



On Monday, June 24, 2019 at 6:12:15 PM UTC+2, Julien Roy wrote:
Hello Gregor,

Sorry for this late answer and thank you very much for your help on the different problems I’m facing.

The code for the delay works fine with one stepper!

I’ve been therefore trying to do the same with two steppers, running and stoping independently from each other.
I want my two steppers to run together, but stop at different times. They start to run together. Then, the first one stops, a LED turns on for 3 seconds, turns off, and the stepper starts to run again. Later on, the same sequence applies for the second stepper. Finally, they run again together, and both stop for 3 seconds to end the loop.
Speeds and accelerations are the same for both steppers, and the steps and delays are combined properly to synchronize the steppers at the end of the loop.

This is somewhat complicated. First, you should call stepper.run() regardless if the steppers are stepping or not. use move() / moveTo() / stop() to control the movement. second, do not use while loops. third, do not call move() / moveTo() in every loop execution. 
Unfortunately I don't have time to create a working sketch for you, but I'd suggest something like this: add a global uint32_t variable for each stepper. this variable will hold the time a stepper has finished its last movement. in the program, regularly check if a stepper is stopped. you can do this fairly easy by using 
if((stepper.speed() == 0.0) &&(stepper.distanceToGo() == 0))
if a stepper just stopped, store the time in one of the variables. on subsequent checks, check if enough time has passed since the stepper has stopped. At this point, just set a new target (once!), the expression above will no longer evaluate to true until the stepper has reached its destination. I'd try somethink like the code below. 
void checkSteppers()
{
    //code will only be executed if stepper is not moving any more
    if((stepper1.speed() == 0.0) &&(stepper1.distanceToGo() == 0))
    {
        if (/* stepper has stopped just now */)
        {
            //remember the current time
            stepper1_stop_last = millis();
        }

        //if the stepper was stopped for long enough, set new targets
        if (millis() - stepper1_stop_last > STEPPER1_DELAY)
        {
            stepper1.move(36800);
        }
    }

    //the same for other steppers...
}

void loop() 
{
    checkSteppers();        //does not block! should return as soon as possible. 

    stepper1.run();
    stepper2.run();
}
 
With this code, the steppers run one by one, and together only at the end. How to correct it to get the right sequence?


Regarding the frequency of the I2C bus, I’ve tried to use Wire.setClock rather than the TWBR code.
As I read on the Arduino web site, Wire.setClock admit only certain frequencies, depending also of the processor used. As I’ve experienced, TWBR may not work with some of these frequencies while admitting other ones. Does it sound correct to you?
I'm only using Wire.setClock() - particularly because it is more platform independent. I've never tried to set I2C frequencies other than 100kHz and 400kHz, so I'm afraid I cannot help you a lot with this.   

Anyway, both ways work pretty fine to make my steppers run in DOUBLE and INTERLEAVE type. I still have problems with SINGLE, but my main problem is the use of MICROSTEP, that I would really need to use to avoid noise issues with my steppers.

With adapted values of speed and acceleration (x 16), whatever the way to set the I2C frequency is and its value, my steppers run much slower. This is the code for one stepper:
the problem with microstepping is that 1 step is actually only 1/16th of a step. That means, to achieve 1 RPM at MICROSTEP setting, you would have to take 3200 steps / second, where with SINGLE or DOUBLE you only need to take 200 steps / second.
Even with 400kHz I2C clock frequency you will be limited to ~1000 steps / second for all stepper motors combined. 
 
By the way, I’m using a 6.2 V stepper supplied with 5 V.
that is ok - your torque will be lower tough. 
 
Thanks again!!

Julien Roy

unread,
Jun 25, 2019, 5:40:33 AM6/25/19
to accelstepper
Hi,

Thanks for this quick answer.
I'm going to study deeper your suggestions for the code I need.

Regarding the I2C frequency, how do you come to this global amount of 1000 steps/s with a frequency of 400 kHz?
Reply all
Reply to author
Forward
0 new messages