1. How does it work?
1.1 Summary
The MODSPI Stepper Controller makes it simple to control stepper motors by providing a plug-and-play solution. Just connect any 4-wire stepper motor (up to 2.8A), set a target position via SPI, and let the module take care of the rest.
Powered by the advanced TMC5160 stepper motor driver chip, the controller ensures smooth and precise motion with features like stealthChop for ultra-quiet operation and stallGuard for real-time load feedback. Its onboard design, including four efficient MOSFETs, delivers reliable performance without the need for additional heatsinks or complicated wiring.
With support for an optional quadrature encoder and a straightforward interface, the MODSPI Stepper Controller is perfect for 3D printers, CNC machines, robotics, and other projects. It simplifies motor control while delivering high performance and reliability.
1.2 Stepper Controller vs Stepper Driver
A stepper driver uses step/direction inputs. It is a basic device that connects a microcontroller to a stepper motor. It translates low-power signals into the power necessary to drive the motor. Its function is limited to executing simple motor drive commands and requires higher computational load on the microcontroller to execute controls.
In contrast, a stepper controller like the TMC5160 is more advanced. It not only drives the stepper motor but also incorporates intelligent control features for complex tasks, like motion control and current management. This leads to smoother motor operation and less strain on the microcontroller, making controllers more sophisticated than basic drivers.
It also makes it simpler for the user, allowing them to change parameters like the motor current, speed or micro-stepping over SPI and provide them with features like stall and crash detection and closed-loop control.
2. Specification
2.1. Form

-
4 way 3.5mm plugable terminal connectors (plugs included).
-
Seperate plugs for 4 wire Stepper Motor and Quadrature Encoder.
-
Standard MODSPI interface with 8 way, 2.54mm pitch header pins for Power + Comms.
2.2. Pinout

2.3. Electrical Characteristics

3. Code
Overview
This example demonstrates how to use the MODSPI_StepperController class to control a stepper motor. The code initializes a MODSPI_StepperController instance, configures optional settings for speed, acceleration, and current, and then moves the motor to a new position in the main loop.
Prerequisites
Ensure you have the MODSPI library installed in your Arduino IDE. If not, you can download and install it from the Library Manager or GITHUB.
Available Functions
Setup
Void begin (int chipSelect)
Starts the Initializes the Stepper Controller module with the specified chip select pin. If you're using a MODSPI controller you can also put in "BAY1" and select your desired bay.
Void setMotorCurrent (float motorCurrent, float runCurrent, float idleCurrent)
Sets the current settings for the motor, where:
-
motorCurrent: The maximum current of the motor specified.
-
runCurrent: The current used when the motor is moving.
-
idleCurrent: The current used when the motor is idle.
Debugging
String getDriverStatus ()
Returns the status of the stepper driver as a String.
Bool isLastReadSuccessful ()
Returns 'true' if the last read operation was successful.
Setting Parameters
Void setCurrentPosition (float position, bool updateEncoderPos = false)
Sets the current internal position in steps and optionally updates the encoder counter to keep them in sync.
Void setTargetPosition (float position)
Sets the target position in steps. Note: Set all other motion profile parameters before calling this function as this starts the motor to move.
Void setMaxSpeed (float speed)
Sets the maximum speed in steps per second.
Void setRampSpeeds (float startSpeed, float stopSpeed, float transitionSpeed)
Sets the ramp start speed (VSTART), ramp stop speed (VSTOP), and acceleration transition speed (V1) in steps per second. Note: Set VSTOP >= VSTART and VSTOP >= 0.1.
Void setAcceleration (float maxAccel)
Sets the ramp acceleration and deceleration in steps per second squared.
Void setAccelerations (float maxAccel, float maxDecel, float startAccel, float finalDecel)
Sets the ramp accelerations (AMAX, DMAX, A1, D1) in steps per second squared. Note: Do not set finalDecel to 0 even if transitionSpeed = 0.
Getting Parameters
Float getCurrentPosition ()
Returns the current internal position in steps.
Float getEncoderPosition ()
Returns the current position according to the encoder counter in steps.
Float getLatchedPosition ()
Returns the position that was latched on the last reference switch or encoder event in steps.
Float getLatchedEncoderPosition ()
Returns the encoder position that was latched on the last encoder event in steps.
Float getTargetPosition ()
Returns the target position in steps.
Float getCurrentSpeed ()
Returns the current speed in steps per second.
Bool isTargetPositionReached ()
Returns 'true' if the target position has been reached.
Bool isTargetVelocityReached ()
Returns 'true' if the target velocity has been reached.
Control Functions
Void stop ()
Stops the current motion according to the set ramp mode and motion parameters. The maximum speed and start speed are set to 0 but the target position remains unchanged.
Void fastStop ()
Stops the current motion as fast as possible and sets the target position to the current position. This can be used for emergency stopping or homing.
Void disable ()
Disables the driver, turning all bridges off.
Void enable ()
Enables the driver. This isn't required unless the driver is disabled by the disable function.
Encoder Configuration
Void setEncoderResolution(int32_t motorSteps, int32_t encResolution, bool inverted = false)
Sets the encoder resolution, where:
-
motorSteps: The number of motor steps per revolution.
-
encResolution: The number of encoder ticks per revolution.
-
inverted : The polarity of the motor steps to the encoder ticks.
Void setEncoderIndexConfiguration(TMC5160_Reg::ENCMODE_sensitivity_Values sensitivity, bool nActiveHigh = true, bool ignorePol = true, bool aActiveHigh = false, bool bActiveHigh = false)
Configures the encoder index. This function isn't required to use an encoder but offers more advanced features, where:
-
sensitivity: Sets the sensitivity of the encoder.
-
nActiveHigh: Specifies if the n channel is active high. Default is true.
-
ignorePol: Specifies if the polarity should be ignored. Default is true.
-
aActiveHigh: Specifies if the A channel is active high. Default is false.
-
bActiveHigh: Specifies if the B channel is active high. Default is false.
Void setEncoderLatching (bool enabled)
Enables or disables encoder latching.
Void setEncoderAllowedDeviation (int steps)
Sets the allowed deviation in steps for the encoder. This is used for crash detection.
Bool isEncoderDeviationDetected()
Returns 'true' if an encoder deviation is detected.
Void clearEncoderDeviationFlag()
Clears the encoder deviation flag. This is called once the crash has been handled, such as after homing the axis.
Protection Configuration
Void setShortProtectionLevels(int s2vsLevel, int s2gLevel, int shortFilter, int shortDelay = 0)
Sets the short protection levels.
Example Code Breakdown
Include the MODSPI Library
First, we need to include the MODSPI library to access the necessary functions and classes.
#include <MODSPI.h>
Create an Instance of MODSPI_StepperController
Next you create an instance of the MODSPI_StepperController class and name it whatever you want, for example motor1. If you have multiple stepper controller modules, you will need to create additional instances.
MODSPI_StepperController motor1;
Setup Function
The setup function is called once when the Arduino starts. Here, we initialize the instance and perform some initial actions.
void setup() {
motor1.begin(D5); // D5 is the chip select pin.
motor1.setMaxSpeed(400); // Set speed to 2 revolutions per second.
motor1.setAcceleration(800); // Set acceleration to 4 revolutions per second per second.
// Set the motor current to 1.2A, the run current to 0.8A and the idle current to 0.2A.
motor1.setCurrent(1.2, 0.8, 0.2);
}
Main Loop
The loop function runs continuously after the setup function. Here, we check if the motor has reached the target position and, if so, set a new target position.
void loop() {
// Check if the motor has finished traveling to the target position.
if (motor1.isTargetPositionReached()) {
// Get the current position of the motor.
float currentPosition = motor1.getCurrentPosition();
// Set a new target position 200 steps beyond the current position (1 revolution).
motor1.setTargetPosition(currentPosition + 200);
}
}