#include <LiquidCrystal_I2C.h>
#include <OneButton.h>
#include <Encoder.h>
#include <EEPROM.h>
#define EEPROM_ADDRESS 0
#define LCD_ADDRESS 0x27
#define LCD_COLUMNS 16
#define LCD_ROWS 2
#define ROTARY_PIN1 2
#define ROTARY_PIN2 3
#define BUTTON_PIN 4
// Initialize the Encoder
Encoder myEnc(ROTARY_PIN1, ROTARY_PIN2);
LiquidCrystal_I2C lcd(LCD_ADDRESS, LCD_COLUMNS, LCD_ROWS);
OneButton button(BUTTON_PIN, true);
const char *menuItems[] = {"Option 1", "Option 2", "Option 3", "Option 4"};
int currentMenuItem = 1;
long oldPosition = -999;
bool adjustMode = false;
int adjustableVariable = 0; // Your adjustable variable
const int minAdjustableValue = -100; // Minimum value for adjustableVariable
const int maxAdjustableValue = 100; // Maximum value for adjustableVariable
const int adjustIncrement = 15; // Adjusted to 1 for finer control with Encoder library
// Function prototypes
void option1Function();
void option2Function();
void option3Function();
void option4Function();
void enterAdjustMode();
void click();
void adjustVariable();
void checkRotaryEncoder();
// Array of function pointers
void (*menuFunctions[])() = {option1Function, option2Function, option3Function, option4Function};
void setup() {
currentMenuItem = EEPROM.read(EEPROM_ADDRESS) % 4; // Ensure the read value is within bounds
Serial.begin(9600);
lcd.init();
lcd.backlight();
lcd.print("Menu: ");
lcd.setCursor(0, 1);
lcd.print(menuItems[currentMenuItem]);
button.attachClick(click);
button.attachLongPressStart(enterAdjustMode);
}
void loop() {
button.tick(); // Check button events
checkRotaryEncoder(); // Check the rotary encoder
}
void checkRotaryEncoder() {
long newPosition = myEnc.read() / 4; // Adjust the divisor for sensitivity
if (newPosition != oldPosition) {
int change = newPosition - oldPosition; // Calculate the change
oldPosition = newPosition; // Update oldPosition with the new reading
if (!adjustMode) {
if (change > 0) {
nextMenuItem();
} else if (change < 0) {
previousMenuItem();
}
} else {
// Adjust the variable when in adjust mode
adjustVariable(change);
}
}
}
void click() {
runSelectedMenuFunction();
}
void enterAdjustMode() {
adjustMode = true;
lcd.clear();
lcd.print("Adjusting: ");
lcd.setCursor(0, 1);
lcd.print("Variable: ");
}
void adjustVariable(long change) {
adjustableVariable += adjustIncrement * change;
adjustableVariable = constrain(adjustableVariable, minAdjustableValue, maxAdjustableValue);
updateLCD(); // Display the adjusted variable in real-time
}
void nextMenuItem() {
currentMenuItem = (currentMenuItem + 1) % (sizeof(menuItems) / sizeof(menuItems[0]));
updateLCD();
}
void previousMenuItem() {
currentMenuItem = (currentMenuItem - 1 + sizeof(menuItems) / sizeof(menuItems[0])) % (sizeof(menuItems) / sizeof(menuItems[0]));
updateLCD();
}
void updateEEPROM() {
EEPROM.write(EEPROM_ADDRESS, currentMenuItem-1);
}
void updateLCD() {
lcd.setCursor(0, 1);
lcd.print(" "); // Clear the line
lcd.setCursor(0, 1);
if (!adjustMode) {
lcd.print(menuItems[currentMenuItem]);
} else {
lcd.print(adjustableVariable);
}
}
void runSelectedMenuFunction() {
if (adjustMode) {
adjustMode = false;
myEnc.write(currentMenuItem * 4); // Reset encoder position based on menu item
} else {
updateEEPROM();
menuFunctions[currentMenuItem]();
}
lcd.clear();
lcd.print("Menu: ");
lcd.setCursor(0, 1);
lcd.print(menuItems[currentMenuItem]);
}
// Implement your specific functions for each menu item
void option1Function() {
Serial.println("Executing Option 1 function");
// Add your Option 1 functionality here
}
void option2Function() {
Serial.println("Executing Option 2 function");
// Add your Option 2 functionality here
}
void option3Function() {
Serial.println("Executing Option 3 function");
// Add your Option 3 functionality here
}
void option4Function() {
Serial.println("Executing Option 4 function");
// Add your Option 4 functionality here
}