NEMA17 Rotary Encoder Control

I'm trying to control a NEMA17 stepper motor using two buttons, a rotary encoder and an A4988 stepper motor driver using the following code:
//Rewritten to not include the display
#include <AccelStepper.h>
AccelStepper stepper(1, 9, 8);// pulses Digital 9 (CLK); Direction Digital 8 (CCW)

//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 = 100; //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);
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(2000); //SPEED = Steps / second
stepper.setAcceleration(5000); //ACCELERATION = Steps /(second)^2
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)
{
TimeNow1 = millis();
}
}

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());
delay(5);
}
Serial.println(MotorSpeed); //for debugging
delay(5);
}

void CheckButtons()
{
Serial.println(digitalRead(ButtonCW)); //Just for debugging
delay(50);
if(digitalRead(ButtonCW) == HIGH) //if the button is pressed
{
RotateCounter += 16;

//increase the value of the variable, this represents the absolute position of the stepper

Serial.print("ButtonCW: "); //for debugging
Serial.println(stepper.distanceToGo());
delay(5);

//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(5); //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
delay(5);
if(digitalRead(ButtonCCW) == HIGH)
{
RotateCounter -= 16; //decrease the value of the variable, this represents the absolute position of the stepper

Serial.print("ButtonCCW: "); //for debugging
Serial.println(stepper.distanceToGo());
delay(5);

}
}

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 += 10;
}
else
{
// Encoder is rotating CW so decrease
MotorSpeed -= 10;
}
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
}
The motor doesn't operate, and the serial monitor constantly outputs the distance to go as 0. What do I do??

@sofanthiel Welcome to the forum.

However, you might want to look at this How to get the best out of this forum before you proceed any further.
We only know what you tell us, and without knowing what you have, and why you want to do this, we don't stand a chance.

It will also tell you how to post code correctly, not the way you did. It will tell you that you need to supply a schematic if you want help. Hand drawn and posted in the correct aspect ratio is fine. A physical layout diagram or pictures joined together with wires is not.

See no need for an encoder with a stepper motor. Buttons could be used to rotate motor

  • some predetermined # of steps
  • a single step
  • continually rotate CW or CCW

It would help to have a better explanation of what is intended

Please post the schematic of your project, even if it is freehand.
I don't understand how the buttons are connected to the processor.
What processor are you using?

Depending on how the buttons are connected, where you are using:
if (digitalRead(ButtonCW) == HIGH)
I think it should be:
if (digitalRead(ButtonCW) == LOW)

I'm trying to create a vertical conveyor storage system that allows me to store stuff in a way that's more space efficient (like the one from Wall-E). The rotary encoder is therefore useful as it allows me to adapt the speed dependent on the load on the stepper motor as it lifts stuff up on a pulley system. Everything I am doing is based on the work by Curious Scientist, as can be found here - Stepper motor control with buttons and rotary encoder — Curious Scientist . I simply do not use the LCD display, and replace his stepper driver with an economical A4998 I already had lying aound.

I have tried changing it to this, but pressing the buttons still doesn't cause the stepper motor to move at all. Here are the schematics though



what is the encoder used for?

is it turned by hand to determine the level (e.g. 0, 1, 2) the motor needs to reach and whcih a pre-defined # of steps or does the stepper motor track the encoder, one step at a time?

what are the buttons used for? couldn't they be used to simply inc/decrement the desired level like an elevator?

The rotary encoder dictates the speed of the NEMA17 motor and the buttons cause the motor to move either clockwise (CW) or counterclockwise (CCW) when pressed

C:\stuff\SW\Arduino\_Others\Tst\Tst.ino: In function 'void setup()':
Tst:37:5: error: 'stepper' was not declared in this scope
     stepper.setMaxSpeed (2000); //SPEED = Steps / second

why isn't stepper defined in the code you posted?

isn't the button pin HIGH when NOT pressed because you're using the internal pullup resistors?

before dealing with the encoder, suggest getting the buttons and servo to move to predefined positions

look this over

// based on https://www.airspayce.com/mikem/arduino/AccelStepper/ProportionalControl_8ino-example.html

#include <AccelStepper.h>

AccelStepper stepper; // Defaults to AccelStepper::FULL4WIRE pins 2, 3, 4, 5

const byte PinBut [] = { 4, 5 };
const int  Nbut      = sizeof(PinBut);
      byte butState [Nbut];

enum { CW, CCW };

const int PosDelta = 16;
const int PosMax   = 5 * PosDelta;
      int posMotor;

// -----------------------------------------------------------------------------
void loop ()
{
    // monitor buttons
    for (int n = 0; n < Nbut; n++)  {
        byte but = digitalRead (PinBut [n]); 
        if (butState [n] != but)  {             // state change
            butState [n]  = but;
            delay (30);                         // debounce

            if (LOW == but)  {                  // pressed
                if (CW == n)  {
                    posMotor += 16;
                    if (PosMax < posMotor)
                        posMotor = PosMax;
                }
                else  {
                    posMotor -= 16;
                    if (0 > posMotor)
                        posMotor = 0;
                }
                Serial.println (posMotor);
            }
        }
    }

    // run motor
    stepper.moveTo (posMotor);
    stepper.runSpeedToPosition ();
}


// -----------------------------------------------------------------------------
void setup ()
{
    Serial.begin (9600);

    for (int n = 0; n < Nbut; n++)  {
        pinMode (PinBut [n],  INPUT_PULLUP);
        butState [n] = digitalRead (PinBut [n]);
    }

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

    Serial.println ("ready");
}