Hello guys, new to Arduino and the forum.
I'm having a real hard time creating an LCD menu with a rotary encoder.
I've set up my basic code for the rotary encoder and switch button. It counts up and down fine and detects when the button is pressed. The counters and button have there own interrupt loops and aren't ran in the main loop.
I'm just looking for general advice on how to create a simple menu with sub menus.
such as ;
Menu 1 > Submenu 1 ; Option 1, Option 2
Menu 2 > Submenu 2 ; etc.
Menu 3 > Submenu 3 ; etc.
The main problem I'm having is differentiating the counted steps from one another. I can get the first layer to work where Menu 1 = counter = 1, Menu 2 = counter = 2 and so on but obviously with that logic the minute I go into another menu and rotate the encoder the menu will just go to menu 2 if I select menu 1 with the push button because the count is on going. If only there was a way to restart the count in each menu and ignore the rest the loop then this method might work.
Basically I'm just looking for general logic on how to set this up. The counter seems nice but it doesn't looks like I'll be able to get it to work this way. if there's a better way to go about this please let me know.
Any input is appreciated.
//NOTES:
//const int: Read only, used if value never changes, saves memory
//int: Read and write, used if value changes, uses more memory
// include the library code:
#include <LiquidCrystal.h>
//Define Encoder Pins
#define outputA 19 // Generating interrupts using CLK signal, int.3
#define outputB 20 // Reading DT signal, int.4
#define SW 18 // Reading Push Button switch SW, int.5
//Define Encoder Variables
int counter = 0;
int counterLast = 0;
int maxCounter = 1;
int aState;
int aLastState;
int SWState;
int SWStateLast;
int pushed = 0;
int page = 1;
int menuPosition = 0;
int menuPositionLast = 0;
//initialize the library with the numbers of the interface pins
const int rs = 40, en = 41, d4 = 42, d5 = 43, d6 = 44, d7 = 45;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
//LCD Contrast
int Con = 100;
//Arrow right
byte arrow[8] = {
B00000,
B00100,
B00010,
B11111,
B00010,
B00100,
B00000,
B00000
};
void setup() {
Serial.begin(9600);
Serial.println("Menu Test");
//Reads the initial state of the outputA
aLastState = digitalRead(outputA);
//Activate Encoder Pins
pinMode (outputA, INPUT_PULLUP);
pinMode (outputB, INPUT_PULLUP);
pinMode (SW, INPUT_PULLUP);
//Call updateEncoder() when any high/low changed seen
attachInterrupt(3, updateEncoder, CHANGE); //outputA
attachInterrupt(4, updateEncoder, CHANGE); //outputB
attachInterrupt(5, pushButton, CHANGE); //SW
//Create arrow char
lcd.createChar(0, arrow);
//LCD Contrast
int Con = 100;
//Controls LCD's contrast
analogWrite(11, Con);
lcd.begin(16, 2);
}//void setup
void loop() {
if (counter > counterLast) {
menuPosition ++;
}
if (counter < counterLast) {
menuPosition - 1;
}
menuPositionLast = menuPosition;
Serial.println(menuPosition);
counterLast = counter; //Save the value of the last state
delay(10);
}//void loop
void updateEncoder() {
//CODE TO CONTROL ENCODER TURNS
//Reads the "current" state of the outputA
aState = digitalRead(outputA);
// If last and current state of CLK are different, then pulse occurred
// React to only 1 state change to avoid double count
if (aState != aLastState && aState == 1) {
//If the outputB state is different to the outputA state, that means the encoder is rotating clockwise
if (digitalRead(outputB) != aState) {
//LOOP FOR ENCODER ROTATING CLOCKWISE
if (counter < maxCounter) { //counter does not go above max
counter ++; //encoder is rotating CW
}
else {
counter = 0; //go back to 0 so the counter keeps looping, this way the
//encoder can be rotated in only one direction for control
}
//LOOP FOR ENCODER ROTATING COUNTER CLOCKWISE
} else {
if (counter < 1) { //counter does go below 0
counter = maxCounter;
}
else {
counter --; //encoder is rotating CCW
}
}
//Serial.println(counter);
}
//Updates the previous state of the outputA with the current state
aLastState = aState;
//Put in a slight delay to help debounce the reading
delay(10);
}//void updateEncoder
void pushButton () {
// Read the button state
SWState = digitalRead(SW);
if (SWState == LOW) {
pushed = 1;
Serial.println("Pushed");
} else {
pushed = 0;
}
delay(10);
}