Cirkit Designer LogoCirkit DesignerYour all-in-one circuit design IDE Launch Cirkit Designer App

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

View and Edit Project In Cirkit DesignerImage 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)

STEPPER DRIVER

Arduino UNO R4 WiFi

Rotary Encoder

Potentiometer

DC Power Source

Rocker Switch

Wiring Details

Stepper Motor (Bipolar)

STEPPER DRIVER

Arduino UNO R4 WiFi

Rotary Encoder

Potentiometer

DC Power Source

Rocker Switch

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