Direct control of a stepper motor using a rotary encoder and the accelstepper library

In this video I show you how to directly control a stepper motor using a rotary encoder and the accelstepper library. The code is fairly simple, you do not need to go too deep when using it. What it does, that whenever the rotary encoder does an increment or a decrement, the motor immediately steps the same amount in the same direction as the encoder was rotated.



Arduino source code

//AccelStepper
#include <AccelStepper.h>
AccelStepper stepper(1, 8, 9);// pulses Digital 9 (CLK); Direction Digital 8 (CCW)

//16x2 LCD
#include <LiquidCrystal_I2C.h> //SDA = A4, SCL = A5
LiquidCrystal_I2C lcd(0x27, 16, 2);


//Defining pins
const int RotaryCLK = 2; //CLK pin on the rotary encoder
const int RotaryDT = 4; //DT pin on the rotary encoder
const int RotarySW = 3; //SW pin on the rotary encoder (Button function)

//Defining variables
int ButtonCounter = 0;
int RotateCounter = 0;

//Statuses
int CLKNow;
int CLKPrevious;

int DTNow;
int DTPrevious;

// Time
float TimeNow1;
float TimeNow2;
float TimeNow3;



void setup()
{

  Serial.begin(9600);
  
	//------------------------------------------------------
	lcd.begin();                      // initialize the lcd 
	
	lcd.backlight();
	//------------------------------------------------------
  lcd.setCursor(0,0); //Defining positon to write from first row,first column .
  lcd.print("Rotary encoder");
  lcd.setCursor(0,1);
  lcd.print("Stepper stepping"); //You can write 16 Characters per line .
  delay(7000); //wait 1 sec
  //------------------------------------------------------

   pinMode(2, INPUT_PULLUP);
   pinMode(3, INPUT_PULLUP);
   pinMode(4, INPUT_PULLUP);
   
   

  //Store states
  CLKPrevious = digitalRead(RotaryCLK);
  DTPrevious = digitalRead(RotaryDT);
    
  attachInterrupt(digitalPinToInterrupt(RotaryCLK), rotate, CHANGE);
  attachInterrupt(digitalPinToInterrupt(RotarySW), buttonPressed, FALLING);

  stepper.setMaxSpeed(1000); //SPEED = Steps / second
  stepper.setAcceleration(5000); //ACCELERATION = Steps /(second)^2

  TimeNow1 = millis(); //Start time
  
}


void loop()
{
  TimeNow2 = millis();
  if(TimeNow2 - TimeNow1 > 200)
  {
  printLCD();
    TimeNow1 = millis();
  }
  RunTheMotor();
}

void buttonPressed()
{  
  TimeNow2 = millis();
  if(TimeNow2 - TimeNow3 > 1000)
  {
  ButtonCounter++; //increase the counter
  }
  TimeNow3 = millis();
    //You can add something here, like resetting the RotateCounter (e.g. redefine 0 position)
}

void rotate()
{
  CLKNow = digitalRead(RotaryCLK); //Read the state of the CLK pin

  // If last and current state of CLK are different, then a pulse occurred  
  if (CLKNow != CLKPrevious  && CLKNow == 1){

    // If the DT state is different than the CLK state then
    // the encoder is rotating CCW so increase
    if (digitalRead(RotaryDT) != CLKNow) {
      RotateCounter++;
      
    } else {
      // Encoder is rotating CW so decrease
      RotateCounter--;      
    }    
  }
  CLKPrevious = CLKNow;  // Store last CLK state
}


void printLCD()
{
  
  
  
    //lcd.clear();
    lcd.setCursor(0,0); // Defining positon to write from first row, first column .
    lcd.print("Clicks: ");
    lcd.setCursor(8,0); 
    lcd.print("        ");
    lcd.setCursor(8,0); 
    lcd.print(ButtonCounter);    //Print the number of button clicks
    
    lcd.setCursor(0,1); // Defining positon to write from second row, first column .
    lcd.print("Position: ");
    lcd.setCursor(10,1); 
    lcd.print("      ");
    lcd.setCursor(10,1); 
    lcd.print(RotateCounter);    //Print the number of pulses
    
    
}

void RunTheMotor() //function for the motor
{    
    stepper.enableOutputs(); //enable pins
    stepper.moveTo(RotateCounter); //-1 is to match the rotation of the encoder with the rotation of the stepper
    while(stepper.distanceToGo() != 0)
    {
      stepper.runToNewPosition(RotateCounter);
    }
    
}

Previous
Previous

Refrigeration with 4x TEC12706 Peltier Block

Next
Next

RF 433 Transmitter and Receiver with sensors and OLED displays