Arduino Menu with Rotary Encoder

Hi Guys,
I think this should be an easy thing but I’m designing a menu system that I can use for a timelapse motion slider. There is people that have done this before but I’m doing it for a school project and I wanted to do as much of the coding myself as I could.
I’m using a standard 12mm rotary encoder from eBay and a rotary encoder library from:
https://www.pjrc.com/teensy/td_libs_Encoder.html

(I tried doing the code for this myself but it didn’t work)

Here is my code:

/* The circuit:
 * LCD RS pin to digital pin 12
 * LCD Enable pin to digital pin 11
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 9
 * LCD D7 pin to digital pin 8
 * LCD R/W pin to ground
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)
 
 http://www.arduino.cc/en/Tutorial/LiquidCrystal
 */

// include the library code:
#include <LiquidCrystal.h>
#include <Encoder.h>
int encoderVal = 0;
int menuVal = 0;
int NumToShow = 0;
int resetVal = 0; //value to reset encoder to
int buttonVal = 0;
int lastMenu = 0; //val to store menu value

Encoder myEnc(2, 3);
int buttonPin = 7;

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 9, 8);

void setup() {
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  digitalWrite (buttonPin, HIGH); //pullup internal pullup resistor
}

long oldPosition  = -999;

void loop() {
  long newPosition = myEnc.read();
  if (newPosition != oldPosition) { //this reads the rotary encoder
    oldPosition = newPosition;
    encoderVal = newPosition/4; //without this the encoder gives a 4,8,12,16 etc value instead of a 1,2,3,4 value
    menuVal = encoderVal;
    NumToShow =encoderVal;
  }
  buttonVal = digitalRead (buttonPin);

  if (menuVal >= 3 || menuVal < 0) { //This means that the menuVal is never greater than 3 or less than 0 as there are only 4 menu options
    myEnc.write (resetVal);
  }
  switch (menuVal) {
  case 0:
    lcd.setCursor (0,0);
    lcd.print("Main Menu: ");
    lcd.setCursor (0,1);
    lcd.print ("Turn For Option");
    break;

  case 1:
    lcd.setCursor (0,0);
    lcd.print ("Option 1 "); 
    lcd.setCursor (0,1);
    lcd.print ("   Num: 0       ");
    if (buttonVal == LOW) { //Here is the part I'm having trouble with:
      lastMenu = 1;
      menuVal = lastMenu;
      myEnc.write (resetVal);
      lcd.setCursor (0,1);
      lcd.print ("   Num: "); 
      lcd.print (NumToShow);
      if (buttonVal == LOW && lastMenu == 1) {
        myEnc.write (lastMenu);
      } //What I want it to do is store the last menuVal keep it in this case but change another variable 'NumToShow' with
      //the rotary encoder. 
    }
    break;
    /*
    case 2: 
     lcd.setCursor (0,0);
     lcd.print ("Option 2 "); 
     lcd.setCursor (0,1);
     lcd.print ("   Num:         "); 
     break;
     */
  } //this bottom one will be added in once I get the base program in case 1 working
}

My aim is to design a menu system using one rotary encoder with a built in pushbutton.
I want to read the encoder, give first a menu value between 0-3, when the pushbutton is pressed I want to store that last menuVal to keep the menu on that option. I then want to change a separate value using the rotary encoder by firstly resetting the encoderVal back to 0 and then printing that value next to Num: .

What its currently doing is correct for the code but not what I want it to do, it goes through the menu options starting with option 0 (Main Menu) when its is on option 1 I press the button and the menu resets to option 0 where I want it to save a value and remain on option 1 while changing a separate value which is then lcd.print ed.

I’m sorry if any of this doesn’t make sense! I was just trying to right my thoughts/plans out.
Thanks for any help,
Nathan

Any thoughts guys?

I am not knowledgeable enough to help you but here is a few links that might help in particular the setup of the menu library

http://www.ad7c.com/projects/ad9850-dds-vfo/

Hi Thaliums,
Thankyou for your reply, you helped me to realize that I can use a sub menu to save the different values for my timelapse slider.
Thank you for your simple yet helpful answer,
Nathan

nathman11:
I'm sorry if any of this doesn't make sense! I was just trying to right my thoughts/plans out.
Thanks for any help,

The simplest solution would be, if you don't need a full featured menu, but just a simple configuration like that:

  • no button pressed ==> normal program operation
  • button pressed once ==> you can edit first value by rotating left/right
  • button pressed once ==> you can edit second value by rotating left/right
  • button pressed once ==> you can edit third value by rotating left/right
  • button pressed once ==> return to normal program operation

The more 'menu like' functions you want, let's say while editing a value you want to have the choice between

  • "OK - use that value"
  • "Cancel - discard changes"
    the more complicated things will become.

Especially if you just have one button for the menu, you will finally have to put those two functions on a single button, such like "Cancel = short press" and "OK = long press". You could prevent this an make things simple when using a simple logic like shown above.