Newsettings for NewEncoder library not working

I'm using @gfvalvo’s newEncoder library. I'd like to change the range of the encoder for a submenu that is navigated with an LCD. I actually found another thread on here where a user was struggling with a very similar issue and was able to get his code working which can be found here.

However I am having limited success. My encoder range does change when I want it to, but instead of changing the range from -20 to 20 like I want, it is changing the range to between -1 and 1.

The library provides a newSettings function that allows one to dynamically reset the min / max encoder values.

 bool newSettings(int16_t newMin, int16_t newMax, int16_t newCurrent, EncoderState &state); 

To my eye everything seems to look correct and also comparing my code to the above referenced thread where they were able to successfully reconfigure the range of their encoder. Any idea why my reconfigured range is so wrong? Here is my code

#include "Arduino.h"
#include "NewEncoder.h"

// Pins 2 and 3 should work for many processors, including Uno. See README for meaning of constructor arguments.
// Use FULL_PULSE for encoders that produce one complete quadrature pulse per detnet, such as: https://www.adafruit.com/product/377
// Use HALF_PULSE for endoders that produce one complete quadrature pulse for every two detents, such as: https://www.mouser.com/ProductDetail/alps/ec11e15244g1/?qs=YMSFtX0bdJDiV4LBO61anw==&countrycode=US&currencycode=USD
NewEncoder encoder(5, 18, 1, 8, 1, HALF_PULSE);
int16_t prevEncoderValue;
int button = 19;
int selected = false;
int16_t prevSpinValue = 0;

void Button() {
  selected = !selected;
  if (selected == true) {
    Serial.println("Selected");
  }
  if (selected == false) {
    Serial.println("Not Selected");
  }
}

void setup() {
  NewEncoder::EncoderState state;

  Serial.begin(115200);
  delay(100);
  Serial.println("Starting");

  if (!encoder.begin()) {
    encoder.getState(state);
    Serial.print("Encoder Successfully Started at value = ");
    prevEncoderValue = state.currentValue;
    Serial.println(prevEncoderValue);
  }
  attachInterrupt(digitalPinToInterrupt(button), Button, RISING);
}

void loop() {
  int16_t currentValue;
  int16_t spinValue;
  NewEncoder::EncoderState currentEncoderState;
  if (selected == true) {
    encoder.newSettings(-20, 20, 0, currentEncoderState);
    if (encoder.getState(currentEncoderState)) {
      Serial.print("Encoder: ");
      spinValue = currentEncoderState.currentValue;
      if (spinValue != prevSpinValue) {
        Serial.println(spinValue);
        prevSpinValue = spinValue;
      } else
        switch (currentEncoderState.currentClick) {
          case NewEncoder::UpClick:
            Serial.println("at upper limit.");
            break;

          case NewEncoder::DownClick:
            Serial.println("at lower limit.");
            break;

          default:
            break;
        }
    }
  }
  if (selected == false) {
    encoder.newSettings(1, 8, prevEncoderValue, currentEncoderState);
    if (encoder.getState(currentEncoderState)) {
      Serial.print("Encoder: ");
      currentValue = currentEncoderState.currentValue;
      if (currentValue != prevEncoderValue) {
        Serial.println(currentValue);
        prevEncoderValue = currentValue;
      } else
        switch (currentEncoderState.currentClick) {
          case NewEncoder::UpClick:
            Serial.println("at upper limit.");
            break;

          case NewEncoder::DownClick:
            Serial.println("at lower limit.");
            break;

          default:
            break;
        }
    }
  }
}

Newbies are advised against attempting to use interrupts ... especially for reading buttons where there're never needed. The code below works (without interrupts for the button) on an Uno. You didn't specify what board you're using. Note that being only example code, there is no debouncing for the button.

#include "Arduino.h"
#include "NewEncoder.h"

// Pins 2 and 3 should work for many processors, including Uno. See README for meaning of constructor arguments.
// Use FULL_PULSE for encoders that produce one complete quadrature pulse per detnet, such as: https://www.adafruit.com/product/377
// Use HALF_PULSE for endoders that produce one complete quadrature pulse for every two detents, such as: https://www.mouser.com/ProductDetail/alps/ec11e15244g1/?qs=YMSFtX0bdJDiV4LBO61anw==&countrycode=US&currencycode=USD

struct EncoderSettings {
  int16_t low;
  int16_t high;
  int16_t start;
};

uint16_t settingIndex = 0;

const EncoderSettings settings[] = {
  { -20, 20, 0 },
  { 40, 50, 45 }
};

NewEncoder encoder(2, 3, settings[settingIndex].low, settings[settingIndex].high, settings[settingIndex].start, HALF_PULSE);
int16_t prevEncoderValue;
const uint8_t button = 7;

void setup() {
  NewEncoder::EncoderState state;

  Serial.begin(115200);
  delay(2000);
  Serial.println("Starting");

  if (!encoder.begin()) {
    Serial.println("Encoder Failed to Start. Check pin assignments and available interrupts. Aborting.");
    while (1) {
      yield();
    }
  } else {
    encoder.getState(state);
    Serial.print("Encoder Successfully Started at value = ");
    prevEncoderValue = state.currentValue;
    Serial.println(prevEncoderValue);
  }
  pinMode(button, INPUT_PULLUP);
}

void loop() {

  int16_t currentValue;
  NewEncoder::EncoderState currentEncoderState;
  static int lastButtonSate = digitalRead(button);

  int buttonReading = digitalRead(button);
  if (buttonReading != lastButtonSate) {
    lastButtonSate = buttonReading;
    if (buttonReading == LOW) {
      Serial.println("Toggling Encoder Settngs");
      settingIndex++;
      settingIndex &= 0b1;
      encoder.newSettings(settings[settingIndex].low, settings[settingIndex].high, settings[settingIndex].start, currentEncoderState);
      currentValue = currentEncoderState.currentValue;
      Serial.print("Encoder: ");
      Serial.println(currentValue);
    }
  }

  if (encoder.getState(currentEncoderState)) {
    Serial.print("Encoder: ");
    currentValue = currentEncoderState.currentValue;
    if (currentValue != prevEncoderValue) {
      Serial.println(currentValue);
      prevEncoderValue = currentValue;
    } else
      switch (currentEncoderState.currentClick) {
        case NewEncoder::UpClick:
          Serial.println("at upper limit.");
          break;

        case NewEncoder::DownClick:
          Serial.println("at lower limit.");
          break;

        default:
          break;
      }
  }
}

Thanks for the reply. I am using an ESP32. Specifically this one. I am aware there is no debouncing for the button. I was trying to get the encoder working properly as this is just a building block that will integrate with other code.

Is there any issue with an ESP32 with this code? I just removed the button interrupt and set the variable selected as true by default to see if it would correctly allow the encoders range to be -20 to 20, but it still limited me to -1 to 1.

Did you try the code I provided on your ESP32 (changing pin numbers as required)? Did it work?

Hi @gfvalvo, thanks so much. That code did work. However there's one other new issue. I adjusted the code to include a debounce for the button. It debounces the button, but it also seems to be adding some kind of bounce back into the encoder. So for example if I press the button when the encoder value is 2 it will register the button press just once as I hoped, but it also seems to bounce the encoder value up or down by 1. Given that the button pin is not the same as pins for the encoder I wasn't sure how to deal with this or why it would register as an encoder click.

Here is the code for that.

Check again the code I posted. Note the following lines after the call to encoder.newSettings(). These lines don't appear in your code. Try adding them. If it still doesn't look right, post sample output from the Serial monitor displaying the issue.

      currentValue = currentEncoderState.currentValue;
      Serial.print("Encoder: ");
      Serial.println(currentValue);

Okay here is that section of code after I added the lines you mentioned back in, but it didn't resolve the issue. Serial monitor output examples below.

  //Calculate the time since the last button reading
  TimeSinceLastButtonReading = (millis() - TimeOfLastButtonReading);  //If enough time has passed for debounce, read the button state
  if (TimeSinceLastButtonReading > debounceThreshold) {
    buttonReading = digitalRead(button);
    if (buttonReading != buttonState) {  //If the button state has changed, update the button state variable
      buttonState = buttonReading;
      if (buttonState == LOW) {                 //If the button is pressed, toggle through the different encoder settings
        encoder.getState(currentEncoderState);  //Get the current state of the encoder and set the setting index based on the current value
        currentValue = currentEncoderState.currentValue;
        if (currentValue == 1) {
          settingIndex = 1;
        } else if (currentValue == 2) {
          settingIndex = 2;
        } else if (currentValue == 3) {
          settingIndex = 3;
        } else {
          settingIndex = 0;
        }
        encoder.newSettings(settings[settingIndex].low, settings[settingIndex].high, settings[settingIndex].start, currentEncoderState);
        currentValue = currentEncoderState.currentValue;
        Serial.print("Encoder: ");
        Serial.println(currentValue);
        Serial.print("Encoder Settings Toggled to Index ");
        Serial.println(settingIndex);
      }
      TimeOfLastButtonReading = millis();
    }
  }

Here are two screenshots from the serial monitor. In both examples the button was pressed when the encoder value was 2. Each time I got a different result. Once when the button was pressed the encoder ticked up by 1. On a different occasion the encoder ticked down by 1.


Please post the complete new code.

Sure here it is.

#include "Arduino.h"
#include "NewEncoder.h"

// Define a struct to store encoder settings (upper and lower limits and starting position)
struct EncoderSettings {
  int16_t low;    // lower limit of encoder values
  int16_t high;   // upper limit of encoder values
  int16_t start;  // starting position of encoder
};

// Define an index to keep track of current encoder setting
uint16_t settingIndex = 0;

// Define an array of encoder settings
const EncoderSettings settings[] = {
  { -20, 20, 0 },     // Setting 0: lower limit -20, upper limit 20, starting position 0
  { 40, 50, 45 },     // Setting 1: lower limit 40, upper limit 50, starting position 45
  { 100, 150, 100 },  // Setting 2: lower limit 100, upper limit 150, starting position 100
  { 200, 250, 210 }   // Setting 3: lower limit 200, upper limit 250, starting position 210
};

//Create a NewEncoder object with pin assignments and initial settings from the settings array
NewEncoder encoder(5, 18, settings[settingIndex].low, settings[settingIndex].high, settings[settingIndex].start, FULL_PULSE);

int16_t prevEncoderValue;  //Initialize a variable to store the previous encoder value

//Define the button pin and initialize time variables
const uint8_t button = 19;
int TimeOfLastButtonReading = 0;
int TimeSinceLastButtonReading;

//Set the debounce threshold for the button
int debounceThreshold = 20;

//Initialize variables for button reading and state
int buttonReading;
bool buttonState = HIGH;
bool lastButtonState = HIGH;

void setup() {
  NewEncoder::EncoderState state;  //Create a NewEncoder::EncoderState object to hold the state of the encoder

  Serial.begin(115200);  //Start serial communication

  delay(2000);  //Delay for 2 seconds

  Serial.println("Starting");

  //If the encoder fails to start, print an error message to the serial monitor and enter an infinite loop
  if (!encoder.begin()) {
    Serial.println("Encoder Failed to Start. Check pin assignments and available interrupts. Aborting.");
    while (1) {
      yield();
    }
  }
  //Otherwise, get the current state of the encoder and print the starting value to the serial monitor
  else {
    encoder.getState(state);
    Serial.print("Encoder Successfully Started at value = ");
    prevEncoderValue = state.currentValue;
    Serial.println(prevEncoderValue);
  }

  pinMode(button, INPUT_PULLUP);  //Set the button pin as an input with internal pull-up resistor
}

void loop() {

  //Declare variables for current encoder value and encoder state
  int16_t currentValue;
  NewEncoder::EncoderState currentEncoderState;

  //Calculate the time since the last button reading
  TimeSinceLastButtonReading = (millis() - TimeOfLastButtonReading);  //If enough time has passed for debounce, read the button state
  if (TimeSinceLastButtonReading > debounceThreshold) {
    buttonReading = digitalRead(button);
    if (buttonReading != buttonState) {  //If the button state has changed, update the button state variable
      buttonState = buttonReading;
      if (buttonState == LOW) {                 //If the button is pressed, toggle through the different encoder settings
        encoder.getState(currentEncoderState);  //Get the current state of the encoder and set the setting index based on the current value
        currentValue = currentEncoderState.currentValue;
        if (currentValue == 1) {
          settingIndex = 1;
        } else if (currentValue == 2) {
          settingIndex = 2;
        } else if (currentValue == 3) {
          settingIndex = 3;
        } else {
          settingIndex = 0;
        }
        encoder.newSettings(settings[settingIndex].low, settings[settingIndex].high, settings[settingIndex].start, currentEncoderState);
        currentValue = currentEncoderState.currentValue;
        Serial.print("Encoder: ");
        Serial.println(currentValue);
        Serial.print("Encoder Settings Toggled to Index ");
        Serial.println(settingIndex);
      }
      TimeOfLastButtonReading = millis();
    }
  }

  if (encoder.getState(currentEncoderState)) {
    Serial.print("Encoder: ");
    currentValue = currentEncoderState.currentValue;
    if (currentValue != prevEncoderValue) {
      Serial.println(currentValue);
      prevEncoderValue = currentValue;
    } else
      switch (currentEncoderState.currentClick) {
        case NewEncoder::UpClick:
          Serial.println("at upper limit.");
          break;

        case NewEncoder::DownClick:
          Serial.println("at lower limit.");
          break;

        default:
          break;
      }
  }
}

I am still too novice of a coder to understand if this is accurate or not, but I asked chat gpt what might be causing the encoder to tick and it suggested that updating the encoder settings may be causing the encoder to tick. Is that a possibility? Here is chat gpt's explanation.

The NewEncoder library used in this code has a function called newSettings() that is used to update the encoder settings. When this function is called, it adjusts the internal state of the encoder to match the new settings. This may involve moving the encoder shaft to a new starting position, or adjusting the limits of the encoder's range of motion. As a result, the encoder may physically rotate, causing the ticking sound.

A perfect example of a little (artificial) knowledge being a dangerous thing. It seems unlikely that something in the code would cause a physical movement of the encoder's shaft or a "click" ... unless a stepper motor or servo was involved.

I made a few minor modifications to your code and it behaves exactly how I'd expect. If you find differently, post Serial Monitor output and a description of how it's behavior differs from your expectations.

Note that I changed the encoder and button pins to work with an Uno. Change them back as appropriate for your platform.

#include "Arduino.h"
#include "NewEncoder.h"

// Define a struct to store encoder settings (upper and lower limits and starting position)
struct EncoderSettings {
  int16_t low;    // lower limit of encoder values
  int16_t high;   // upper limit of encoder values
  int16_t start;  // starting position of encoder
};

// Define an index to keep track of current encoder setting
uint16_t settingIndex = 0;

// Define an array of encoder settings
const EncoderSettings settings[] = {
  { -20, 20, 0 },     // Setting 0: lower limit -20, upper limit 20, starting position 0
  { 40, 50, 45 },     // Setting 1: lower limit 40, upper limit 50, starting position 45
  { 100, 150, 100 },  // Setting 2: lower limit 100, upper limit 150, starting position 100
  { 200, 250, 210 }   // Setting 3: lower limit 200, upper limit 250, starting position 210
};

//Create a NewEncoder object with pin assignments and initial settings from the settings array
NewEncoder encoder(2, 3, settings[settingIndex].low, settings[settingIndex].high, settings[settingIndex].start, FULL_PULSE);

int16_t prevEncoderValue;  //Initialize a variable to store the previous encoder value

//Define the button pin and initialize time variables
const uint8_t button = 7;

//Set the debounce threshold for the button
uint8_t debounceThreshold = 20;

void setup() {
  NewEncoder::EncoderState state;  //Create a NewEncoder::EncoderState object to hold the state of the encoder

  Serial.begin(115200);  //Start serial communication

  delay(2000);  //Delay for 2 seconds

  Serial.println("Starting");

  //If the encoder fails to start, print an error message to the serial monitor and enter an infinite loop
  if (!encoder.begin()) {
    Serial.println("Encoder Failed to Start. Check pin assignments and available interrupts. Aborting.");
    while (1) {
      yield();
    }
  }
  //Otherwise, get the current state of the encoder and print the starting value to the serial monitor
  else {
    encoder.getState(state);
    Serial.print("Encoder Successfully Started at value = ");
    prevEncoderValue = state.currentValue;
    Serial.println(prevEncoderValue);
  }

  pinMode(button, INPUT_PULLUP);  //Set the button pin as an input with internal pull-up resistor
}

void loop() {
  //Declare variables for current encoder value and encoder state
  int16_t currentValue;
  NewEncoder::EncoderState currentEncoderState;
  uint32_t TimeSinceLastButtonReading;
  int buttonReading;
  uint32_t currentMillis = millis();
  static uint32_t TimeOfLastButtonReading = currentMillis;
  static int buttonState = digitalRead(button);

  //Calculate the time since the last button reading
  TimeSinceLastButtonReading = currentMillis - TimeOfLastButtonReading;  //If enough time has passed for debounce, read the button state
  if (TimeSinceLastButtonReading > debounceThreshold) {
    buttonReading = digitalRead(button);
    if (buttonReading != buttonState) {  //If the button state has changed, update the button state variable
      buttonState = buttonReading;
      if (buttonState == LOW) {                 //If the button is pressed, toggle through the different encoder settings
        encoder.getState(currentEncoderState);  //Get the current state of the encoder and set the setting index based on the current value
        currentValue = currentEncoderState.currentValue;
        if ((currentValue >= 0) && (currentValue < 4)) {
          settingIndex = currentValue;
        } else {
          settingIndex = 0;
        }

        encoder.newSettings(settings[settingIndex].low, settings[settingIndex].high, settings[settingIndex].start, currentEncoderState);
        currentValue = currentEncoderState.currentValue;
        Serial.print("Encoder Settings Toggled to Index ");
        Serial.println(settingIndex);
        Serial.print("Updated Encoder Value: ");
        Serial.println(currentValue);
        prevEncoderValue = currentValue;
      }
      TimeOfLastButtonReading = currentMillis;
    }
  }

  if (encoder.getState(currentEncoderState)) {
    Serial.print("Encoder: ");
    currentValue = currentEncoderState.currentValue;
    if (currentValue != prevEncoderValue) {
      Serial.println(currentValue);
      prevEncoderValue = currentValue;
    } else {
      switch (currentEncoderState.currentClick) {
        case NewEncoder::UpClick:
          Serial.println("at upper limit.");
          break;

        case NewEncoder::DownClick:
          Serial.println("at lower limit.");
          break;

        default:
          break;
      }
    }
  }
}

Thanks unfortunately it did not change the behavior, but I noticed one thing that was consistent about the behavior is that whatever direction the encoder had been moving in prior to the button press is also the direction the encoder ticks down to. So if I had been moving the encoder 5, 4, 3, 2. Press the button on 2, then it will tick down to 1. If had been moving the encoder -2, -1, 0, 1, 2. Press the button on 2 then it will tick up to 3. I hope that helps.

I so appreciate your willingness to problem solve. Here are two screenshots of the serial monitor output again with your most recent code. I didn't change anything about the code other than changing the pins that were set for arduino uno. I also tried two other encoders to ensure it wasn't an issue with the encoder itself.

Encoder direction moving Counter Clockwise then button press


Encoder direction moving Clockwise then button press

I tried the same code that I posted on an ESP32 .... still not seeing that issue.

Is the button / switch integral to the encoder? If so maybe the mechanical action of the switch is bouncing the encoder's rotation sensing contacts. Try using a discrete switch instead. And / or, try a different encoder.

@gfvalvo okay everything is working, but it appears that a lot of this was due to a bug in arduino IDE that I didn't catch. I have auto scroll turned on in my serial monitor which appears to work correctly but in reality it's showing me the 2nd to last line. So as I would dial the encoder down to 2 as shown on my serial monitor there was actually another line that it wouldn't auto scroll to which would have shown the encoder value is at 1. So when I would press the button, auto scroll would reveal the line "Encoder: 1" that was already there but appeared to me as a new line, but also the new lines indicating Index 1 had been toggled.

So sorry you spent time troubleshooting that. Thank you so much for your help. It's a great encoder library and debounces the encoder better than anything else I had tried previously.

Interesting. Glad it worked out.

@gfvalvo sorry one last question. Is there a simple way to store the last encoder value from each settingIndex so that when returned back to that settingIndex again it returns to the same encoder value instead of the starting position? I was attempting to do that with this code.

#include "Arduino.h"
#include "NewEncoder.h"

int16_t mainMenuValue;          //integer to store speed value
int16_t speedValue;             //integer to store speed value
int16_t feedValue;              //integer to store speed value
int16_t spinValue;              //integer to store speed value
int16_t oscillationValue;       //integer to store speed value
int16_t oscillationRangeValue;  //integer to store speed value
int16_t oscillationSpeedValue;  //integer to store speed value
int16_t drillsValue;            //integer to store speed value

// Define a struct to store encoder settings (upper and lower limits and starting position)
struct EncoderSettings {
  int16_t low;    // lower limit of encoder values
  int16_t high;   // upper limit of encoder values
  int16_t start;  // starting position of encoder
};

// Define an index to keep track of current encoder setting
uint16_t settingIndex = 0;
// Define variable for encoder value
int16_t currentValue;

// Define an array of encoder settings
const EncoderSettings settings[] = {
  { 1, 7, mainMenuValue },            // Setting 0: Main Menu lower limit 1, upper limit 7, starting position 1
  { 1, 50, speedValue },  // Setting 1: Speed Menu lower limit 1, upper limit 50, starting position 10
  { 0, 30, feedValue },           // Setting 2: Feed Menu lower limit 0, upper limit 30, starting position 3
  { -20, 20, spinValue },         // Setting 3: Spin Menu lower limit -20, upper limit 20, starting position 0
  { 0, 1, oscillationValue },            // Setting 4: Oscillation Menu lower limit 0, upper limit 1, starting position 0
  { 1, 20, oscillationRangeValue },           // Setting 5: Oscillation Range Menu lower limit 1, upper limit 20, starting position 1
  { 1, 15, oscillationSpeedValue },           // Setting 6: Oscillation Speed Menu lower limit 1, upper limit 15, starting postion 3
  { 0, 1, drillsValue }             // Setting 7: Drills lower limit 0, upper limit 1, starting position 0
};

//Create a NewEncoder object with pin assignments and initial settings from the settings array
NewEncoder encoder(5, 18, settings[settingIndex].low, settings[settingIndex].high, settings[settingIndex].start, FULL_PULSE);

int16_t prevEncoderValue;        //Initialize a variable to store the previous encoder value
const uint8_t button = 19;       //Define the button pin and initialize time variables
uint8_t debounceThreshold = 20;  //Set the debounce threshold for the button

bool mainMenuSelected = true;           // initialize that main menu is selected
bool speedSelected = false;             // initialize that speed menu is not selected
bool feedSelected = false;              // initialize that feed menu is not selected
bool spinSelected = false;              // initialize that spin menu is not selected
bool oscillationSelected = false;       // initialize that oscillation menu is not selected.
bool oscillationRangeSelected = false;  // initialize that oscillation range menu is not selected
bool oscillationSpeedSelected = false;  // initialize that oscillation speed menu is not selected
bool drillsSelected = false;            // initialize that drills menu is not selected
bool subMenu = false;

void subMenuSelected() {
  mainMenuSelected = false;
  subMenu = true;
  switch (currentValue) {
    case 1:
      speedSelected = true;
      mainMenuSelected = false;
      feedSelected = false;
      spinSelected = false;
      oscillationSelected = false;
      oscillationRangeSelected = false;
      oscillationSpeedSelected = false;
      drillsSelected = false;
      Serial.println("Speed is selected");
      break;
    case 2:
      feedSelected = true;
      mainMenuSelected = false;
      speedSelected = false;
      spinSelected = false;
      oscillationSelected = false;
      oscillationRangeSelected = false;
      oscillationSpeedSelected = false;
      drillsSelected = false;
      Serial.println("Feed is selected");
      break;
    case 3:
      spinSelected = true;
      mainMenuSelected = false;
      speedSelected = false;
      feedSelected = false;
      oscillationSelected = false;
      oscillationRangeSelected = false;
      oscillationSpeedSelected = false;
      drillsSelected = false;
      Serial.println("Spin is selected");
      break;
    case 4:
      oscillationSelected = true;
      mainMenuSelected = false;
      speedSelected = false;
      feedSelected = false;
      spinSelected = false;
      oscillationRangeSelected = false;
      oscillationSpeedSelected = false;
      drillsSelected = false;
      Serial.println("Oscillation is selected");
      break;
    case 5:
      oscillationRangeSelected = true;
      mainMenuSelected = false;
      speedSelected = false;
      feedSelected = false;
      spinSelected = false;
      oscillationSelected = false;
      oscillationSpeedSelected = false;
      drillsSelected = false;
      Serial.println("Oscillation Range is selected");
      break;
    case 6:
      oscillationSpeedSelected = true;
      mainMenuSelected = false;
      speedSelected = false;
      feedSelected = false;
      spinSelected = false;
      oscillationSelected = false;
      oscillationRangeSelected = false;
      drillsSelected = false;
      Serial.println("Oscillation Speed is selected");
      break;
    case 7:
      drillsSelected = true;
      mainMenuSelected = false;
      speedSelected = false;
      feedSelected = false;
      spinSelected = false;
      oscillationSelected = false;
      oscillationRangeSelected = false;
      oscillationSpeedSelected = false;
      Serial.println("Drills is selected");
      break;
  }
}
void deSelectSubMenus() {  // unSelects all menus
  subMenu = false;
  mainMenuSelected = true;
  speedSelected = false;
  feedSelected = false;
  spinSelected = false;
  oscillationSelected = false;
  oscillationRangeSelected = false;
  oscillationSpeedSelected = false;
  drillsSelected = false;
  Serial.println("All Menus Unselected");
}
void setMachineValues() {
  if (mainMenuValue == true) {
    mainMenuValue = currentValue;
    Serial.print("Main Menu Value is ");
    Serial.println(currentValue);
  }
  if (speedSelected == true) {
    speedValue = currentValue;
    Serial.print("Speed Value is ");
    Serial.println(speedValue);
  }
  if (feedSelected == true) {
    feedValue = currentValue;
    Serial.print("Feed Value is ");
    Serial.println(feedValue);
  }
  if (spinSelected == true) {
    spinValue = currentValue;
    Serial.print("Spin Value is ");
    Serial.println(spinValue);
  }
  if (oscillationSelected == true) {
    oscillationValue = currentValue;
    Serial.print("Oscillation Value is ");
    Serial.println(oscillationValue);
  }
  if (oscillationRangeSelected == true) {
    oscillationRangeValue = currentValue;
    Serial.print("Oscillation Range is ");
    Serial.println(oscillationRangeValue);
  }
  if (oscillationSpeedSelected == true) {
    oscillationSpeedValue = currentValue;
    Serial.print("Oscillation Speed is ");
    Serial.println(oscillationSpeedValue);
  }
  if (drillsSelected == true) {
    drillsValue = currentValue;
    Serial.print("Drills value is ");
    Serial.println(drillsValue);
  }
}
void storedValues() {
  if (mainMenuSelected == true) {
    currentValue = mainMenuValue;
  }
  if (speedSelected == true) {
    currentValue = speedValue;
  }
  if (feedSelected == true) {
    currentValue = feedValue;
  }
  if (spinSelected == true) {
    currentValue = spinValue;
  }
  if (oscillationSelected == true) {
    currentValue = oscillationValue;
  }
  if (oscillationRangeSelected == true) {
    currentValue = oscillationRangeValue;
  }
  if (oscillationSpeedSelected == true) {
    currentValue = oscillationSpeedValue;
  }
  if (drillsSelected == true) {
    currentValue = drillsValue;
  }
}
void setup() {
  NewEncoder::EncoderState state;  //Create a NewEncoder::EncoderState object to hold the state of the encoder

  Serial.begin(115200);  //Start serial communication

  delay(2000);  //Delay for 2 seconds

  Serial.println("Starting");

  //If the encoder fails to start, print an error message to the serial monitor and enter an infinite loop
  if (!encoder.begin()) {
    Serial.println("Encoder Failed to Start. Check pin assignments and available interrupts. Aborting.");
    while (1) {
      yield();
    }
  }
  //Otherwise, get the current state of the encoder and print the starting value to the serial monitor
  else {
    encoder.getState(state);
    Serial.print("Encoder Successfully Started at value = ");
    prevEncoderValue = state.currentValue;
    Serial.println(prevEncoderValue);
  }

  pinMode(button, INPUT_PULLUP);  //Set the button pin as an input with internal pull-up resistor
  speedValue = 10;                //initializes speedValue at 10;
  feedValue = 3;                  //initializes feedValue at 3;
  spinValue = 0;                  //initializes spinValue at 0;
  oscillationValue = 0;           //initializes oscillationValue at 0;
  oscillationRangeValue = 1;      //initializes oscillationRangeValue at 1;
  oscillationSpeedValue = 3;      //initializes oscillationSpeedValue at 1;
  drillsValue = 0;                //initializes drillsValue at 0;
  mainMenuValue = 1;              //initializes mainMenuValue at 1;
}

void loop() {
  //Declare variables for current encoder value and encoder state
  NewEncoder::EncoderState currentEncoderState;
  uint32_t TimeSinceLastButtonReading;
  int buttonReading;
  uint32_t currentMillis = millis();
  static uint32_t TimeOfLastButtonReading = currentMillis;
  static int buttonState = digitalRead(button);

  //Calculate the time since the last button reading
  TimeSinceLastButtonReading = currentMillis - TimeOfLastButtonReading;  //If enough time has passed for debounce, read the button state
  if (TimeSinceLastButtonReading > debounceThreshold) {
    buttonReading = digitalRead(button);
    if (buttonReading != buttonState) {  //If the button state has changed, update the button state variable
      buttonState = buttonReading;
      if (buttonState == LOW) {                 //If the button is pressed, toggle through the different encoder settings
        encoder.getState(currentEncoderState);  //Get the current state of the encoder and set the setting index based on the current value
        currentValue = currentEncoderState.currentValue;
        if ((currentValue >= 0) && (currentValue < 7) && (subMenu == false)) {
          subMenuSelected();
          settingIndex = currentValue;
        } else {
          settingIndex = 0;
          deSelectSubMenus();
        }
        encoder.newSettings(settings[settingIndex].low, settings[settingIndex].high, settings[settingIndex].start, currentEncoderState);
        currentValue = currentEncoderState.currentValue;
        storedValues();
        Serial.print("Encoder Settings Toggled to Index ");
        Serial.println(settingIndex);
        Serial.print("Updated Encoder Value: ");
        Serial.println(currentValue);
        prevEncoderValue = currentValue;
      }
      TimeOfLastButtonReading = currentMillis;
    }
  }

  if (encoder.getState(currentEncoderState)) {
    currentValue = currentEncoderState.currentValue;
    if (currentValue != prevEncoderValue) {
      setMachineValues();
      Serial.println(currentValue);
      prevEncoderValue = currentValue;
    } else {
      switch (currentEncoderState.currentClick) {
        case NewEncoder::UpClick:
          Serial.println("at upper limit.");
          break;

        case NewEncoder::DownClick:
          Serial.println("at lower limit.");
          break;

        default:
          break;
      }
    }
  }
}

I'd store it in the settings[] array. You'd have to remove the 'const' sprecifier:

EncoderSettings settings[] = {

Then:

    if (currentValue != prevEncoderValue) {
      setMachineValues();
      Serial.println(currentValue);
      settings[settingIndex].start = currentValue;    // <-------- Here
      prevEncoderValue = currentValue;
    } else {

That worked flawlessly. That completes my encoder portion of this project. Thank you again!