Skip to main content

Ramp the step rate up and down

What this example shows​

The motor speeding up and then slowing back down. The module has no built-in acceleration curve, so the example builds one the simple way: it shortens the delay between steps a little more each time round, then lengthens it again.

Only DIR and STEP are used here. ENABLE, RESET and SLEEP are left out of begin(), so RESET and SLEEP must be tied high in hardware for this sketch to run: both have internal pulldowns and would otherwise hold the driver in reset and asleep.

The example's pin numbers, GPIO4 for DIR and GPIO5 for STEP, are both broken out on the NULA DeepSleep ESP32-S3, so this code runs unchanged.

The example code​

from drv8825 import DRV8825 # Import the DRV8825 motor driver module
from time import sleep # Import sleep function for timing delays

# Define GPIO pins for motor control
DIR_PIN = 4 # GPIO pin used for direction control
STEP_PIN = 5 # GPIO pin used for step pulses

# Create a DRV8825 motor instance
motor = DRV8825()

# Initialize the motor with the specified DIR and STEP pins
motor.begin(DIR=DIR_PIN, STEP=STEP_PIN)

# Set the number of steps the motor takes per full rotation (usually 200 for a 1.8° stepper motor)
motor.setStepsPerRotation(200)

# Set the length of each step pulse in microseconds
motor.setStepPulseLength(1000)

# Set motor rotation direction to clockwise
motor.setDirection(DRV8825.CLOCK_WISE)

# Enable the motor driver (turns on output)
motor.enable()

print("Accelerating")

# Gradually increase the step frequency (i.e., speed up the motor)
accelerationFactor = 1
while accelerationFactor < 2000:
motor.step() # Send a single step pulse to the motor
sleep(
1 / accelerationFactor
) # Delay inversely proportional to the factor (higher = faster)
accelerationFactor += 1 # Increase acceleration factor
print(accelerationFactor) # Print current acceleration factor

# Gradually decrease the step frequency (i.e., slow down the motor)
while accelerationFactor > 1:
motor.step() # Send a single step pulse
sleep(1 / accelerationFactor) # Delay increases as acceleration factor decreases
accelerationFactor -= 1 # Decrease acceleration factor
print(accelerationFactor) # Print current acceleration factor

Expected result:

ShellMicroPython
Accelerating
2
3
4
...
2000
1999
1998
...
2

The counter is printed by the example on every step, so the shape is exact: it climbs from 2 to 2000, then counts back down to 2.

The motor starts almost stationary and speeds up. The first step waits a full second, and the pace picks up quickly from there, so most of the run time is spent in the first handful of steps. Expect the whole ramp to take tens of seconds rather than a moment.

This example calls enable() but never passes an enable pin to begin(), so that call returns False and does nothing. It does not matter here: the driver's ENABLE input is active low with an internal pulldown, so an unwired pin sits low and the outputs are enabled anyway.

Functions used​

DRV8825()returns DRV8825

Creates the driver object. It configures nothing on its own; every pin is set up by begin().

ReturnsA new driver instance with no pins assigned.

Parameters

This constructor takes no parameters.

begin(DIR, STEP, EN=None, RST=None, SLP=None)returns bool

Assigns the control pins and configures them as outputs. Called here with only DIR and STEP, which leaves EN, RST and SLP unmanaged. RESET and SLEEP must then be held high in hardware.

ReturnsTrue once the pins are configured.

Parameters

TypeNameDescription
intDIRGPIO number for the direction pin.
intSTEPGPIO number for the step pin.
intENGPIO number for the enable pin. Optional, defaults to None.
intRSTGPIO number for the reset pin. Optional, defaults to None.
intSLPGPIO number for the sleep pin. Optional, defaults to None.
setStepsPerRotation(steps)returns None

Tells the module how many steps make one full rotation, so it can track position within a rotation. A 1.8 degree motor at full step takes 200. It does not change how the motor is driven.

ReturnsNothing.

Parameters

TypeNameDescription
intstepsSteps per full rotation.
setStepPulseLength(length)returns None

Sets how long the STEP pin is held high, and then low, inside each step() call, in microseconds. This is the floor on how fast the motor can be stepped: at 1000 microseconds each step() takes at least 2 ms on its own, before any delay you add on top.

ReturnsNothing.

Parameters

TypeNameDescription
intlengthPulse length in microseconds.
setDirection(direction)returns bool

Sets the direction pin. Use the class constants DRV8825.CLOCK_WISE and DRV8825.COUNTER_CLOCK_WISE rather than raw numbers. Any other value is rejected and the pin is left alone. The constant names describe the DIR level, not a guaranteed shaft direction, which follows your coil wiring.

ReturnsTrue if the direction was valid, False otherwise.

Parameters

TypeNameDescription
intdirectionDRV8825.CLOCK_WISE (1) or DRV8825.COUNTER_CLOCK_WISE (0).
enable()returns bool

Enables the driver outputs by pulling the ENABLE pin low. Returns False if no enable pin was passed to begin().

ReturnsTrue if the pin was driven, False if no enable pin is configured.

Parameters

This function takes no parameters.

step()returns None

Advances the motor one step: pulses STEP high then low, waiting the configured pulse length at each level. Calling it in a loop with a shrinking delay is what produces the ramp.

ReturnsNothing.

Parameters

This function takes no parameters.

getSteps()returns int

The number of steps taken since the counter was last reset. Useful for checking how far a ramp actually got.

ReturnsTotal steps counted.

Parameters

This function takes no parameters.

resetSteps(s=0)returns int

Resets the step counter and hands back what it was before, so you can measure one move without losing the previous total.

ReturnsThe step count as it was before the reset.

Parameters

TypeNameDescription
intsNew value for the counter. Optional, defaults to 0.

Putting it together​

sleep(1 / accelerationFactor) is the whole acceleration curve. At the start the factor is 1, so the motor waits a full second between steps. By the end it is 2000 and the wait is half a millisecond.

At that point the delay has stopped being what sets the speed. setStepPulseLength(1000) holds STEP high for 1 ms and low for 1 ms inside every step() call, so no matter how small the sleep gets, a step cannot take less than about 2 ms. The last few hundred iterations of the ramp barely differ from each other. If you want the top end to actually be fast, shorten the pulse length as well as the delay.

Ramping matters with steppers. Asking a loaded motor to jump straight to full speed makes it skip steps, and skipped steps mean the position you think you are at is not the position you are at. Starting slow and building up avoids that.

If you want to know how far the motor travelled, call resetSteps() before the ramp and getSteps() after.