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); } }