StepperDriver Arduino Library

repository·master·Indexed 20 days ago

https://github.com/laurb9/stepperdriver

An Arduino library for controlling two-pin stepper motor drivers (DIR/STEP) including A4988, DRV8825, DRV8834, DRV8880, TMC2100, and TB6600. It supports constant speed and linear acceleration profiles, microstepping control, and both blocking and non-blocking operation. The library includes specialized classes for hardware-specific timing and microstepping, as well as MultiDriver and SyncDriver for coordinating multiple motors.

Tokens
7.9K
Snippets
33
Records
41
Agent score
69%

What's inside StepperDriver

  1. Overview of StepperDriver library

    master

    StepperDriver is an Arduino library designed for controlling various two-pin stepper motor drivers using DIR and STEP pins. It supports constant speed mode (low RPM) and linear (accelerated) speed mode with independent acceleration and deceleration settings. The library also features a non-blocking mode that yields back to the caller after each pulse, allowing for early braking or increased runtime control.

    Supported Hardware:

    • DRV8834: Up to 1:32 microstepping.
    • A4988: Up to 1:16 microstepping.
    • DRV8825: Up to 1:32 microstepping.
    • DRV8880: Up to 1:16 microstepping, with current/torque control.
    • TMC2100: Up to 1:16 native (1:256 interpolated).
    • Toshiba TB6600: Up to 1:16 (microstepping set via DIP switches).
    • Generic 2-pin drivers: Via DIR and STEP pins, microstepping up to 1:128 (set externally).
  2. Choose the correct StepperDriver class for your hardware

    master

    The library provides several classes depending on your driver board. All single-motor classes derive from BasicStepperDriver and share its API, but driver-specific classes add microstepping pin control and optimized signal timing.

    ClassDriver boardMicrostep pinsMax microstep
    BasicStepperDriverany STEP/DIR (indexer mode) boardnone (set externally)1:128
    A4988Allegro A4988MS1, MS2, MS31:16
    DRV8825TI DRV8825MODE0, MODE1, MODE21:32
    DRV8834TI DRV8834 (low-voltage)M0, M11:32
    DRV8880TI DRV8880 (with torque control)M0, M1 (+TRQ0, TRQ1)1:16
    TMC2100Trinamic TMC2100 SilentStepStickCFG1, CFG21:16 (interpolates to 1:256 internally)
    TB6600Toshiba TB6600 module (PUL/DIR/ENA)none (on-board DIP switches)1:16
    MultiDriver2-3 motors, independent moves
    SyncDriver2-3 motors, synchronized moves
  3. Configure speed profiles with setSpeedProfile()

    master

    You can choose between two movement modes using setSpeedProfile(Mode mode, short accel=1000, short decel=1000):

    • CONSTANT_SPEED (default): Every step fires at a fixed target RPM interval. It is lightweight but can cause stalling if starting at high RPM from a standstill.
    • LINEAR_SPEED: Uses a trapezoidal profile (accelerate at accel [full steps/s²], cruise, then decelerate at decel). If the move is too short to reach target RPM, it uses a triangular profile.

    Important: Ramp parameters are precalculated at the start of a move. Changing RPM or the profile mid-move will not take effect until the next move starts.

    enum Mode {CONSTANT_SPEED, LINEAR_SPEED};
    void setSpeedProfile(Mode mode, short accel=1000, short decel=1000);
  4. Coordinate multiple motors with MultiDriver and SyncDriver

    master

    These classes coordinate 2 or 3 motor objects.

    • MultiDriver: Each motor runs its own speed profile. Motors finish at different times based on their individual distances.
    • SyncDriver: Scales move timing so all motors arrive at their targets simultaneously (linear interpolation of the slower axes).

    Usage Pattern: Set individual motor parameters (like speed profile or RPM) on the motor objects before calling the group move command on the driver controller.

    DRV8825 stepperX(200, DIR_X, STEP_X);
    DRV8825 stepperY(200, DIR_Y, STEP_Y);
    SyncDriver controller(stepperX, stepperY);
    
    void setup() {
        controller.begin(120, 8);
    }
    
    void loop() {
        // Y turns twice as fast as X, but both arrive at the target at the same time
        controller.rotate(90, 180); 
    }
  5. Wiring a stepper motor driver to an Arduino

    master

    To use the library, connect your Arduino to the driver board using the following suggested pin mapping (all pins can be customized in your code):

    Control Pins:

    • DIR: D8
    • STEP: D9
    • ~SLEEP (optional): D13

    Microstep Control (Driver Dependent):

    • A4988/DRV8825: MS1 -> D10, MS2 -> D11, MS3 -> D12
    • DRV8834/DRV8880: M0 -> D10, M1 -> D11
    • TMC2100: CFG1 -> D10, CFG2 -> D11

    Power and Ground:

    • GND: Arduino GND
    • GND: Motor power GND
    • VMOT: Motor power (ensure voltage is within driver's supported range)

    Important Hardware Requirements:

    • Place a 100uF capacitor between GND and VMOT.
    • Ensure the motor power supply can deliver the maximum current required by the motor.
    • Set the max current on the driver board to the motor's limit using the onboard potentiometer.
  6. Set max current on Pololu driver boards

    master

    The maximum current is adjusted via the potentiometer on the driver board. To set it correctly, measure the voltage at the passthrough next to the potentiometer using the formula: V = I * 5 * R, where I is the max current and R is the current sense resistor installed onboard.

    For DRV8834 or DRV8825 Pololu boards (where R = 0.1):

    • Use the simplified formula: V = 0.5 * max current (A).
    • Example: To set a limit of 1A, adjust the potentiometer until you measure 0.5V.
  7. Perform non-blocking moves with startMove() and nextAction()

    master

    Non-blocking moves allow the MCU to perform other tasks while the motor is moving. You must call nextAction() inside your main loop() as often as possible.

    • startMove(long steps, long time=0): Starts a move. time (µs) can optionally stretch the move to a specific duration.
    • startRotate(long deg): Starts a rotation move.
    • nextAction(): Performs the timing wait for the next step. Returns the number of microseconds (long) available until the next step event. Returns 0 when the move is complete.
    • startBrake(): Begins decelerating to a stop (in LINEAR_SPEED) or stops immediately (in CONSTANT_SPEED).
    • stop(): Stops the motor immediately and returns the number of steps remaining.

    Best Practice: If you delay calling nextAction() past the returned wait_time, steps will fire late, causing jitter or slowed motion.

    void setup() {
        stepper.begin(120, 8);
        stepper.startRotate(5L * 360); // Five full turns
    }
    
    void loop() {
        unsigned wait_time = stepper.nextAction();
        if (wait_time == 0) {
            stepper.disable(); // Move finished
        } else if (wait_time > 100) {
            // Do other work here, ensuring it takes < wait_time µs
        }
    }
  8. Control motor movement timing with startMove() and nextAction()

    master

    For advanced users requiring external control over timing (e.g., in a non-blocking loop), MultiDriver provides a manual stepping interface:

    1. Call startMove(long steps1, long steps2, long steps3=0) to initiate a movement sequence.
    2. In your main loop, call nextAction(). This method toggles the step pins and returns the number of microseconds (long) to wait until the next step change is required.
    3. Use isRunning() to check if the movement sequence is still active.
    // Non-blocking movement pattern
    if (!group.isRunning()) {
      group.startMove(400, 400);
    }
    
    long waitTime = group.nextAction();
    if (waitTime > 0) {
      delayMicroseconds(waitTime);
    }
  9. Initialize a MultiDriver for multiple motors

    master

    The MultiDriver class allows you to manage a group of stepper motors (up to 3) as a single unit. You can initialize it by passing references to your existing BasicStepperDriver instances.

    To prepare the driver for operation, call begin(float rpm, short microsteps). This initializes pins and calculates necessary timings based on the provided RPM and microstepping level.

    // Example for a two-motor setup
    BasicStepperDriver motor1(DIR_PIN1, STEP_PIN1, EN_PIN1);
    BasicStepperDriver motor2(DIR_PIN2, STEP_PIN2, EN_PIN2);
    
    MultiDriver group(motor1, motor2);
    
    void setup() {
      group.begin(60, 1); // Start at 60 RPM with 1 microstep
    }
  10. Initialize a BasicStepperDriver

    master

    To use a stepper driver, instantiate the BasicStepperDriver class by providing the motor's steps per revolution, the direction pin, and the step pin. You can optionally provide an enable pin.

    Constructors:

    • BasicStepperDriver(short steps, short dir_pin, short step_pin)
    • BasicStepperDriver(short steps, short dir_pin, short step_pin, short enable_pin)

    After instantiation, call begin(float rpm, short microsteps) to initialize the pins and timing calculations. The default rpm is 60 and microsteps is 1.

    // Example initialization
    // 200 steps/rev, DIR pin 2, STEP pin 3, ENABLE pin 4
    BasicStepperDriver driver(200, 2, 3, 4);
    
    driver.begin(60, 16); // Start at 60 RPM with 16 microsteps
  11. Basic usage example with A4988

    master

    This example demonstrates how to initialize an A4988 driver and rotate a 200-step motor 360 degrees at 1 RPM with full-step microstepping.

    #include <Arduino.h>
    #include "A4988.h"
    
    // using a 200-step motor (most common)
    #define MOTOR_STEPS 200
    // configure the pins connected
    #define DIR 8
    #define STEP 9
    #define MS1 10
    #define MS2 11
    #define MS3 12
    A4988 stepper(MOTOR_STEPS, DIR, STEP, MS1, MS2, MS3);
    
    void setup() {
        // Set target motor RPM to 1RPM and microstepping to 1 (full step mode)
        stepper.begin(1, 1);
    }
    
    void loop() {
        // Tell motor to rotate 360 degrees. That's it.
        stepper.rotate(360);
    }
  12. Manage motor power with enable() and disable()

    master

    Use enable() to energize the coils (providing holding torque) and disable() to release them (allowing the motor to be turned by hand).

    Configuring Enable Pin Logic: Depending on your driver, the enable pin might be active HIGH (e.g., nSLEEP) or active LOW (e.g., nENABLE). Use setEnableActiveState(short state) to configure this.

    • For active LOW (common on TB6600): setEnableActiveState(LOW).
    • Default is HIGH.
    void enable();
    void disable();
    void setEnableActiveState(short state); // HIGH (default) or LOW