Motor speed jumps higher before decelerating

38 views
Skip to first unread message

Vincent Serantoni

unread,
Jun 6, 2025, 9:51:22 AMJun 6
to accelstepper
Hello everyone,

I have a basic setup with: Arduino Mega 2560, two DM320T driver, two nema21 motor and one push button (digilent PmodBTN).

My objective is :
  • while I'm pushing the button, , the two motors turn endlessly in opposite directions with smooth acceleration
  • when I release the button, the two motors decelerate until they stop
I've noticed some strange behavior when my output speed exceeds 6tr/s.
The acceleration is fine, but when I release the button, the two motors suddenly increase their speed and then start to slow down (the image is an illustration of what I observe)Observed_pb.png.

Here is my code. Can anyone help me achieve a smooth deceleration?

#include <AccelStepper.h>

const int pinPUL_1 = 40;  // impulsion
const int pinDIR_1 = 42;  // dir of rotation
const int pinPUL_2 = 44;  // impulsion
const int pinDIR_2 = 45;  // dir of rotation

AccelStepper moteur1(AccelStepper::DRIVER, pinPUL_1, pinDIR_1);
AccelStepper moteur2(AccelStepper::DRIVER, pinPUL_2, pinDIR_2);

const int pinButon1 = 36; // motor is turning while pushing

const int stepsPerRevolution = 200;
const int rotationsPerSecond = 10; // when this value is <= 5 everything is fine. For higher value I observe the weird behavior

// let the motor slowing down
bool arretEnCours = false;

void setup() {
  // Configuration moteur
  moteur1.setAcceleration(400);       // acceleration in step/s²
  moteur2.setAcceleration(400);       // accélération in step/s²

  // Config bouton
  pinMode(pinButon1, INPUT);
}

void loop() {
  int bouton1 = digitalRead(pinButon1);

  if (bouton1 == 1) {
    moteur1.setMaxSpeed(stepsPerRevolution * rotationsPerSecond);
    moteur2.setMaxSpeed(stepsPerRevolution * rotationsPerSecond);
    moteur1.moveTo(moteur1.currentPosition() - 100000);
    moteur2.moveTo(moteur2.currentPosition() + 100000);
    arretEnCours = false;
  }
  else {
    if (!arretEnCours) {
      // Clean slowing down
      moteur1.stop();
      moteur2.stop();
      arretEnCours = true;
    }
  }

  moteur1.run();
  moteur2.run();
}


Thank you all

Jim Larson

unread,
Jun 6, 2025, 8:08:38 PMJun 6
to accelstepper
Hi Vincent -
I have duplicated your setup (using NEMA 17 motors) and have your code running. I believe the problem you observe is caused by not being able to deliver steps at the required rate. That is, your processor is not able to produce 200*6*2 steps per second. I can't explain why that causes the speed-up when the button is released yet, but I hope to figure that out. But I'm sure that the processor simply can't keep up.

You can do one of two things. Either accept that you must limit your step rate, or use a faster version of the Arduino. I have tried an STM32G431 version (170MHz clock) and could easily and reliably run your code with 10 rotations per second.

I'm doing more experiments and will report results as I get them. Thanks for asking this fascinating question!

                      -jim

Jim Larson

unread,
Jun 8, 2025, 12:32:58 AMJun 8
to accelstepper
OK. Nothing like a few experiments to clear things up! 
First, the stop() function is working exactly as it should. So the problem is not related to the part of your code where the button is released.
Let's look at the code that runs when the button is pressed. First, the setMaxSpeed() calls are not being changed and should be moved into setup(). The problem, I think, is caused by calling moveTo() constantly while the button is pressed. As explained in the Missing Manual, "If moveTo() is called while the motor is moving,the target position is changed immediately and the acceleration algorithm is used to calculate the new speed." By doing this recalculation, your motor may not reach full speed and so tries to first speed up when stop() is called. 
Here's what seems to fix the problem, at least on my set up. I added a conditional around the calls to moveTo() similar to what you have in the button released code. It looks like this:
if (bouton1 == 1) {
  if (arretEnCours) {
      //moteur1.setMaxSpeed(stepsPerRevolution * rotationsPerSecond);   - moved to setup()
      //moteur2.setMaxSpeed(stepsPerRevolution * rotationsPerSecond);  - moved to setup()
      moteur1.moveTo(moteur1.currentPosition() - 100000);
      moteur2.moveTo(moteur2.currentPosition() + 100000);
      arretEnCours = false;
    }
  }
 
Now the moveTo() is only called once per button press. Try this and see if it cures the problem for you. I also found that the motors reach higher speeds. Please let us know if this works for you.

                     -jim

Vincent Serantoni

unread,
Jun 10, 2025, 3:18:17 AMJun 10
to accelstepper
Thank you very much for your time and investigation :)
I will try this asap and let you know !

Best
Vincent

Vincent Serantoni

unread,
Jun 10, 2025, 6:20:04 AMJun 10
to accelstepper
Ok,

I ran some tests and found a solution.
First, regarding the "setMaxSpeed" option in the setup, I did not select it. Indeed, In my complete program, I have several buttons, each with its own speed.
However, I clearly identified that the issue was calling 'moveTo' too often, so I added a counter and called it at the beginning and after some iterations to create a continuous, smooth, endless turn while pushing the button.
Here the modified code.
Thank you again.

#include <AccelStepper.h>

const int pinPUL_1 = 40;  // impulsion
const int pinDIR_1 = 42;  // dir of rotation
const int pinPUL_2 = 44;  // impulsion
const int pinDIR_2 = 45;  // dir of rotation

AccelStepper moteur1(AccelStepper::DRIVER, pinPUL_1, pinDIR_1);
AccelStepper moteur2(AccelStepper::DRIVER, pinPUL_2, pinDIR_2);

const int pinButon1 = 36; // motor is turning while pushing

const long bigMove = 100000;   // large relative distance
int count = 0;

const int stepsPerRevolution = 200;
const int rotationsPerSecond = 10;  // when this value is <= 5 everything is fine. For higher value I observe the weird behavior

// let the motor slowing down
bool arretEnCours = false;

void setup() {
  // Configuration moteur
  moteur1.setAcceleration(400);       // acceleration in step/s²
  moteur2.setAcceleration(400);       // accélération in step/s²

  // Config bouton
  pinMode(pinButon1, INPUT);
}

void loop() {
  int bouton1 = digitalRead(pinButon1);

  if (bouton1 == 1) {
    if (count == 0) {
      moteur1.setMaxSpeed(stepsPerRevolution * rotationsPerSecond);   // several buttons with different speeds in the complete code
      moteur2.setMaxSpeed(stepsPerRevolution * rotationsPerSecond);
      moteur1.moveTo(moteur1.currentPosition() - bigMove);
      moteur2.moveTo(moteur2.currentPosition() + bigMove);
      arretEnCours = false;
    }
    count++;
  }
  else {
    if (!arretEnCours) {
      // Clean slowing down
      moteur1.stop();
      moteur2.stop();
      arretEnCours = true;
    }
  }

  if (count > 0.9*bigMove) {
    count = 0;
  }
  moteur1.run();
  moteur2.run();
}

Jim Larson

unread,
Jun 10, 2025, 11:24:25 PMJun 10
to accelstepper
Glad it's working for you!

Be careful using your variable count like you are. 0.9 * 100000 is 90000. But count is an int and has maximum value of 32768. I'm not sure what value you'll actually be getting in your code.

                -jim
Reply all
Reply to author
Forward
0 new messages