Files
ardu-scan/rotating-display-controller
2026-07-07 14:11:06 +08:00
..
2026-07-07 12:33:24 +08:00
2026-07-07 14:11:06 +08:00

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:

  1. MOVE:

    • The motor steps at the calculated _stepInterval.
    • _stepsRemaining decrements with each step.
    • When _stepsRemaining hits 0, the system transitions to WAIT.
  2. WAIT:

    • The motor stops.
    • _waitTime is 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.0 seconds
  • Default Speed: 5.0 degrees/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

  1. Move 90 degrees clockwise at 10 deg/s:
    s10
    a90