Two drivers, one controller
What this example shows
Two stepper motors running from one controller, each with its own DRV8825 board. Both motors move to a target position, and when they arrive they reverse to mirror it, so they travel back and forth indefinitely. Acceleration is handled for you: the motors ramp up and slow down into each target rather than starting and stopping abruptly.
You need two of these boards, one per motor, and four controller pins.
Despite its file name, DualMotorShield.ino does not use a motor shield. It builds two
BasicStepper instances on the DRIVER interface, which is exactly how this
board is driven.
The example code
The four pin numbers are the NULA DeepSleep ESP32-S3 assignment. The shipped sketch uses 2, 3, 6 and 7, which is Arduino Uno numbering; the rest is unchanged.
#include "Basic-Stepper-Driver-SOLDERED.h"
// The X Stepper pins
#define STEPPER1_DIR_PIN 4
#define STEPPER1_STEP_PIN 5
// The Y stepper pins
#define STEPPER2_DIR_PIN 6
#define STEPPER2_STEP_PIN 7
// Define some steppers and the pins the will use
BasicStepper stepper1(BasicStepper::DRIVER, STEPPER1_STEP_PIN, STEPPER1_DIR_PIN);
BasicStepper stepper2(BasicStepper::DRIVER, STEPPER2_STEP_PIN, STEPPER2_DIR_PIN);
void setup()
{
stepper1.setMaxSpeed(200.0);
stepper1.setAcceleration(200.0);
stepper1.moveTo(100);
stepper2.setMaxSpeed(100.0);
stepper2.setAcceleration(100.0);
stepper2.moveTo(100);
}
void loop()
{
// Change direction at the limits
if (stepper1.distanceToGo() == 0)
stepper1.moveTo(-stepper1.currentPosition());
if (stepper2.distanceToGo() == 0)
stepper2.moveTo(-stepper2.currentPosition());
stepper1.run();
stepper2.run();
}
Expected result:
Both motors step to position 100, then reverse to -100, then back again, continuing indefinitely. Each move accelerates away and decelerates in. The first motor runs at up to 200 steps per second and the second at up to 100, so it visibly takes about twice as long to cover the same distance and the two drift out of step with each other.
There is no serial output.
Functions used
BasicStepper(uint8_t interface, uint8_t pin1, uint8_t pin2)returns NoneConstructs a stepper on the given interface. Pass BasicStepper::DRIVER for this board, then the STEP pin and the DIR pin, in that order. Inherited from AccelStepper, which also accepts two further pins and an enable flag for the direct-drive interfaces.
ReturnsConstructor; no return value.
Parameters
| Type | Name | Description |
|---|---|---|
uint8_t | interface | Motor interface type. BasicStepper::DRIVER (1) for a step/dir driver. Defaults to FULL4WIRE (4). |
uint8_t | pin1 | With DRIVER, the STEP pin. Defaults to 2. |
uint8_t | pin2 | With DRIVER, the DIR pin. Defaults to 3. |
setMaxSpeed(float speed)returns voidSets the highest speed the motor is allowed to reach. Acceleration ramps up to this value and no further.
ReturnsNothing.
Parameters
| Type | Name | Description |
|---|---|---|
float | speed | Maximum speed in steps per second. |
setAcceleration(float acceleration)returns voidSets how quickly the motor changes speed, used for both accelerating and decelerating. This is what makes the motor ease into a target position instead of stopping dead.
ReturnsNothing.
Parameters
| Type | Name | Description |
|---|---|---|
float | acceleration | Acceleration in steps per second squared. |
moveTo(long absolute)returns voidSets an absolute target position in steps. It does not move the motor by itself; run() does the stepping. Calling it with the negative of the current position, as this example does, sends the motor back the way it came.
ReturnsNothing.
Parameters
| Type | Name | Description |
|---|---|---|
long | absolute | Target position in steps, relative to where the motor started. |
distanceToGo()returns longHow many steps remain before the target position is reached. Zero means the motor has arrived, which is how this example knows when to reverse.
ReturnsSteps still to go. Negative when the target is behind the current position.
Parameters
This function takes no parameters.
currentPosition()returns longThe motor's position in steps, counted from where it started.
ReturnsCurrent position in steps.
Parameters
This function takes no parameters.
run()returns booleanSteps the motor at most once, applying the acceleration curve. It has to be called repeatedly for the motor to keep moving, which is why it sits in loop() with nothing blocking around it.
ReturnsTrue while the motor is still travelling to its target.
Parameters
This function takes no parameters.
Putting it together
The pattern is the same for one motor or several. Configure speed and
acceleration once in setup(), set a target, then call run() on every pass
through loop(). Because run() steps at most once per call, anything that
blocks, a delay() or a slow sensor read, stalls the motor. Keep loop() fast
and let distanceToGo() tell you when a move has finished.
Both drivers need their own board, their own motor supply connection and their own current limit set at the trimmer. They can share the controller's ground.