Introducing MultiStepperLite – A Lightweight Non-Blocking Multi-Stepper Control Library
GitHub - gunakkoc/MultiStepperLite: A lightweight C++ library designed for independently controlling multiple stepper motors with a single microcontroller in a non-blocking manner. (also available in Arduino Library)
I was looking for lightweight and reliable library to run multiple stepper motors concurrently, and without any delay functions so that I can use the processing power to full extent. I wanted avoid any interrupts as I also wanted USB communication which is rather heavy and time critical (rather simple in AtMega328p). I also wanted to use the library with anything from Arduino, to Pico and STM32 boards.
Q: What are some key features?
A:
- Controlling up to 256 stepper motors (given the MCU has enough RAM).
- Changing motor speed on the fly.
- Easy support for custom timekeeping (default is micros()), for instance sub-microsecond precision. See the example "custom_timekeeping".
- Time autocorrection, to ensure the the steppers finish their steps in time as much as possible. This can be helpful if there are arbitrarily long jobs between task calls. See example "time_autocorrection".
Q: When does alternative libraries not make sense?
A:
- Stepper library is minimal and light but depends on Arduino's slowness for reliability. For common and cheap stepper drivers A4988 and DRV8825, 1us and 2us time is required to register a change in step pin state, respectively. On common Arduino variants such as Uno rev3 and Mega2560, just calling micros() function takes more than 3us. For faster and 32-bit MCUs (ESP32, STM32, Pico), however, if the motor task is called too fast or irregularly, pin switching might not be registered by these slow motor drivers.
- AccelStepper is a comprehensive library and manages the risk mentioned in Stepper library. But it ensures this waiting time via a delay function. I also personally find this library too bulky for running motors without acceleration.
Bonus: Here is a slightly altered implementation of the same ideas for a 4 channel peristaltic pump, including a Python API (it even includes a SiLa2 wrapper for laboratory automation) for communication. Here, we used BIGTREETECH SKR MINI E3 V3.0 3D printer board that has STM32G0B1 MCU. GitHub - gunakkoc/HiPeristaltic: A fully open source peristaltic pump with multiple independent channels.
Enjoy!
1 Like
I guess this is designed for relatively slow speed motion.
There appears to be an error in the example :
//enable motor's and set directions
pinMode(motor0_enabledPin, OUTPUT);
pinMode(motor0_dirPin, OUTPUT);
digitalWrite(motor0_stepPin, LOW);
digitalWrite(motor0_enabledPin, LOW);
And I don't mean the apostrophe lol
1 Like
Actually it covers a very wide range, from ~70 minutes between steps to a few microseconds between steps.
For a typical Nema17 with 200 steps per rev:
RPM = 60,000,000 / (step_interval_us * 200 * microstepping)
With, for instance, 50us step interval the RPM would be 6000 when microstepping is disabled(set to 1). I don't think the off-the-shelf stepper motors can reach this without (maybe even with) acceleration tho
.
It can also go as slow as 0.00006984919 RPM when step_interval is (2^32)-1 = 4294967295us
And thanks for the catch. Fixed it now. 5AM copy pastes are never reliable 
There doesn't seem to be much advantage over AccelStepper, tbh.
Maybe. I'd say it depends on the application. Especially for scientific applications, I'd go with MultiStepperLite if I want to stay cheap, or a hardware with dedicated clock etc with the added cost (but I love cheap and accessible).
1-With slow Arduino processors, the AccelStepper wastes too many cycles, the delay function can be skipped altogether. Indeed, MultiStepperLite skips them for such MCUs. For high RPM and many motors it adds up. At the end, the steps would become irregular if the MCU is doing something else in between. For instance, serial communication alone can exceed the step interval.
2-For faster MCUs, the delay function is a big waste. Plus, if you want to use more precise timers of 32-bit MCUs for even finer timing (sub-microsecond) of the motors, AccelStepper doesn't have that option.
So to me MultiStepperLite is both lighter and more resilient.
The initiating reason I spent time on this library was our laboratory grade peristaltic pump (GitHub - gunakkoc/HiPeristaltic: A fully open source peristaltic pump with multiple independent channels.). In between tasks, the USB communication was really time consuming, each byte taking ~20us. With continuous back-forth communication and high RPM of multiple motors, it was lagging behind. Peristaltic pumps are already not so precise for mechanical limitations so I aimed to minimize any error contribution from the electronics. For that I used 1/16us precision and basically the ideas in MultiStepperLite.