#include <AccelStepper.h> //AccelStepper library
AccelStepper stepper(1, 9, 8);// 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 = 3; //DT pin on the rotary encoder
const int ButtonCW = 4; //Button for clockwise rotation
const int ButtonCCW = 5; //Button for counterclockwise rotation
//Defining variables
int RotateCounter = 0; //initial position
int MotorSpeed = 50; //some default value for steps/s
//Statuses
int CLKNow;
int CLKPrevious;
int DTNow;
int DTPrevious;
// Time
float TimeNow1;
float TimeNow2;
void setup()
{
Serial.begin(9600);
//------------------------------------------------------
lcd.init(); // initialize the lcd
lcd.init();
lcd.backlight();
//------------------------------------------------------
lcd.setCursor(0,0); //Defining positon to write from first row,first column .
lcd.print("Button stepping with");
lcd.setCursor(0,1);
lcd.print("AccelStepper()"); //You can write 16 Characters per line .
delay(1000); //wait 1 sec
//------------------------------------------------------
pinMode(2, INPUT_PULLUP); //we use the internal pullup resistor
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT); //CW button
pinMode(5, INPUT); //CCW button
//Store states
CLKPrevious = digitalRead(RotaryCLK);
DTPrevious = digitalRead(RotaryDT);
attachInterrupt(digitalPinToInterrupt(RotaryCLK), rotate, CHANGE);
stepper.setMaxSpeed(1000); //SPEED = Steps / second
stepper.setAcceleration(5000); //ACCELERATION = Steps /(second)^2
printLCD(); //Print the things on the LCD
TimeNow1 = millis(); //Start time
}
void loop()
{
//The motor only runs when one of the buttons are kept pressed
CheckButtons(); //Checking the status of the buttons
RunTheMotor(); //Running the motor
TimeNow2 = millis();
if(TimeNow2 - TimeNow1 > 200) //if the time difference is more than 200 ms (increase the number to print to the LCD less often)
{
updateLCD(); //Printing LCD (This slows down the stepping significantly, so use it less frequently)
TimeNow1 = millis();
}
}
void updateLCD()
{
//this function only updates the necessary parts
lcd.setCursor(7,0);
lcd.print(" "); //first we clear the area with spaces (it is important when you show a 3-digit number after a 4-digit number)
lcd.setCursor(7,0);
lcd.print(MotorSpeed); //Print the speed
lcd.setCursor(10,1);
lcd.print(" ");
lcd.setCursor(10,1);
lcd.print(stepper.currentPosition()); //Print the number of steps done from the origin (i.e. the position)
}
void printLCD()
{
lcd.setCursor(0,0); // Defining position to write from first row, first column .
lcd.print("Speed: ");
lcd.setCursor(8,0);
lcd.print(" ");
lcd.setCursor(8,0);
lcd.print(MotorSpeed); //Print the speed
lcd.setCursor(0,1); // Defining position to write from second row, first column .
lcd.print("Position: ");
lcd.setCursor(10,1);
lcd.print(" ");
lcd.setCursor(10,1);
lcd.print(stepper.currentPosition()); //Print the number of pulses
}
void RunTheMotor() //function for the motor
{
stepper.enableOutputs(); //enable pins
stepper.moveTo(RotateCounter); //tell the stepper to move to the 'RotateCounter'steps (absolute) position
while(stepper.distanceToGo() != 0)
{
stepper.setSpeed(MotorSpeed);
stepper.runSpeedToPosition();
//Serial.print("DistanceToGo: "); //for debugging
//Serial.println(stepper.distanceToGo());
}
//Serial.println(MotorSpeed); //for debugging
}
void CheckButtons()
{
//Serial.println(digitalRead(ButtonCW)); //Just for debugging
if(digitalRead(ButtonCW) == HIGH) //if the button is pressed
{
RotateCounter++; //increase the value of the variable, this represents the absolute position of the stepper
// Serial.print("ButtonCW: "); //for debugging
// Serial.println(stepper.distanceToGo());
//you can add delay here which is also a type of debouncing. It is useful when you want to click the button
//once and increase the steps (value of RotateCounter) only by one.
//delay(100); //Simplest thing to be able to use this function to add just 1 step at a time to use delay
}
//Serial.println(digitalRead(ButtonCCW)); //Just for debugging
if(digitalRead(ButtonCCW) == HIGH)
{
RotateCounter--; //decrease the value of the variable, this represents the absolute position of the stepper
//Serial.print("ButtonCCW: "); //for debugging
// Serial.println(stepper.distanceToGo());
//delay(100);
}
}
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)
{
MotorSpeed++;
}
else
{
// Encoder is rotating CW so decrease
MotorSpeed--;
}
stepper.setSpeed(MotorSpeed); //as this functions is not started from the loop() it is maybe good to update the speed here
}
CLKPrevious = CLKNow; // Store last CLK state
}