Arduino Stepper Motor Controller
A state-machine based Arduino sketch for controlling a 28BYJ-48 stepper motor via Serial communication. The system supports both Manual and Automatic modes, allowing for relative angle movement, speed control, and configurable wait intervals.
Hardware Requirements
- Microcontroller: Arduino Uno / Mega / Nano
- Motor Driver: ULN2003 (or compatible)
- Stepper Motor: 28BYJ-48 (or compatible bipolar/unipolar stepper)
Pin Connections
| Pin | Function | Arduino Pin |
|---|---|---|
| IN1 | Step 1 | 9 |
| IN2 | Step 2 | 10 |
| IN3 | Step 3 | 11 |
| IN4 | Step 4 | 12 |
System Configuration
Constants
- STEPS_PER_REVOLUTION:
2048(Standard for 28BYJ-48 with gear reduction) - DEGREES_PER_STEP: Calculated as
360.0 / 2048(~0.1758°)
Global Variables
| Variable | Type | Description |
|---|---|---|
autoMode |
enum |
AUTO or MANUAL |
targetAngle |
float |
Target angle in degrees (relative to current position) |
turnSpeed |
float |
Speed in degrees per second |
_currState |
enum |
MOVE or WAIT |
waitInterval |
float |
Time in seconds to wait in WAIT state (only active in AUTO mode) |
_waitTime |
unsigned long |
Timestamp of when WAIT state began |
_stepInterval |
float |
Time in seconds between individual steps |
_stepTime |
unsigned long |
Timestamp of the last step |
_stepCount |
int |
Total steps to move for the current target |
_stepsRemaining |
int |
Steps remaining in the current move sequence |
_directionCW |
bool |
true for Clockwise, false for Counter-Clockwise |
Serial Command Interface
The controller listens to the Serial port (9600 baud). Commands must start with a letter followed by a value. No spaces are required.
| Command | Format | Description |
|---|---|---|
| Mode Switch | m0 / m1 |
m0: Set to AUTO (cycles MOVE/WAIT).m1: Set to MANUAL (moves once, then waits indefinitely). |
| Move Angle | a<degrees> |
Move <degrees> degrees relative to current position. Supports negative values for reverse direction.Example: a90 (move 90° CW), a-45 (move 45° CCW). |
| Set Speed | s<speed> |
Set speed in degrees per second. Example: s10 (10 deg/s). |
| Set Wait Time | i<seconds> |
Set the duration (in seconds) to wait in WAIT state when in AUTO mode.Example: i5 (wait 5 seconds). |
Operational Logic
State Machine
The system operates in two primary states:
-
MOVE:
- The motor steps at the calculated
_stepInterval. _stepsRemainingdecrements with each step.- When
_stepsRemaininghits 0, the system transitions to WAIT.
- The motor steps at the calculated
-
WAIT:
- The motor stops.
_waitTimeis recorded.- In AUTO Mode: If
millis() - _waitTime > waitInterval, the system transitions back to MOVE (repeats cycle). - In MANUAL Mode: The system stays in WAIT indefinitely until a new Serial command is received.
autoMode // AUTO or MANUAL. If AUTO, cycles between MOVE and WAIT state. If MANUAL, goes into MOVE state, but stays in WAIT indefinitely until a new command is sent
targetAngle // The target angle in degrees, relative to the current position
turnSpeed // The turn speed in degrees per second
_currState // MOVE or WAIT
waitInterval // Time to stay in wait state in AUTO mode, in seconds
_waitTime // Variable to compare against millis()
_stepInterval // Time between motor steps, in seconds
_stepTime // Variable to compare against millis()
_stepCount // Number of steps remaining
_stepRemaining //
LOOP
--- READ SERIAL ---
if serial.Available
string = serial.readString
switch(string[0])
case 'm':
if autoMode != string[1]
autoMode = AUTO if string[1] == 0, MANUAL if string[1] == 1
// Start moving following existing parameters, relative to current position
_currState = MOVE
_waitTime = 0
_stepTime = millis()
_stepsRemaining = _stepCount
case 'a':
// Move this many degrees relative to current position
targetAngle = strToFloat(string[1:])
// TODO: Recalculate step count
_currState = MOVE
_waitTime = 0
_stepTime = millis()
_stepsRemaining = _stepCount
case 's':
// Sets the step interval
turnSpeed = strToFloat(string[1:])
// TODO: Recalculate step interval
case 'i':
// Sets the wait interval
waitInterval = strToFloat(string[1:])
--- Execution Logic ---
if _stepsRemaining == 0
_currState = WAIT
_waitTime = millis()
if autoMode = AUTO and _currState == WAIT and millis() - _waitTime > waitInterval
_currState = MOVE
_stepsRemaining = _stepCount
_stepTime = millis()
if currState == MOVE
if millis() - _stepTime > _stepInterval
RunStep
_stepTime = millis()
_stepsRemaining -= 1
Initialization
- Default Mode:
AUTO - Default State:
MOVE - Default Wait Interval:
8.0seconds - Default Speed:
5.0degrees/second
Step Sequence Logic
The controller supports bidirectional movement by using two sequences:
- Clockwise (CW): Standard 4-step sequence.
- Counter-Clockwise (CCW): Reverse of the CW sequence.
The direction is determined by the sign of the targetAngle when the a command is received.
Usage Examples
- Move 90 degrees clockwise at 10 deg/s:
s10 a90