Cirkit Designer Logo
Cirkit Designer
Your all-in-one circuit design IDE
Home / 
Project Documentation

Arduino-Controlled Stepper Motor with Rotary Encoder and Potentiometer Speed Adjustment

Image of Arduino-Controlled Stepper Motor with Rotary Encoder and Potentiometer Speed Adjustment

Circuit Documentation

Summary

This circuit is designed to control a bipolar stepper motor using an Arduino UNO R4 WiFi microcontroller. The control is achieved through a stepper motor driver, which receives signals from the Arduino to drive the motor. The user can interact with the system using a rotary encoder and a potentiometer. The rotary encoder is used to set the position and direction of the stepper motor, while the potentiometer adjusts the speed. Additionally, the rotary encoder button enables fine movement control. The circuit is powered by a DC power source, and a rocker switch is used to turn the motor driver on and off.

Component List

Stepper Motor (Bipolar)

  • Description: A bipolar stepper motor that can be driven by the stepper motor driver.
  • Pins: D, B, C, A

STEPPER DRIVER

  • Description: A driver module that controls the stepper motor based on signals from the Arduino.
  • Pins: ENA -, ENA +, DIR -, DIR+, PUL -, PUL +, B-, B+, A-, A+, GND, VCC

Arduino UNO R4 WiFi

  • Description: A microcontroller board based on the ATmega328, with integrated WiFi capability.
  • Pins: OFF, GND, VRTC, IIC0_SCL, IIC0_SDA, 3V3, GPIO 41, GPIO 0, GPIO 42, GPIO 43, GPIO 44, BOOT, IOREF, RESET, 5V, VIN, A0, A1, A2, A3, A4, A5, RSPCKA, CIPO, COPI, D0/RX, D1/TX, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, AREF, SDA, SCL

Rotary Encoder

  • Description: An input device that provides rotational position feedback and a push-button interface.
  • Pins: clk, dt, sw, gnd, +

Potentiometer

  • Description: A variable resistor that provides an adjustable voltage output.
  • Pins: GND, Output, VCC

DC Power Source

  • Description: Provides the electrical power for the circuit.
  • Pins: Ground, Positive

Rocker Switch

  • Description: A switch to control the power flow to the stepper motor driver.
  • Pins: 1, 2

Wiring Details

Stepper Motor (Bipolar)

  • D connected to STEPPER DRIVER B-
  • B connected to STEPPER DRIVER B+
  • C connected to STEPPER DRIVER A-
  • A connected to STEPPER DRIVER A+

STEPPER DRIVER

  • ENA - connected to Arduino UNO R4 WiFi D4
  • ENA + connected to Rocker Switch 2, VCC, DIR+, PUL +, and Arduino UNO R4 WiFi VIN
  • DIR - connected to Arduino UNO R4 WiFi D3
  • PUL - connected to Arduino UNO R4 WiFi D2
  • GND connected to DC Power Source Ground and Arduino UNO R4 WiFi GND

Arduino UNO R4 WiFi

  • VIN connected to STEPPER DRIVER VCC
  • GND connected to STEPPER DRIVER GND and DC Power Source Ground
  • D2 connected to STEPPER DRIVER PUL -
  • D3 connected to STEPPER DRIVER DIR -
  • D4 connected to STEPPER DRIVER ENA -
  • D5 connected to Rotary Encoder dt
  • D6 connected to Rotary Encoder sw
  • D7 connected to Rotary Encoder clk
  • A0 connected to Potentiometer Output
  • 5V connected to Potentiometer VCC and Rotary Encoder +

Rotary Encoder

  • clk connected to Arduino UNO R4 WiFi D7
  • dt connected to Arduino UNO R4 WiFi D5
  • sw connected to Arduino UNO R4 WiFi D6
  • gnd connected to Arduino UNO R4 WiFi GND
    • connected to Arduino UNO R4 WiFi 5V

Potentiometer

  • VCC connected to Arduino UNO R4 WiFi 5V
  • Output connected to Arduino UNO R4 WiFi A0
  • GND connected to Arduino UNO R4 WiFi GND

DC Power Source

  • Positive connected to Rocker Switch 1
  • Ground connected to STEPPER DRIVER GND and Arduino UNO R4 WiFi GND

Rocker Switch

  • 1 connected to DC Power Source Positive
  • 2 connected to STEPPER DRIVER ENA +, VCC, DIR+, PUL +

Documented Code

/*
 * This Arduino sketch controls a stepper motor using a rotary encoder and a
 * potentiometer. The rotary encoder sets the position and direction of the
 * stepper motor, while the potentiometer adjusts the speed. Pressing the
 * rotary encoder button enables fine movements. All actions are printed to
 * the serial monitor for debugging purposes. The motor will not move unless
 * the rotary encoder is turned clockwise or counter-clockwise.
 */

// Pin definitions
const int ENA_PIN = 4; // Connected to D4 on Arduino
const int DIR_PIN = 3; // Connected to D3 on Arduino
const int PUL_PIN = 2; // Connected to D2 on Arduino
const int ENCODER_CLK_PIN = 7; // Connected to D7 on Arduino
const int ENCODER_DT_PIN = 5; // Connected to D5 on Arduino
const int ENCODER_SW_PIN = 6; // Connected to D6 on Arduino
const int POT_PIN = A0; // Connected to A0 on Arduino

// Variables
int lastEncoderState = LOW;
int currentEncoderState;
int encoderValue = 0;
int potValue = 0;
int motorSpeed = 0;
bool fineMovement = false;
bool lastButtonState = HIGH; // Initial state is HIGH because of pull-up resistor
int lastEncoderValue = 0;
bool lastFineMovement = false;
int lastMotorDirection = LOW;
unsigned long lastDebounceTime = 0; // For debouncing
const unsigned long debounceDelay = 50; // Debounce delay in milliseconds

// Constants
const int STEPS_PER_DETENT = 20; // Steps per detent in normal mode
const int FINE_STEPS_PER_DETENT = 5; // Steps per detent in fine movement mode

void setup() {
  // Initialize serial communication
  Serial.begin(9600);

  // Initialize pins
  pinMode(ENA_PIN, OUTPUT);
  pinMode(DIR_PIN, OUTPUT);
  pinMode(PUL_PIN, OUTPUT);
  pinMode(ENCODER_CLK_PIN, INPUT);
  pinMode(ENCODER_DT_PIN, INPUT);
  pinMode(ENCODER_SW_PIN, INPUT_PULLUP); // Use internal pull-up resistor
  pinMode(POT_PIN, INPUT);

  // Enable the stepper driver
  digitalWrite(ENA_PIN, LOW);

  // Test direction pin
  digitalWrite(DIR_PIN, LOW); // Set to counter-clockwise
  delay(2000); // Wait for 2 seconds
  digitalWrite(DIR_PIN, HIGH); // Set to clockwise
  delay(2000); // Wait for 2 seconds

  // Debugging statements
  Serial.println("Setup complete. Waiting for input...");
}

void loop() {
  // Read the rotary encoder with debouncing
  int reading = digitalRead(ENCODER_CLK_PIN);
  if (reading != lastEncoderState) {
    lastDebounceTime = millis();
  }
  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (reading != currentEncoderState) {
      currentEncoderState = reading;
      if (digitalRead(ENCODER_DT_PIN) != currentEncoderState) {
        encoderValue += fineMovement ? FINE_STEPS_PER_DETENT : STEPS_PER_DETENT;
      } else {
        encoderValue -= fineMovement ? FINE_STEPS_PER_DETENT : STEPS_PER_DETENT;
      }
    }
  }
  lastEncoderState = reading;

  // Read the potentiometer
  potValue = analogRead(POT_PIN);
  motorSpeed = map(potValue, 0, 1023, 200, 1000); // Adjusted range for motor speed

  // Check if the encoder button is pressed with debouncing
  int encoderButtonState = digitalRead(ENCODER_SW_PIN);
  if (encoderButtonState != lastButtonState) {
    if ((millis() - lastDebounceTime) > debounceDelay) {
      if (encoderButtonState == LOW) {
        fineMovement = !fineMovement;
      }
    }
    lastDebounceTime = millis();
  }
  lastButtonState = encoderButtonState;

  // Set motor direction
  int motorDirection = (encoderValue > 0) ? HIGH : LOW;
  digitalWrite(DIR_PIN, motorDirection);

  // Move the motor only if encoder value has changed
  if (encoderValue != 0) {
    int stepsToMove = abs(encoderValue);
    for (int i = 0; i < stepsToMove; i++) {
      digitalWrite(PUL_PIN, HIGH);
      delayMicroseconds(motorSpeed);
      digitalWrite(PUL_PIN, LOW);
      delayMicroseconds(motorSpeed);
    }
    encoderValue = 0; // Reset encoder value after moving the motor
  }

  // Print changes