A wrapper library for FastAccelStepper that automatically configures pins for open-drain operation on ESP32 platforms.
⚠️ NON-COMMERCIAL USE ONLY: This library is licensed under Creative Commons BY-NC 4.0. For commercial licensing, please contact tim@rosener.com.
ODStepper (Open-Drain Stepper) is a lightweight wrapper that extends FastAccelStepper with automatic open-drain pin configuration. This is particularly useful when interfacing with stepper drivers that require open-drain outputs for level shifting or when using drivers with different voltage levels than your microcontroller.
- Automatic Open-Drain Configuration: On ESP32, all stepper pins (step, direction, enable) are automatically configured as open-drain outputs
- Full FastAccelStepper Compatibility: Inherits all features from FastAccelStepper including:
- High-performance stepper control
- Smooth acceleration/deceleration
- Multi-stepper support
- Non-blocking operation
- Up to 200,000 steps/second on ESP32
- Transparent Operation: Use it exactly like FastAccelStepper - no API changes required
- Platform Aware: Falls back to normal output mode on non-ESP32 platforms
- Open Arduino IDE
- Go to Sketch → Include Library → Manage Libraries
- Search for "ODStepper"
- Click Install
- Download the library as a ZIP file
- Open Arduino IDE
- Go to Sketch → Include Library → Add .ZIP Library
- Select the downloaded ZIP file
Add to your platformio.ini
:
lib_deps =
https://github.com/TimRosener/ODStepper
- ESP32 - Full open-drain support (recommended)
- AVR (Arduino Uno, Mega, etc.) - Standard output mode (requires external pull-up resistors)
- Other platforms - Standard output mode (requires external pull-up resistors)
When using open-drain outputs, external pull-up resistors are required:
- Typical value: 4.7kΩ for faster rise times, and using 5V logic on the driver I will use a 1.8K resostor on the postive pin in series to the 5V rail. the GPIO attaches to the - pin. The resisitor is large enough to limit the current when the GPIO goes to Gnd.
- Connect between: Each output pin and VCC of the stepper driver
- ESP32: Required for proper operation
- Other platforms: Required to simulate open-drain behavior
ESP32/Arduino Pull-up Stepper Driver
Step Pin ─────────────┬─────────────→ STEP
│
4.7kΩ
│
VCC (3.3V or 5V)
Direction Pin ────────┬─────────────→ DIR
│
4.7kΩ
│
VCC (3.3V or 5V)
Enable Pin ───────────┬─────────────→ ENABLE
│
4.7kΩ
│
VCC (3.3V or 5V)
GND ──────────────────────────────→ GND
ODStepper uses the exact same API as FastAccelStepper. Simply replace FastAccelStepper
with ODStepper
in your code:
#include <ODStepper.h>
// Define pins
#define STEP_PIN 7
#define DIR_PIN 15
#define ENABLE_PIN 16
// Create engine and stepper
ODStepperEngine engine = ODStepperEngine();
ODStepper *stepper = NULL;
void setup() {
// Initialize the engine
engine.init();
// Connect stepper to step pin
stepper = engine.stepperConnectToPin(STEP_PIN);
if (stepper) {
// Configure additional pins
stepper->setDirectionPin(DIR_PIN);
stepper->setEnablePin(ENABLE_PIN, false); // false = active low
// Enable automatic enable/disable
stepper->setAutoEnable(true);
// Set motion parameters
stepper->setSpeedInHz(1000); // 1000 steps/second
stepper->setAcceleration(2000); // 2000 steps/second²
// Move 1000 steps forward
stepper->move(1000);
}
}
void loop() {
// Your code here
}
#include <ODStepper.h>
ODStepperEngine engine = ODStepperEngine();
ODStepper *stepperX = NULL;
ODStepper *stepperY = NULL;
void setup() {
engine.init();
// Create two steppers
stepperX = engine.stepperConnectToPin(7);
stepperY = engine.stepperConnectToPin(8);
// Configure both steppers
if (stepperX) {
stepperX->setDirectionPin(15);
stepperX->setEnablePin(16, false);
stepperX->setAutoEnable(true);
stepperX->setSpeedInHz(2000);
stepperX->setAcceleration(5000);
}
if (stepperY) {
stepperY->setDirectionPin(17);
stepperY->setEnablePin(18, false);
stepperY->setAutoEnable(true);
stepperY->setSpeedInHz(2000);
stepperY->setAcceleration(5000);
}
}
void loop() {
// Coordinated movement
if (!stepperX->isRunning() && !stepperY->isRunning()) {
stepperX->move(1000);
stepperY->move(500);
delay(2000);
}
}
ODStepper is a clever wrapper around FastAccelStepper that works by:
- Macro Redefinition: Before including FastAccelStepper, ODStepper redefines the
PIN_OUTPUT
macro that FastAccelStepper uses internally - Platform Detection: On ESP32, the macro configures pins as
OUTPUT_OPEN_DRAIN
- Type Aliasing: Creates aliases so
ODStepper
andODStepperEngine
can be used in place of their FastAccelStepper equivalents - Zero Overhead: All changes happen at compile-time - no runtime performance impact
// The entire implementation in ODStepper.h:
#ifdef ARDUINO_ARCH_ESP32
// ESP32: Use native open-drain support
#define PIN_OUTPUT(pin, value) \
{ \
digitalWrite(pin, (value)); \
pinMode(pin, OUTPUT_OPEN_DRAIN);\
}
#else
// Other platforms: Standard output (requires external pull-ups)
#define PIN_OUTPUT(pin, value) \
{ \
digitalWrite(pin, (value)); \
pinMode(pin, OUTPUT); \
}
#endif
// Include the original library
#include <FastAccelStepper.h>
// Create convenient aliases
typedef FastAccelStepperEngine ODStepperEngine;
typedef FastAccelStepper ODStepper;
ODStepper uses the complete FastAccelStepper API. For detailed API documentation, please refer to:
engine.init()
- Initialize the engineengine.stepperConnectToPin(pin)
- Create a stepper instancestepper->setDirectionPin(pin)
- Set direction pinstepper->setEnablePin(pin, activeLow)
- Set enable pinstepper->setSpeedInHz(speed)
- Set maximum speedstepper->setAcceleration(accel)
- Set accelerationstepper->move(steps)
- Move relative stepsstepper->moveTo(position)
- Move to absolute positionstepper->isRunning()
- Check if motor is movingstepper->getCurrentPosition()
- Get current position
The library includes a comprehensive example:
- SimpleTest - Interactive motion control with serial commands demonstrating all major features
When your microcontroller operates at 3.3V but your stepper driver requires 5V signals, open-drain outputs with pull-up resistors provide safe level shifting without additional hardware.
Some stepper drivers work better with open-drain signals, especially in noisy environments or with long cable runs.
Open-drain outputs prevent potential damage from voltage mismatches or accidental short circuits.
- Check pull-up resistors are installed (4.7kΩ typical)
- Verify wiring connections
- Ensure common ground between microcontroller and driver
- Check driver power supply
- Try different pull-up resistor values (2.2kΩ to 10kΩ)
- Keep wires short or use shielded cables
- Ensure solid ground connections
- Add capacitors near the driver for power supply filtering
- Ensure FastAccelStepper library is installed
- Use a compatible platform (ESP32 recommended)
- FastAccelStepper - The underlying stepper control library
This library is released under the Creative Commons Attribution-NonCommercial 4.0 International License (CC BY-NC 4.0).
- Free for non-commercial use
- Commercial use requires a license - Contact tim@rosener.com
- You must give appropriate credit
- You may adapt and build upon this work
See LICENSE file for full details.
Note: FastAccelStepper (the underlying library) is MIT licensed. The non-commercial restriction applies only to the ODStepper wrapper code.
Contributions are welcome! Please feel free to submit a Pull Request.
- gin66 - Creator of FastAccelStepper
- All contributors to the FastAccelStepper project
- 1.0.0 - Initial release with open-drain support for ESP32
For more information about the underlying stepper control capabilities, please visit the FastAccelStepper repository.