Help with Rotary Encoder, Push button, and Stepper Motor

What is intended is so that when the rotary encoder is turned, the motor turns with it, but if the button is pressed it will not move. This all works, but there is an integer keeping track of how many steps have been taken, and the motor won’t move if passed 0 - 5 (inclusive). The problem lays in that when the button is pressed and the rotary encoder is spun the int still count the movement. Any help would be appreciated!

#include <StepperMotor.h>
    #include <Stepper.h>
     
    /*
        To be used with Arduino Uno, Step Motor Servo, and Rotary Encoder.
        Turn encoder to turn motor, pushing down while turning double steps.    
    */
     
    // Stepper Variables
    StepperMotor stepper(8, 9, 10, 11);
    int totalturn = 0;
    long countSteps = 0;
     
    // Encoder pins
    int encoderPin1 = 2;
    int encoderPin2 = 3;
     
    // Encoder button pin
    int encoderSwitchPin = 4;
     
    // Encoder Variables
    volatile int lastEncoded = 0;
    volatile long encoderValue = 0;
    int oldval = 0;
    long lastencoderValue = 0;
    int lastMSB = 0;
    int lastLSB = 0;
    int countsafe = 0;
    // Limit switch button
    int limitSwitchPin = 5;
    boolean safetySwitch = true;
     
    void setup(){
      Serial.begin (9600);  //setup serial for debugging purposes
     
      stepper.setPeriod(5); // Set speed. Smaller = faster
     
      pinMode(encoderPin1,INPUT);  //initialize all encoder pins
      pinMode(encoderPin2,INPUT);
      pinMode(encoderSwitchPin, INPUT);
      pinMode(limitSwitchPin, INPUT);
     
      digitalWrite(encoderPin1, HIGH);  //turn pullup resistors on for both pins
      digitalWrite(encoderPin2, HIGH);
     
      attachInterrupt(0,updateEncoder, CHANGE);  //call updateEncoder() when any high/low changed seen
      attachInterrupt(1,updateEncoder, CHANGE);  //on interrupt 0 (pin 2), or interrupt 1 (pin 3)
     
      digitalWrite(encoderSwitchPin, HIGH);      //turn pullup resistor on
      digitalWrite(limitSwitchPin, HIGH);
    }
     
    // Updates and converts encoder value
    void updateEncoder(){
      int MSB = digitalRead(encoderPin1);         //MSB = most significant bit
      int LSB = digitalRead(encoderPin2);        //LSB = least significant bit
     
      int encoded = (MSB << 1) |LSB;             //converting the 2 pin value to single number
      int sum  = (lastEncoded << 2) | encoded;  //adding it to the previous encoded value
     
      if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011)// Detect direction of encoder
        encoderValue ++;
      if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000)
        encoderValue --;
      lastEncoded = encoded; //store this value for next time
    }
     
    void loop()
    {
      Serial.println("STAT OF MAIN LOOP");
      //TO DEBUG: REMOVE COMMENTS WITH SERIAL.PRINT
      /*
      Serial.println("VALUE OF ENCODER=");
      Serial.println(encoderValue);
      Serial.println("VALUE OF OLDVAL");
      Serial.println(oldval);
      */
      totalturn = 0;
      safetySwitch = (digitalRead(limitSwitchPin));
     
      if (safetySwitch==false){
        //Serial.println("SAFETYSWITCH FALSE");
        countsafe = 1;
        stepper.stop(true);
      }
      else {
        //Serial.println("FINISHED SAFETYSWITCH CHECK, TRUE");
      while (safetySwitch==true) {
       Serial.println("START OF WHILE LOOP");
        if (safetySwitch==false){
          //Serial.println("SAFETY SWITCH FALSE IN WHILE LOOP");
          countsafe = 1;
        break;}
        /*if (countSteps>5) {     // Soft boundary top
          countSteps=5;
        }
        if (countSteps<0) {      // Soft boundary bottom
          countSteps = 0;
        }*/
          /*if (digitalRead(encoderSwitchPin)== false) {     // Increase encoder sensitivity when pushed
            StepsPerTurn = 1;
          }
          else {
            StepsPerTurn = 2;
          }*/
         
          safetySwitch = (digitalRead(limitSwitchPin));
          //Serial.println("ABOUT TO RUN IF LOOP");
          if (encoderValue-oldval>0 && countSteps > 0 && safetySwitch==true)        // Limits movement to 5      CCW Rotation
          {
            //Serial.println("POSITIVE TURN LOOP SAFETY SWITCH WAS TRUE");
            Serial.print("WTF IS THE VALUE OF COUNTSAFE ");
            Serial.print(countsafe);
            Serial.println("");
            if (countsafe == 0){
            totalturn = 50;            //steps per turn
            stepper.move(totalturn);                  // Rotate
            stepper.stop();
            oldval = encoderValue;
            countSteps--;                              // Decrement steps
            Serial.println("STEPS TAKEN: ");          // Debug
            Serial.println(countSteps);
            totalturn = 0;
            stepper.reset(); 

             
            }
            else {
              Serial.println("COUNTSAFE IS ON, DONT ADD");
              countsafe = 0;
              break;
          }
          }
         
          else if (encoderValue-oldval<0 && countSteps < 5 && safetySwitch == true)  // Limits movement to 5 steps    CW Rotation
          {
           // Serial.println("NEGATIVE TURN LOOP SAFETY SWITCH WAS TRUE");
            Serial.print("WTF IS THE VALUE OF COUNTSAFE ");
            Serial.print(countsafe);
            Serial.println("");
             if (countsafe == 0){
            totalturn = -50;              // steps per turn
            stepper.move(totalturn);                    // Rotate
            stepper.stop();
            oldval = encoderValue;
            countSteps++;                              // Decrement steps
            Serial.println("STEPS TAKEN: ");          // Debug
            Serial.println(countSteps);
      
            totalturn = 0;
            stepper.reset();
              
            
              
            }
            else {
               Serial.println("COUNTSAFE IS ON, DONT ADD");
              countsafe = 0;
              break;
           
            }
          }
       }
      }
    }

Firstly I reckon you might want INPUT_PULLUP in all of these - encoders
are usually open-collector or switches to a shared ground…

      pinMode(encoderPin1,INPUT);  //initialize all encoder pins
      pinMode(encoderPin2,INPUT);
      pinMode(encoderSwitchPin, INPUT);
      pinMode(limitSwitchPin, INPUT);

For your encoder tracking I’d suggest this approach: two encoder counters,
one that is always stepped (then you know the absolute position should you
need it) and one that is controlled by a boolean:

volatile boolean count_both = true ;
volatile long gatedEncValue = 0L ;

// Updates and converts encoder value
    void updateEncoder(){
      int MSB = digitalRead(encoderPin1);         //MSB = most significant bit
      int LSB = digitalRead(encoderPin2);        //LSB = least significant bit
     
      int encoded = (MSB << 1) |LSB;             //converting the 2 pin value to single number
      int sum  = (lastEncoded << 2) | encoded;  //adding it to the previous encoded value
     
      if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011)// Detect direction of encoder
      {
        encoderValue ++;
        if (count_both)
          gatedEncValue ++ ;
      }
      if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000)
      {
        encoderValue --;
        if (count_both)
          gatedEncValue -- ;
      }
      lastEncoded = encoded; //store this value for next time
    }

Then just alter count_both as needed.

You also have a bug - you are accessing encoderValue from the rest of the
program without guarding against interrupts. You could define a getter
that is safe:

long getEncoderValue ()
{
  noInterrupts () ;
  long result = encoderValue ;
  interrupts () ;
  return result ;
}

Ditto for any other > 1 byte volatile variable.

Thank you for a response, we tried it but had no luck.

Care to post the code as it is now? "No luck" isn't much information to go on!

The button will be pressed and then we turn the knob and as soon as the button is released the value is updated, the value should be unchanged.

#include <StepperMotor.h>
    #include <Stepper.h>
     
    /*
        To be used with Arduino Uno, Step Motor Servo, and Rotary Encoder.
        Turn encoder to turn motor, pushing down while turning double steps.    
    */
     
    // Stepper Variables
    StepperMotor stepper(8, 9, 10, 11);
    int totalturn = 0;
    long countSteps = 0;
     
    // Encoder pins
    int encoderPin1 = 2;
    int encoderPin2 = 3;
     
    // Encoder button pin
    int encoderSwitchPin = 4;
     
    // Encoder Variables
    volatile int lastEncoded = 0;
    volatile long encoderValue = 0;
    int oldval = 0;
    long lastencoderValue = 0;
    int lastMSB = 0;
    int lastLSB = 0;
    int countsafe = 0;
    // Limit switch button
    int limitSwitchPin = 5;
    boolean safetySwitch = true;
     
    void setup(){
      Serial.begin (9600);  //setup serial for debugging purposes
     
      stepper.setPeriod(5); // Set speed. Smaller = faster
     
      pinMode(encoderPin1,INPUT_PULLUP);  //initialize all encoder pins
      pinMode(encoderPin2,INPUT_PULLUP);
      pinMode(encoderSwitchPin, INPUT_PULLUP);
      pinMode(limitSwitchPin, INPUT_PULLUP);
     
      digitalWrite(encoderPin1, HIGH);  //turn pullup resistors on for both pins
      digitalWrite(encoderPin2, HIGH);
     
      attachInterrupt(0,updateEncoder, CHANGE);  //call updateEncoder() when any high/low changed seen
      attachInterrupt(1,updateEncoder, CHANGE);  //on interrupt 0 (pin 2), or interrupt 1 (pin 3)
     
      digitalWrite(encoderSwitchPin, HIGH);      //turn pullup resistor on
      digitalWrite(limitSwitchPin, HIGH);
    }
    
    long getEncoderValue ()
{
  noInterrupts () ;
  long result = encoderValue ;
  interrupts () ;
  return result ;
}
     
    // Updates and converts encoder value
    volatile boolean count_both = true ;
    volatile long gatedEncValue = 0L ;
    void updateEncoder(){
      int MSB = digitalRead(encoderPin1);         //MSB = most significant bit
      int LSB = digitalRead(encoderPin2);        //LSB = least significant bit
     
      int encoded = (MSB << 1) |LSB;             //converting the 2 pin value to single number
      int sum  = (lastEncoded << 2) | encoded;  //adding it to the previous encoded value
     
      if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011)// Detect direction of encoder
      {
        encoderValue ++;
        if (count_both)
          gatedEncValue ++ ;
      }
      if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000)
      {
        encoderValue --;
        if (count_both)
          gatedEncValue -- ;
      }
      lastEncoded = encoded; //store this value for next time
    }
    
    
     
    void loop()
    {
      //TO DEBUG: REMOVE COMMENTS WITH SERIAL.PRINT
      /*
      Serial.println("VALUE OF ENCODER=");
      Serial.println(encoderValue);
      Serial.println("VALUE OF OLDVAL");
      Serial.println(oldval);
      */
      safetySwitch = (digitalRead(limitSwitchPin));
     
      if (safetySwitch==false){
        countsafe = 1;
        stepper.stop(true);
      }
      else {
        if (safetySwitch==false){
          countsafe = 1;
      }
          safetySwitch = (digitalRead(limitSwitchPin));
          if (encoderValue-oldval>0 && countSteps > 0 && safetySwitch==true)        // Limits movement to 5      CCW Rotation
          {
            if (countsafe == 0){
            totalturn = 50;            //steps per turn
            stepper.move(totalturn);                  // Rotate
            stepper.stop();
            oldval = encoderValue;
            countSteps--;                              // Decrement steps
            Serial.println("STEPS TAKEN: ");          // Debug
            Serial.println(countSteps);
            totalturn = 0;
            stepper.reset(); 
            }
            else {
              countsafe = 0;
          }
          }
         
          else if (encoderValue-oldval<0 && countSteps < 5 && safetySwitch == true)  // Limits movement to 5 steps    CW Rotation
          {
             if (countsafe == 0){
            totalturn = -50;              // steps per turn
            stepper.move(totalturn);                    // Rotate
            stepper.stop();
            oldval = encoderValue;
            countSteps++;                              // Decrement steps
            Serial.println("STEPS TAKEN: ");          // Debug
            Serial.println(countSteps);
      
            totalturn = 0;
            stepper.reset();
            }
            else {
              countsafe = 0;
           
            }
       }
      }
    }

Raxor53:
The button will be pressed and then we turn the knob and as soon as the button is released the value is updated, the value should be unchanged.

I give you all the information you need and you don't notice.

You need to use gatedEncValue if you want gated behaviour, you are not touching it

You have to set check_both appropriately to control the gating, then read gatedEncValue
if you want the gated value!

You need to write a safe getter for gatedEncValue as well, like I said: "Ditto for any other > 1 byte volatile variable."

Sorry, we only have two days of experience with anything Arduino related other than C/C++. I can’t find anything on gated behavior, what do you mean?

The gatedEncValue is conditionally controlled, conditionally on you setting
the count_both boolean. A logic gate controls a signal, hence the use gated

You asked for a way to only change the count when the relevant button was
off, you know have a mechanism for doing this, putting the parts together is
the next stage. The button controls count_both, and the getter(*) you are going
to add will access it in an interrupt-safe way (remember interrupts can happen
at any time and on the ATmega processors all memory accesses are 8 bit, so
reading a long variable is 4 separate instructions, the interrupt could get in
the middle and you'd see a corrupt value if so.

(*) a getter is a method/function that reads the value of a variable or property, allowing
some extra functionality to happen when reading it, here making the access
interrupt-safe). And yes you can have setters too.