Continuous rotation for stepper motors

I recently published a library that allows your program to spin stepper motors in continuous motions.

It's registered with the name "ContinuousStepper" in the Arduino Library Manager.

Contrary to other stepper libraries, this one doesn't provide any function to move the shaft at a specific angle. Instead, it provides one function to spin the shaft at a specific speed. It smoothly accelerates and decelerates when the speed changes.

Features

  • Supports stepper drivers with step and dir pins
  • Optionally supports the enable pin
  • Accelerates and decelerates smoothly
  • Negative speed rotates backward
  • Tiny footprint (about 150 lines of code)

Suggested applications

  • Tape recorders
  • Conveyors
  • Wheels

How to use the ContinousStepper library?

ContinuousStepper stepper(stepPin, dirPin);

void setup() {
  stepper.spin(200); // rotate at 200 steps per seconds
}

void loop() {
  stepper.loop(); // this function must be called as frequently as possible
}

Why use this library instead of AccelStepper?

AccelStepper is an excellent library when you want to move a stepper motor shaft at a specific angle (for example, in a 3D printer), but it doesn't support applications that need continuous rotations.

AccelStepper provides a runSpeed() function for continuous motion, but it doesn't accelerate smoothly.

You could repeatedly call move(), but after a while, the 32-bit integer that stores the target position will overflow, causing the motor to reverse its rotation.

Moreover, even if you can control the speed with setMaxSpeed(), you'll see that it accelerates smoothly but decelerates abruptly.

3 Likes

you could call setCurrentPosition() to reset the position just before reaching target.

but really for most projects a long is fine. Max target position would be 2,147,483,647 āžœ at 200 steps per second that will spin for about 124 days.

Also a stepper is probably not the best motor for a continuous long time rotation

Also a stepper is probably not the best motor for a continuous long time rotation

On the contrary, a stepper motor is a simple way to get an accurate speed.
Searching this forum reveals that I'm not the only person interested in this.

you could call setCurrentPosition() to reset the position just before reaching target.

You mean way before reaching the target; otherwise, the motor decelerates.

but really for most projects a long is fine.

I developed this library for a project that uses up to 10k steps/sec, so the counter could wrap after only 60 hours of operations.
But, you're right; I could have reset the position periodically, but why do that when a 140-lines library eliminates this pitfall? Unless you love debugging this kind of issue...

As I said, AccelStepper is an excellent library; it's just not suitable for all applications.

Salut Benoit

Yes - way before works :slight_smile:

fair ask and for sure it's a valid option.

sure agreed.
Not even sure you get 10k steps/sec with that library on standard arduino

But my point was more that steppers are not suitable for all applications and I'm not convinced by the one you described.

The key attribute of a stepper is its precise position control : the ability to move in slow, precise and discrete steps. It's an attribute you don't really leverage if you keep the stepper spinning at fast speed once you have accelerated. So I would question cost efficiency āžœ not great for your wallet.

Their efficiency (current consumption) is independent of the load. They are constantly drawing the max current. Not great when you work on battery.

because of the current consumption, they are becoming hot which will shorten their life. Not great for your wallet.

They tend to be noisy at high speed. So that's on the table for discussion. I prefer quiet electronics :slight_smile:

They are not famous for keeping their torque at high speed (need special driver). Another point on the table.

So for those reasons I would explore the use of a brushless DC motor instead. You find them in tons of consumer electronics devices that run continuously (from washing machines to fans and even in Drones where the rotors' rotational speed is precisely controlled) there's likely a reason for that ... :thinking: :innocent:

2 Likes

side note

when tinkering with electronics and personal projects, often the best component to use is the one you have with you :wink:

so thanks for the library, I'm sure it can be helpful to those in needs

It works amazingly. Just got 10000 steps per second, without upping voltage and power. With other library it went 2200 maximum. Thanks man, I'm happy.

1 Like

You're welcome @antonsed :smiley:
I made sure the library was as lightweight as possible.
Also, it doesn't call delayMicroseconds(), which allows it to run faster than most libraries.

1 Like

On the contrary. When you use motors on an accurate Omni-Wheels platform, the ability to hold position is as important as accurate rotation speed. Stepper motors are silent at low to medium speeds when you use TMC2209 drivers. The alternative is regular brushless motors with encoder and FOC controllers at many times the cost.

I only just found this library

1 Like

No need for a library for that purpose.

using the accelstepper.h library:

motor.setSpeed(x);
motor.runSpeed();

..where x is the desired speed as an integer.

As I said in my original message, "AccelStepper provides a runSpeed() function for continuous motion, but it doesn't accelerate smoothly."

Besides, AccelStepper is a library.

A good library, although its only drawback is that it does not have a function to display the current position for fixed displacements up to a certain distance.

it does not have a function to display the current position

That's the whole point!

The ContinuousStepper library is designed for applications that need accurate speed but don't care about the position, like tape recorders, film projectors, conveyors, wheels, etc.
You would often use a DC motor for these applications, but sometimes a stepper motor offers a simpler solution.

If you need the position, use AccelStepper.

Do you have examples where it would be simpler ?
May be when controlled acceleration is important ?

If you need accurate speed with a DC motor, you need a feedback mechanism to measure and regulate the speed.
With a stepper motor, you don't need feedback because each step moves the shaft by a constant angle, so you get an accurate speed by sending pulses at a precise pace.

I think the speed is an advantage of this library over AccelStepper:

// Simulation: https://wokwi.com/projects/364440263181446145
// for https://forum.arduino.cc/t/continuous-rotation-for-stepper-motors/992363 

#include <ContinuousStepper.h> // https://github.com/bblanchon/ArduinoContinuousStepper

const uint8_t stepPin = 2;
const uint8_t dirPin = 3;

ContinuousStepper stepper;

void setup() {
  stepper.begin(stepPin, dirPin);
  stepper.spin(10000);
  Serial.begin(115200);
}

void loop() {
  stepper.loop();
  report();
}

void report(void) {
  const int interval = 1000;
  static unsigned long last = -interval;
  static float lastSpeed = 0;
  unsigned long now = millis();

  if (now - last < interval) return;
  last = now;
  float speed = stepper.speed();
  if (speed != lastSpeed) {
    lastSpeed = speed;
    Serial.print(now);
    Serial.print("ms:");
    Serial.println(speed);
  }
}

ContinuousStepper can also send pulses on interrupt or PWM.

The interrupt feature uses TimerOne, TimerThree or TeensyTimerTool.
In this case, you don't need to call stepper.loop() at all.

The PWM feature uses tone(), analogWriteFrequency(), or one of Khoi Hoang's PWM libraries (RP2040_PWM, SAMD_PWM, AVR_PWM, STM32_PWM, Teensy_PWM...).
Here, you still need to call stepper.loop() to get smooth acceleration/deceleration, but you can call it less frequently.

Check out the examples folder to see how you can do that.

Hi @BenoitB,

I really love your work. For one week I try to run a stepper like your library dose. Is it possible to change the steps per round? I have the problem, to not be able running full speed, because I can't rise the speed value high enough.

I also want to change the speed via Poti. Do you have an example code for this? I'm not able to change the speed value if I'm using timerOne.

@Herr_Flodo, the library has no notion of turns; it only works with steps.
For example, the speed is in step/s, and the acceleration is in step/sĀ².
To work with turns, you need to multiply and divide by the step-per-revolution constant accordingly.

Here is a demo with a potentiometer based on @DaveX's work: ContinuousStepper with potentiometer - Wokwi Arduino and ESP32 Simulator
It's using the regular ContinuousStepper, you'll have to adapt it if you use ContinuousStepper_Timer1.

Hi @BenoitB ,

Thank you for the awser. My problem is, the steps/sek in my case need to be up to 40000. It seems to be a problem to handle such a big number. But I'm not sure. In the end the motor is not running 3000 rpm with 800 steps/ round (What is unfortunately the minimum I am able to set).

Do you know what I can do?

Have you tried raising the voltage to the stepper motor? I have a stepper motor rated at 4.2 volts that was part of a commercial device that used 42 volt power supply.

1 Like