Joystick Stepper Motor Control EASY

Control a stepper motor's direction and speed using an analog joystick module. This project demonstrates analog input reading and precise motor control.

Materials Used

Arduino UNO R3 (Elegoo kit)
Stepper motor 28BYJ-48 (5V)
ULN2003 driver board
Joystick module (VRx, VRy, SW, VCC, GND)
USB cable for Arduino
Breadboard
Jumper wires

Wiring Instructions

Joystick Connections:
• 5V → VCC
• GND → GND
• A0 → VRx
• A1 → VRy (not used in this project)

ULN2003 Driver Connections:
• D2 → IN1
• D3 → IN2
• D4 → IN3
• D5 → IN4
• 5V → VCC
• GND → GND
• Connect stepper motor to driver board

Project Photos & Demo

Joystick Stepper Motor Setup

Arduino Code

// Joystick-Controlled Stepper Motor
#include <AccelStepper.h>

// Stepper motor pins (28BYJ-48 with ULN2003 driver)
#define IN1 2
#define IN2 3
#define IN3 4
#define IN4 5

// IMPORTANT: 28BYJ-48 pin order for AccelStepper is IN1, IN3, IN2, IN4
AccelStepper stepper(AccelStepper::FULL4WIRE, IN1, IN3, IN2, IN4);

// Joystick pin
#define JOY_X A0

// Settings
const int DEADZONE = 80;       // ignore small joystick movement
const int MAX_SPEED = 2000;    // top motor speed (steps/sec)
const int ACCEL_STEP = 20;     // acceleration step size

int currentSpeed = 0;

void setup() {
  stepper.setMaxSpeed(MAX_SPEED);
}

void loop() {
  int x = analogRead(JOY_X) - 512;  // read joystick X, centered at 0

  if (abs(x) < DEADZONE) {
    // Joystick released → stop
    currentSpeed = 0;
  } else if (x > 0) {
    // Joystick right → accelerate clockwise
    currentSpeed += ACCEL_STEP;
    if (currentSpeed > MAX_SPEED) currentSpeed = MAX_SPEED;
  } else {
    // Joystick left → accelerate counterclockwise
    currentSpeed -= ACCEL_STEP;
    if (currentSpeed < -MAX_SPEED) currentSpeed = -MAX_SPEED;
  }

  stepper.setSpeed(currentSpeed);
  stepper.runSpeed();  // run motor at current speed
}

🔧 Troubleshooting

Stepper motor not responding? Here are solutions to common issues:

🔄 Stepper Motor Not Moving At All
  1. Check ULN2003 driver power - ensure 5V and GND are connected from Arduino to driver board.
  2. Verify the stepper motor cable is fully inserted into the ULN2003 driver board socket.
  3. Confirm IN1-IN4 pins are connected to correct Arduino pins (2, 3, 4, 5 in this project).
  4. Check AccelStepper library is installed: Sketch → Include Library → Manage Libraries → search "AccelStepper".
⚡ Important:

The 28BYJ-48 stepper motor has a specific pin order for AccelStepper: IN1, IN3, IN2, IN4. Using the wrong order will prevent movement!

🕹️ Joystick Not Controlling Motor
  1. Verify joystick VCC → 5V, GND → GND, and VRx → A0 connections.
  2. Open Serial Monitor and add debugging: Serial.println(analogRead(A0)); to verify joystick readings (should range 0-1023).
  3. Check DEADZONE value - if too large (>100), joystick movement might be ignored. Try reducing to 50-80.
  4. Test joystick by itself with a simple analogRead sketch to confirm it's working.
📊 Calibration:

Most joysticks center at ~512 (±50). If your joystick has a different center value, adjust the code: int x = analogRead(JOY_X) - [your_center_value];

⚠️ Motor Jitters or Vibrates Without Moving
  1. Reduce MAX_SPEED - try 1000 instead of 2000. High speeds can cause jittering.
  2. Check for loose driver board connections - ensure all IN pins have solid contact.
  3. Verify power supply can handle current - USB power may be insufficient. Try external 5V supply.
  4. Ensure motor cable is fully seated in driver board - partial connection causes erratic behavior.
🔋 Power Issue:

Stepper motors can draw significant current. If motor jitters when moving but works when stationary, use an external 5V power supply (1A minimum) connected to the ULN2003 driver.

🔁 Motor Moves in Wrong Direction
  1. Swap the speed sign in your code - change currentSpeed to -currentSpeed for joystick movements.
  2. Verify joystick is centered correctly - if offset, it may appear to move in wrong direction.
  3. Check if > and < comparisons are correct in your if statements.
🔧 Easy Fix:

To reverse motor direction, simply swap IN1 and IN3 in the AccelStepper declaration: AccelStepper stepper(AccelStepper::FULL4WIRE, IN3, IN1, IN2, IN4);

📈 Motor Doesn't Gradually Speed Up
  1. Confirm ACCEL_STEP is set (recommended 20-50) for gradual acceleration.
  2. Verify currentSpeed is being incremented/decremented, not set directly to MAX_SPEED.
  3. Check that currentSpeed clamping is working (values between -MAX_SPEED and +MAX_SPEED).
  4. Ensure loop() is running continuously without long delays blocking acceleration.
🎯 Smooth Control:

For smoother acceleration, reduce ACCEL_STEP to 10-15. This makes the motor ramp up more gradually but feels more responsive to joystick input.

What You Learned

Electrical Engineering Applications

This project teaches analog-to-digital conversion (ADC), motor control theory, and the operation of stepper motors with precise angular positioning. You learned about driver circuits (ULN2003), current amplification, the relationship between analog input ranges and motor speed mapping, and how to implement acceleration curves for smooth motion control. These concepts are fundamental in robotics, CNC machines, 3D printers, and industrial automation.

Broader Technology Context

Stepper motor control is ubiquitous in precision positioning systems. This technology powers 3D printers, plotters, camera gimbals, telescope mounts, robotic arms, automated manufacturing equipment, and medical devices like infusion pumps. Joystick-based control interfaces extend to drone piloting, video game controllers, industrial machinery operation, and assistive technology for accessibility applications.