#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Encoder.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // Adresse I2C, nombre de colonnes, nombre de lignes
Encoder encoder(4, 2); // pin A et B de l'encodeur
const int BOUTON_ENCODEUR = 3; // pin du bouton de l'encodeur
class MenuItem {
public:
MenuItem(const char* text, void (*action)()) : text(text), action(action) {}
const char* text;
void (*action)();
};
class Menu {
public:
Menu(const char* name) : name(name), selectedItem(0), itemCount(0), firstItem(0), buttonState(HIGH), lastButtonState(HIGH) {}
void addMenuItem(const char* text, void (*action)()) {
if (itemCount < MAX_ITEMS) {
items[itemCount++] = new MenuItem(text, action);
}
}
int getSelectedItem() {
return selectedItem;
}
int getItemCount() {
return itemCount;
}
void display() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(name);
for (int i = 0; i < DISPLAY_ROWS; ++i) {
int index = i + firstItem;
lcd.setCursor(0, i + 1);
if (index == selectedItem) {
lcd.print(">");
} else {
lcd.print(" ");
}
if (index < itemCount) {
lcd.print(items[index]->text);
} else if (i == 0 && itemCount > DISPLAY_ROWS) {
lcd.print("..."); // Indiquer qu'il y a plus d'éléments à faire défiler
}
}
}
void selectNext() {
if (selectedItem < itemCount - 1) {
selectedItem++;
if (selectedItem >= firstItem + DISPLAY_ROWS) {
firstItem++;
}
}
}
void selectPrev() {
if (selectedItem > 0) {
selectedItem--;
if (selectedItem < firstItem) {
firstItem--;
}
}
}
void executeSelected() {
if (selectedItem >= 0 && selectedItem < itemCount) {
items[selectedItem]->action();
}
}
void checkButton() {
int buttonReading = digitalRead(BOUTON_ENCODEUR);
if (buttonReading == LOW && lastButtonState == HIGH) {
executeSelected();
delay(200); // Délai anti-rebond
}
lastButtonState = buttonReading;
}
private:
const char* name;
static const int MAX_ITEMS = 10; // Nombre maximal d'éléments de menu
static const int DISPLAY_ROWS = 1; // Nombre de lignes affichées à l'écran
MenuItem* items[MAX_ITEMS];
int selectedItem;
int itemCount;
int firstItem;
int buttonState;
int lastButtonState;
};
Menu mainMenu("Shredder");
Menu submenu1("Sous-Menu 1");
Menu submenu2("Sous-Menu 2");
Menu* currentMenu = &mainMenu;
void retourArriere() {
if (currentMenu != &mainMenu) {
currentMenu = &mainMenu;
}
}
void option1() {
lcd.clear();
lcd.print("Option 1 sélectionnée");
}
void option2() {
lcd.clear();
lcd.print("Option 2 sélectionnée");
}
void option3() {
lcd.clear();
lcd.print("Option 3 sélectionnée");
}
void option4() {
lcd.clear();
lcd.print("Option 4 sélectionnée");
}
void setup() {
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Menu avec Encodeur");
delay(1000);
lcd.clear();
mainMenu.addMenuItem("Sous-Menu 1", []() { currentMenu = &submenu1; });
mainMenu.addMenuItem("Sous-Menu 2", []() { currentMenu = &submenu2; });
submenu1.addMenuItem("Retour", retourArriere);
submenu1.addMenuItem("Option 1", option1);
submenu1.addMenuItem("Option 2", option2);
submenu2.addMenuItem("Retour", retourArriere);
submenu2.addMenuItem("Option 3", option3);
submenu2.addMenuItem("Option 4", option4);
// Configure la broche du bouton de l'encodeur en entrée avec résistance de pull-up
pinMode(BOUTON_ENCODEUR, INPUT_PULLUP);
// Initialise la communication série pour les messages de débogage
Serial.begin(9600);
currentMenu->display();
}
void loop() {
long encoderValue = encoder.read();
static bool buttonState = HIGH;
static bool lastButtonState = HIGH;
// Lire l'état du bouton
int buttonReading = digitalRead(BOUTON_ENCODEUR);
// Détection du flanc montant (relâchement du bouton)
if (buttonReading == LOW && lastButtonState == HIGH) {
currentMenu->executeSelected();
currentMenu->display();
delay(200); // Délai anti-rebond
Serial.println("Bouton enfoncé");
}
lastButtonState = buttonReading;
if (encoderValue > 0) {
currentMenu->selectNext();
currentMenu->display();
delay(200); // Délai anti-rebond
Serial.println("Rotation vers la droite");
} else if (encoderValue < 0) {
currentMenu->selectPrev();
currentMenu->display();
delay(200); // Délai anti-rebond
Serial.println("Rotation vers la gauche");
}
}