Stepper Motor Control Using Arduino – Wokwi Simulator Project Guide

 

                            

Learn how to control a stepper motor using Arduino in the Wokwi online simulator with this beginner-friendly, step-by-step tutorial. This project explains stepper motor working principles, wiring connections, required components, and Arduino code implementation using popular drivers like ULN2003 or A4988.

Using the Wokwi simulator, you can test and simulate stepper motor rotation, direction control, speed variation, and step accuracy without physical hardware. This makes it perfect for students, robotics beginners, and IoT enthusiasts who want to understand precise motor control concepts virtually.

Code:

/*
  28BYJ-48 Stepper Motor Control with ULN2003 Driver
  ===================================================
  Complete stepper motor control with multiple modes and directions
 
  Hardware:
  - Arduino Uno
  - 28BYJ-48 5V Stepper Motor
  - ULN2003 Driver Board
  - Push Buttons for control
 
  Features:
  - Forward/Reverse rotation
  - Variable speed control
  - Step count display
  - Multiple control modes
  - Serial command interface
 
  Author: Arduino Project
  Date: 2024
*/

#include <Stepper.h>

// Motor specifications for 28BYJ-48
// Steps per revolution (full step mode)
#define STEPS_PER_REV 2048  // 28BYJ-48 has gear ratio of 64:1, 32 steps * 64 = 2048

// Pin definitions for ULN2003 driver (IN1, IN2, IN3, IN4)
#define IN1 8
#define IN2 9
#define IN3 10
#define IN4 11

// Button pins
#define BTN_FORWARD 2
#define BTN_REVERSE 3
#define BTN_SPEED_UP 4
#define BTN_SPEED_DOWN 5
#define BTN_STOP 6

// LED indicators
#define LED_FORWARD 12
#define LED_REVERSE 13

// Initialize stepper library
Stepper myStepper(STEPS_PER_REV, IN1, IN3, IN2, IN4);

// Control variables
int motorSpeed = 10;          // RPM (5-15 recommended for 28BYJ-48)
int currentPosition = 0;       // Track motor position
bool motorRunning = false;
int direction = 1;            // 1 = forward, -1 = reverse
unsigned long stepCount = 0;

// Button state variables
bool lastBtnForward = HIGH;
bool lastBtnReverse = HIGH;
bool lastBtnSpeedUp = HIGH;
bool lastBtnSpeedDown = HIGH;
bool lastBtnStop = HIGH;

void setup() {
  // Initialize serial communication
  Serial.begin(9600);
  Serial.println("========================================");
  Serial.println("  28BYJ-48 Stepper Motor Controller");
  Serial.println("========================================");
  Serial.println();
 
  // Set button pins as input with pullup
  pinMode(BTN_FORWARD, INPUT_PULLUP);
  pinMode(BTN_REVERSE, INPUT_PULLUP);
  pinMode(BTN_SPEED_UP, INPUT_PULLUP);
  pinMode(BTN_SPEED_DOWN, INPUT_PULLUP);
  pinMode(BTN_STOP, INPUT_PULLUP);
 
  // Set LED pins as output
  pinMode(LED_FORWARD, OUTPUT);
  pinMode(LED_REVERSE, OUTPUT);
 
  // Set initial motor speed
  myStepper.setSpeed(motorSpeed);
 
  // Turn off LEDs
  digitalWrite(LED_FORWARD, LOW);
  digitalWrite(LED_REVERSE, LOW);
 
  // Display instructions
  printInstructions();
}

void loop() {
  // Check button inputs
  checkButtons();
 
  // Check serial commands
  checkSerialCommands();
 
  // Run motor if active
  if (motorRunning) {
    myStepper.step(direction);
    stepCount++;
    currentPosition += direction;
   
    // Display status every 100 steps
    if (stepCount % 100 == 0) {
      displayStatus();
    }
  }
 
  delay(1); // Small delay for stability
}

void checkButtons() {
  // Forward button
  bool btnForward = digitalRead(BTN_FORWARD);
  if (btnForward == LOW && lastBtnForward == HIGH) {
    delay(50); // Debounce
    if (digitalRead(BTN_FORWARD) == LOW) {
      rotateForward();
    }
  }
  lastBtnForward = btnForward;
 
  // Reverse button
  bool btnReverse = digitalRead(BTN_REVERSE);
  if (btnReverse == LOW && lastBtnReverse == HIGH) {
    delay(50);
    if (digitalRead(BTN_REVERSE) == LOW) {
      rotateReverse();
    }
  }
  lastBtnReverse = btnReverse;
 
  // Speed up button
  bool btnSpeedUp = digitalRead(BTN_SPEED_UP);
  if (btnSpeedUp == LOW && lastBtnSpeedUp == HIGH) {
    delay(50);
    if (digitalRead(BTN_SPEED_UP) == LOW) {
      increaseSpeed();
    }
  }
  lastBtnSpeedUp = btnSpeedUp;
 
  // Speed down button
  bool btnSpeedDown = digitalRead(BTN_SPEED_DOWN);
  if (btnSpeedDown == LOW && lastBtnSpeedDown == HIGH) {
    delay(50);
    if (digitalRead(BTN_SPEED_DOWN) == LOW) {
      decreaseSpeed();
    }
  }
  lastBtnSpeedDown = btnSpeedDown;
 
  // Stop button
  bool btnStop = digitalRead(BTN_STOP);
  if (btnStop == LOW && lastBtnStop == HIGH) {
    delay(50);
    if (digitalRead(BTN_STOP) == LOW) {
      stopMotor();
    }
  }
  lastBtnStop = btnStop;
}

void checkSerialCommands() {
  if (Serial.available() > 0) {
    char command = Serial.read();
   
    switch (command) {
      case 'F':
      case 'f':
        rotateForward();
        break;
       
      case 'R':
      case 'r':
        rotateReverse();
        break;
       
      case 'S':
      case 's':
        stopMotor();
        break;
       
      case '+':
        increaseSpeed();
        break;
       
      case '-':
        decreaseSpeed();
        break;
       
      case '1':
        rotate90Degrees();
        break;
       
      case '2':
        rotate180Degrees();
        break;
       
      case '3':
        rotate360Degrees();
        break;
       
      case 'H':
      case 'h':
        printInstructions();
        break;
       
      case 'I':
      case 'i':
        displayStatus();
        break;
       
      case 'Z':
      case 'z':
        resetPosition();
        break;
    }
  }
}

void rotateForward() {
  motorRunning = true;
  direction = 1;
  digitalWrite(LED_FORWARD, HIGH);
  digitalWrite(LED_REVERSE, LOW);
  Serial.println(">>> FORWARD ROTATION <<<");
  Serial.print("Speed: ");
  Serial.print(motorSpeed);
  Serial.println(" RPM");
  Serial.println();
}

void rotateReverse() {
  motorRunning = true;
  direction = -1;
  digitalWrite(LED_FORWARD, LOW);
  digitalWrite(LED_REVERSE, HIGH);
  Serial.println(">>> REVERSE ROTATION <<<");
  Serial.print("Speed: ");
  Serial.print(motorSpeed);
  Serial.println(" RPM");
  Serial.println();
}

void stopMotor() {
  motorRunning = false;
  digitalWrite(LED_FORWARD, LOW);
  digitalWrite(LED_REVERSE, LOW);
  Serial.println(">>> MOTOR STOPPED <<<");
  Serial.print("Total steps: ");
  Serial.println(stepCount);
  Serial.println();
}

void increaseSpeed() {
  if (motorSpeed < 15) {
    motorSpeed++;
    myStepper.setSpeed(motorSpeed);
    Serial.print("Speed increased to: ");
    Serial.print(motorSpeed);
    Serial.println(" RPM");
  } else {
    Serial.println("Maximum speed reached (15 RPM)");
  }
}

void decreaseSpeed() {
  if (motorSpeed > 1) {
    motorSpeed--;
    myStepper.setSpeed(motorSpeed);
    Serial.print("Speed decreased to: ");
    Serial.print(motorSpeed);
    Serial.println(" RPM");
  } else {
    Serial.println("Minimum speed reached (1 RPM)");
  }
}

void rotate90Degrees() {
  int steps = STEPS_PER_REV / 4;
  Serial.println("Rotating 90 degrees...");
  myStepper.step(steps);
  currentPosition += steps;
  stepCount += steps;
  Serial.println("90 degree rotation complete!");
  Serial.println();
}

void rotate180Degrees() {
  int steps = STEPS_PER_REV / 2;
  Serial.println("Rotating 180 degrees...");
  myStepper.step(steps);
  currentPosition += steps;
  stepCount += steps;
  Serial.println("180 degree rotation complete!");
  Serial.println();
}

void rotate360Degrees() {
  Serial.println("Rotating 360 degrees (full rotation)...");
  myStepper.step(STEPS_PER_REV);
  currentPosition += STEPS_PER_REV;
  stepCount += STEPS_PER_REV;
  Serial.println("Full rotation complete!");
  Serial.println();
}

void resetPosition() {
  currentPosition = 0;
  stepCount = 0;
  Serial.println("Position counter reset to zero");
  Serial.println();
}

void displayStatus() {
  Serial.println("=== Motor Status ===");
  Serial.print("Running: ");
  Serial.println(motorRunning ? "YES" : "NO");
  Serial.print("Direction: ");
  Serial.println(direction == 1 ? "FORWARD" : "REVERSE");
  Serial.print("Speed: ");
  Serial.print(motorSpeed);
  Serial.println(" RPM");
  Serial.print("Position: ");
  Serial.print(currentPosition);
  Serial.println(" steps");
  Serial.print("Total steps: ");
  Serial.println(stepCount);
  float rotations = (float)currentPosition / STEPS_PER_REV;
  Serial.print("Rotations: ");
  Serial.println(rotations, 2);
  Serial.println("===================");
  Serial.println();
}

void printInstructions() {
  Serial.println("BUTTON CONTROLS:");
  Serial.println("  Button 1 - Forward Rotation");
  Serial.println("  Button 2 - Reverse Rotation");
  Serial.println("  Button 3 - Increase Speed");
  Serial.println("  Button 4 - Decrease Speed");
  Serial.println("  Button 5 - Stop Motor");
  Serial.println();
  Serial.println("SERIAL COMMANDS:");
  Serial.println("  F/f - Forward rotation");
  Serial.println("  R/r - Reverse rotation");
  Serial.println("  S/s - Stop motor");
  Serial.println("  +   - Increase speed");
  Serial.println("  -   - Decrease speed");
  Serial.println("  1   - Rotate 90 degrees");
  Serial.println("  2   - Rotate 180 degrees");
  Serial.println("  3   - Rotate 360 degrees");
  Serial.println("  I/i - Display status");
  Serial.println("  Z/z - Reset position counter");
  Serial.println("  H/h - Show this help");
  Serial.println();
  Serial.println("Ready for commands!");
  Serial.println("========================================");
  Serial.println();
}

In this tutorial, you’ll learn:

  • How a stepper motor works

  • Difference between stepper motor and DC motor

  • Arduino stepper motor interfacing

  • Controlling speed and direction using code

  • Simulation setup in Wokwi

Diagram.json:
{
  "version": 1,
  "author": "28BYJ-48 Stepper Motor Control",
  "editor": "wokwi",
  "parts": [
    {
      "type": "wokwi-arduino-uno",
      "id": "uno",
      "top": 0,
      "left": 0,
      "attrs": {}
    },
    {
      "type": "wokwi-stepper-motor",
      "id": "stepper1",
      "top": -100,
      "left": 300,
      "attrs": {
        "size": "28BYJ-48"
      }
    },
    {
      "type": "wokwi-pushbutton",
      "id": "btn1",
      "top": 120,
      "left": -200,
      "attrs": {
        "color": "green",
        "label": "Forward"
      }
    },
    {
      "type": "wokwi-pushbutton",
      "id": "btn2",
      "top": 120,
      "left": -100,
      "attrs": {
        "color": "red",
        "label": "Reverse"
      }
    },
    {
      "type": "wokwi-pushbutton",
      "id": "btn3",
      "top": 180,
      "left": -200,
      "attrs": {
        "color": "blue",
        "label": "Speed+"
      }
    },
    {
      "type": "wokwi-pushbutton",
      "id": "btn4",
      "top": 180,
      "left": -100,
      "attrs": {
        "color": "blue",
        "label": "Speed-"
      }
    },
    {
      "type": "wokwi-pushbutton",
      "id": "btn5",
      "top": 240,
      "left": -150,
      "attrs": {
        "color": "yellow",
        "label": "STOP"
      }
    },
    {
      "type": "wokwi-led",
      "id": "led1",
      "top": -80,
      "left": 500,
      "attrs": {
        "color": "green",
        "label": "Forward"
      }
    },
    {
      "type": "wokwi-led",
      "id": "led2",
      "top": -20,
      "left": 500,
      "attrs": {
        "color": "red",
        "label": "Reverse"
      }
    },
    {
      "type": "wokwi-resistor",
      "id": "r1",
      "top": -60,
      "left": 480,
      "attrs": {
        "value": "220"
      }
    },
    {
      "type": "wokwi-resistor",
      "id": "r2",
      "top": 0,
      "left": 480,
      "attrs": {
        "value": "220"
      }
    }
  ],
  "connections": [
    [
      "uno:GND.1",
      "stepper1:GND",
      "black",
      [
        "v0"
      ]
    ],
    [
      "uno:5V",
      "stepper1:V+",
      "red",
      [
        "v0"
      ]
    ],
    [
      "uno:8",
      "stepper1:A-",
      "orange",
      [
        "v0"
      ]
    ],
    [
      "uno:9",
      "stepper1:A+",
      "yellow",
      [
        "v0"
      ]
    ],
    [
      "uno:10",
      "stepper1:B-",
      "green",
      [
        "v0"
      ]
    ],
    [
      "uno:11",
      "stepper1:B+",
      "blue",
      [
        "v0"
      ]
    ],
    [
      "btn1:1.l",
      "uno:2",
      "green",
      [
        "v0"
      ]
    ],
    [
      "btn1:2.l",
      "uno:GND.2",
      "black",
      [
        "v0"
      ]
    ],
    [
      "btn2:1.l",
      "uno:3",
      "red",
      [
        "v0"
      ]
    ],
    [
      "btn2:2.l",
      "uno:GND.2",
      "black",
      [
        "v0"
      ]
    ],
    [
      "btn3:1.l",
      "uno:4",
      "blue",
      [
        "v0"
      ]
    ],
    [
      "btn3:2.l",
      "uno:GND.2",
      "black",
      [
        "v0"
      ]
    ],
    [
      "btn4:1.l",
      "uno:5",
      "blue",
      [
        "v0"
      ]
    ],
    [
      "btn4:2.l",
      "uno:GND.2",
      "black",
      [
        "v0"
      ]
    ],
    [
      "btn5:1.l",
      "uno:6",
      "yellow",
      [
        "v0"
      ]
    ],
    [
      "btn5:2.l",
      "uno:GND.2",
      "black",
      [
        "v0"
      ]
    ],
    [
      "uno:12",
      "r1:1",
      "green",
      [
        "v0"
      ]
    ],
    [
      "r1:2",
      "led1:A",
      "green",
      [
        "v0"
      ]
    ],
    [
      "led1:C",
      "uno:GND.3",
      "black",
      [
        "v0"
      ]
    ],
    [
      "uno:13",
      "r2:1",
      "red",
      [
        "v0"
      ]
    ],
    [
      "r2:2",
      "led2:A",
      "red",
      [
        "v0"
      ]
    ],
    [
      "led2:C",
      "uno:GND.3",
      "black",
      [
        "v0"
      ]
    ]
  ],
  "dependencies": {}
}

This Arduino stepper motor project is ideal for robotics projects, automation systems, CNC basics, and IoT-based motion control applications.

Comments