FastAccelStepper: stepper moves that run in the background
FastAccelStepper by Jochen Kiemes drives steppers through STEP and DIR drivers such as the A4988, DRV8825 or TMC2209, with acceleration and deceleration ramps, from a hardware timer. That is the difference from AccelStepper: AccelStepper needs run() called fast and often from loop(), and any slow code in loop() stalls the motor. With FastAccelStepper you call move(), it returns at once, and the interrupt makes the steps while the sketch does other work.
Built in on Mokxi: #include <FastAccelStepper.h> and it builds, with nothing to install. Free, and no account needed.
What FastAccelStepper does
You first start the engine, then ask it for a stepper on a step pin. On the AVR boards only certain pins can be step pins, because the timer drives them directly: pins 9 and 10 on an Uno (timer 1), and timer 4’s pins on a Mega. On an ESP32 almost any output pin works. stepperConnectToPin() returns NULL for a pin it cannot use, so check the pointer before calling anything on it.
Speed is set in steps per second with setSpeedInHz() or as the time between steps with setSpeedInUs(), and acceleration in steps per second squared. The example puts STEP on pin 9, DIR on 5 and EN on 6, moves 100 steps (half a turn of a 200-step NEMA 17) and counts how many times the sketch loops while the motor moves, to show the moves really run in the background. Mokxi goes up to 10,000 steps a second, where a real board reaches 50,000 or more, and leaves out the raw command queue and moveTimed().
| Library Manager name | FastAccelStepper |
|---|---|
| Author | Jochen Kiemes |
| Include | #include <FastAccelStepper.h> |
| Boards | Arduino Uno, Arduino Nano, Arduino Mega 2560, Arduino Leonardo, SparkFun Pro Micro, Arduino Micro, Arduino Pro Mini 3.3 V, ESP32-C3, ESP32-C6, Seeed XIAO ESP32-C3, ESP32-C3 SuperMini, Seeed XIAO ESP32-C6, ESP32 DevKit, ESP32-DevKitC V4, LOLIN32 Lite, Wemos D1 R32, Cheap Yellow Display, TTGO T-Display, ESP32-S3-DevKitC-1, Seeed XIAO ESP32-S3, Arduino Nano ESP32 |
| In the simulator | Runs, with a gap the note below names. |
| Parts it drives | Stepper driver, A4988, Stepper motor, NEMA 17 |
Install it
It builds on Arduino Uno, Arduino Nano, Arduino Mega 2560, Arduino Leonardo, SparkFun Pro Micro, Arduino Micro, Arduino Pro Mini 3.3 V, ESP32-C3, ESP32-C6, Seeed XIAO ESP32-C3, ESP32-C3 SuperMini, Seeed XIAO ESP32-C6, ESP32 DevKit, ESP32-DevKitC V4, LOLIN32 Lite, Wemos D1 R32, Cheap Yellow Display, TTGO T-Display, ESP32-S3-DevKitC-1, Seeed XIAO ESP32-S3, Arduino Nano ESP32.
In Mokxi it is built in: #include <FastAccelStepper.h> and the sketch compiles, with no download, no zip and no Library Manager.
On a real board, install "FastAccelStepper" by Jochen Kiemes from the Arduino IDE’s Library Manager (Sketch, Include Library, Manage Libraries), or add FastAccelStepper to lib_deps in PlatformIO. Mokxi follows the calls of release 2.0.1, so a sketch written here builds there too.
What to know in the simulator: On the AVR boards a timer compare interrupt makes the steps, on timer 1’s pins (9 and 10 on the Uno) or timer 4’s on the Mega, as upstream; on the ESP32 boards a software timer that runs in delay(), between loop()s and in isRunning(). Up to 10,000 steps a second, where upstream goes to 50,000 or more. The raw command queue, moveTimed() and the pulse counter are not here, and the RP2040 and SAM boards upstream also supports are not listed.
- Arduino Uno
- Arduino Nano
- Arduino Mega 2560
- Arduino Leonardo
- SparkFun Pro Micro
- Arduino Micro
- Arduino Pro Mini 3.3 V
- ESP32-C3
- ESP32-C6
- Seeed XIAO ESP32-C3
- ESP32-C3 SuperMini
- Seeed XIAO ESP32-C6
- ESP32 DevKit
- ESP32-DevKitC V4
- LOLIN32 Lite
- Wemos D1 R32
- Cheap Yellow Display
- TTGO T-Display
- ESP32-S3-DevKitC-1
- Seeed XIAO ESP32-S3
- Arduino Nano ESP32
The calls you will use
In the order a sketch meets them.
FastAccelStepperEngine engine = FastAccelStepperEngine()
The engine that owns the timer. One per sketch, as a global.
engine.init()
Starts the timer. Call it in setup() before connecting any stepper.
stepper = engine.stepperConnectToPin(9)
Returns a FastAccelStepper pointer for a step pin the timer can drive, or NULL if it cannot.
stepper = engine.stepperConnectToPin(9);
if (!stepper) Serial.println("not a step pin");stepper->setDirectionPin(5)
The pin wired to the driver’s DIR input. An optional second argument flips which level means forward.
stepper->setEnablePin(6)
The driver’s EN pin, low to enable on most drivers. Pair it with setAutoEnable(true) to power the coils only while moving.
stepper->setSpeedInHz(400)
The top speed in steps a second for the next moves.
stepper->setAcceleration(800)
Acceleration and deceleration in steps a second, a second. Must be set before the first move.
stepper->move(100)
Starts a relative move and returns at once. moveTo(1000) goes to an absolute position instead.
stepper->isRunning()
True while a move is under way. getCurrentPosition() gives the position in steps at any moment.
stepper->stopMove()
Brings the motor to a halt with the set deceleration; forceStop() stops it at once.
Example: Half a turn of a NEMA 17 in the background with FastAccelStepper
On the Arduino Uno R3. It runs in the browser exactly as printed.
#include "FastAccelStepper.h"
// As in StepperDemo for Motor 1 on AVR: STEP on OC1A, which is pin 9 on an Uno.
#define dirPinStepper 5
#define enablePinStepper 6
#define stepPinStepper 9
FastAccelStepperEngine engine = FastAccelStepperEngine();
FastAccelStepper *stepper = NULL;
void setup() {
Serial.begin(9600);
engine.init();
stepper = engine.stepperConnectToPin(stepPinStepper);
if (stepper) {
stepper->setDirectionPin(dirPinStepper);
stepper->setEnablePin(enablePinStepper);
stepper->setAutoEnable(true);
stepper->setSpeedInHz(400); // steps a second
stepper->setAcceleration(800); // steps a second, a second
stepper->move(100); // returns at once: the timer makes the steps
unsigned long spins = 0;
while (stepper->isRunning()) {
spins++; // the sketch is free while it moves
}
Serial.print("at ");
Serial.println(stepper->getCurrentPosition());
if (spins > 1000) Serial.println("the sketch ran while it moved");
} else {
Serial.println("not a step pin of the timer");
}
}
void loop() {}Wiring
- Arduino Uno R3 9 to Stepper driver, A4988 STEP
- Arduino Uno R3 5 to Stepper driver, A4988 DIR
- Arduino Uno R3 6 to Stepper driver, A4988 EN
- Arduino Uno R3 5V to Stepper driver, A4988 VDD
- Arduino Uno R3 GND to Stepper driver, A4988 GND
- Arduino Uno R3 GND to Stepper driver, A4988 GNDM
- Power VCC to Stepper driver, A4988 VMOT
- Stepper driver, A4988 RST to Stepper driver, A4988 SLP
- Stepper driver, A4988 2B to Stepper motor, NEMA 17 A1
- Stepper driver, A4988 2A to Stepper motor, NEMA 17 A2
- Stepper driver, A4988 1A to Stepper motor, NEMA 17 B1
- Stepper driver, A4988 1B to Stepper motor, NEMA 17 B2
Common errors and how to fix them
stepperConnectToPin() returns NULL on an Uno
The step pin is not one the timer can drive. On an Uno or Nano use pin 9 or 10; on a Mega use 6, 7 or 8. DIR and EN can be any pin.
The motor does not move and setSpeedInHz() was called
Acceleration was never set, so the move cannot start. Call setAcceleration() before move(). Also check the driver’s EN pin, either with setEnablePin() and setAutoEnable(true) or by holding it low yourself.
analogWrite() on pin 9 or 10 stops working
FastAccelStepper takes over timer 1 on the Uno, which makes the PWM on those pins. Move PWM loads such as an LED or servo to pins 3, 5, 6 or 11.
Questions and answers
FastAccelStepper or AccelStepper?
AccelStepper works on any pin and any board but needs run() called constantly. FastAccelStepper is faster and runs on its own, at the cost of fixed step pins and fewer supported boards.
Projects that use FastAccelStepper
Built-in projects that include it. Each page has the full sketch and opens in the editor, already wired.
Keep going
Learn
Try FastAccelStepper without installing anything
Open the example, change the sketch, and keep your version in a free account.