AccelStepper library seens buggy

Hi,

I am using AccelStepper to run 2 stepper motors using A4988 driver. I am using the very simple code below. When I run it, initially, the motors accelerate slowly till they reach the 1000 speed. After that I try to send number in the serial like 100, 200, 300...

When I reach the value 700 the motors stop spinning and make a really strange noise. Why? This should not happen cause when I started my arduino I set the motors to spin at 1000 steps/second and it worked perfectly, but when I try to set it manually, after boot up, it does not work.

#include <AccelStepper.h>

AccelStepper stepper1(1,4,5);
AccelStepper stepper2(1,6,7);

void setup() {  

    stepper1.setMaxSpeed(1000);
    stepper1.setAcceleration(1000);
    stepper1.moveTo(50000);
    
    
    stepper2.setMaxSpeed(1000);
    stepper2.setAcceleration(1000);
    stepper1.moveTo(50000);
    
    Serial.begin(115200); 
    
}

void loop() {

    String resultado = "";
    
    if (Serial.available()) {
    
        while (Serial.available()) {
        
            delay(10);
            resultado += (char)Serial.read();
        
        }
    
    }

    if (resultado != "") {
    
        stepper1.setMaxSpeed(resultado.toInt());
        
        Serial.println(resultado.toInt());
    
    }

    stepper1.run();
    stepper2.run();
    
}

the motors accelerate slowly till they reach the 1000 speed.

How do you know that the motors are running at "the 1000 speed"? 1000 what?

What do your Serial.print() statements tell you is going on?

Why do you need to stick your head in the sand after determining that there is a character in the incoming buffer that can be read?

    stepper2.setMaxSpeed(1000);
    stepper2.setAcceleration(1000);
    stepper1.moveTo(50000);

Is there some good reason for setting the maximum speed and acceleration of motor number 2, and then setting the end position for motor number 1?

Clearly I am stupid and my first code was wrong, sorry, really sorry. Here is the corrected code:

#include <AccelStepper.h>

AccelStepper stepper1(1,4,5);
AccelStepper stepper2(1,6,7);

void setup() {  

    stepper1.setMaxSpeed(1000);
    stepper1.setAcceleration(1000);
    stepper1.moveTo(50000);
    
    
    stepper2.setMaxSpeed(1000);
    stepper2.setAcceleration(1000);
    stepper2.moveTo(50000);
    
    Serial.begin(115200); 
    
}

void loop() {

    String resultado = "";
    
    if (Serial.available()) {
    
        while (Serial.available()) {
        
            delay(10);
            resultado += (char)Serial.read();
        
        }
    
    }

    if (resultado != "") {
    
        stepper1.setMaxSpeed(resultado.toInt());
        stepper2.setMaxSpeed(resultado.toInt());
        
        Serial.println(resultado.toInt());
    
    }

    stepper1.run();
    stepper2.run();
    
}

At first, you can see in my code, that I set the speed at 1000 steps/second in the "setup" call. It works fine, I mean, I can see my motor accelerating till it reaches a fixed speed. Ok, after that I type in my serial 200 and the motor slows down. Then I type 500 and the motor accelerates. The problem is that if I type 1000 the motor will get "stuck" making strange sounds.

For some reason, when I start arduino and tell it to make the motor make 1000steps/second it works, but if I set that after arduino boots up, my motor cant reach 1000 steps/second anymore.

Get rid of the Serial.println statement in the main loop.
That works as a delay statement and the steppers don't like that.

You should not be using delay(10); or delay() anything in a program that needs to call stepper.run() as often as possible.

And your code for receiving data is not at all robust. There is no guarantee that all 4 characters of "1000" will have arrived.

Have a look at the examples in Serial Input Basics - simple reliable ways to receive data. There is also a parse example.

...R

Removed the println and the problem remains, I mean, when I type 1000 my motor cant reach that speed anymore. This is not actually the problem cause this serial.println is called only once when I type something and never more, so println will not have a significant impact.

Serial is not the guilty one in this case cause clearly it is called only when I type, and even then, it outputs to me what it got, so I can make sure it got 1000. Anyway, I did a new code and the problem remains, removed everything you said could be guilty one and the problem still remains.

In the code below I make it start spinning at 1000 steps/second, after 5 seconds I make it spin at 300 steps/second and 2 more seconds later I try to reach 1000 steps/second but the result is the same as I posted in the top of this thread.

#include <AccelStepper.h>

AccelStepper stepper1(1,4,5);
AccelStepper stepper2(1,6,7);

byte x = 0;

void setup() {  

    stepper1.setMaxSpeed(1000);
    stepper1.setAcceleration(1000);
    stepper1.moveTo(50000);
    
    
    stepper2.setMaxSpeed(1000);
    stepper2.setAcceleration(1000);
    stepper2.moveTo(50000);
    
    Serial.begin(115200); 
    
}

void loop() {

	if (   (x == 0)   &&   (millis() > 5000)   ) {

        stepper1.setMaxSpeed(300);
        stepper2.setMaxSpeed(300);
        
        x = 1;
      
    }
	else if (   (x == 1)   &&   (millis() > 7000)   ) {

        stepper1.setMaxSpeed(1000);
        stepper2.setMaxSpeed(1000);
        
        x = 2;
      
    }

    stepper1.run();
    stepper2.run();
    
}

I mean, I can see my motor accelerating till it reaches a fixed speed.

But, you don't know what that speed is. Is that right?

That works as a delay statement and the steppers don't like that.

But the delay() is OK? Serial output is interrupt driven. Unless the buffer is full (which seems unlikely), the Serial.print() function will simply copy the data to the output buffer, so the call will not take near as long as the delay() call above it. Picking pepper out of horsecrap seems like waste of effort.

OP: I suspect that the fixed speed that you first achieve is nowhere near 1000 steps per second.

One thing I would try would be to send one letter to the serial port. '1' --> 100 steps per second. '2' --> 200 steps per second. See if the motors do the same thing when you send '7' as they do when you send "700".

Do NOT use any delay(). Do not call toInt() three times to convert the same String to the same int value. In fact, do NOT use the String class at all.

Anyway, I did a new code and the problem remains, removed everything you said could be guilty one and the problem still remains.

So, you've proven that the motors can't really do 700 steps per second. Good to know.

What driver board are you using? Is it configured to do micro-stepping?

@PaulS I dont know for sure the first 1000 steps/second is correct but I know for sure that it is way faster than when I type 700 steps/second in the serial or in the last code I provided. If I try to type 701 the motor gets stuck.

SO CLEARLY the motor spins way faster at the beginning than when I try to reach it's maximum speed incrementing it one by one.

batata004:
Serial is not the guilty one in this case cause clearly it is called only when I type, and even then, it outputs to me what it got, so I can make sure it got 1000.

I suggest you write a short test program that cycles through 3 or 4 speed values without needing to receive them from Serial and see if the problem remains. Leave a suitable interval between changes to the values. If the problem continues, post your test program.

if the problem does not continue then you will know that your Serial code may be at fault.

...R

There could be a power supply problem, an incorrect current limit setting, or the motor is the wrong choice for the A4988 driver, and it is overheating.

Ok, I discovered what the issue was. It's the library. You assume people are ignorant and treat them as idiots. I may be stupid but not ignorant.

Seriously? Serial is the problem? It's only used once and never more, if you knew what you are talking about you would never say such a thing.

Incorrect current limit? wrong choice of driver? Seriously, did you even read what I said? At first it works and then it does not.

I reported the bug to the AccelStepper tracker and hope they fix it.

Ok, I discovered what the issue was. It's the library.

Specifically, what did you put in your bug report? If you put no more information than what we have been able to drag out of you, I wouldn't hold my breath waiting for a fix.

At first it works and then it does not.

Typical of a driver overheating problem.

I said everything I said here, but I know there they will try to find the problem, not only trying to say the user is the problem.

@jremington another nonsense, if I simply reset arduino after long time running, the motor will still spin initially.

batata004:
Seriously? Serial is the problem? It's only used once and never more, if you knew what you are talking about you would never say such a thing.

You are demonstrating a lack of understanding of the process of diagnosis.

In Reply #10 I suggested a simple means to eliminate one aspect of uncertainty - but you seem not to be interested in a methodical approach.

For my information, if for no one else, I would appreciate it if you would explain what you reported to the AccelStepper people. I am interested to try to replicate it.

...R

another nonsense, if I simply reset arduino after long time running, the motor will still spin initially.

That does seem like nonsense! You have my complete sympathy.

@Robin2 I pointed a link to this thread and copied the first post of this thread with a corrected code without serial so nobody will point finger to serial, poor serial.

@jremington :wink:

batata004:
@Robin2 I pointed a link to this thread and copied the first post of this thread with a corrected code without serial so nobody will point finger to serial, poor serial.

I would appreciate it f you would post the corrected code in reply to this so I can be sure I am looking at the same thing you are looking at.

...R