I’m working on an arduino project using a keypad 4x4, a lcd screen, 8 relays. A RTC 3232. It’s divided in several files .cpp/.h. The following code consist on a menu for relays managing. It’s called from the main loop by using a button calling mainMenu(). This code works but I want you optimise the menu (information on the screen, delays…) feel free to reorgonize to make a better code, and advice me about kind of improvement you can do (uning ables, créating other functions…).
//Menu.cpp
#include <Arduino.h>
#include <Keypad.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "RELAIS.h"
#include "HORLOGE.h"
#include "Menu.h"
#include "Elec.h"
#include "Temperature.h"
Elec elec3;

const byte ROWS = 4;
const byte COLS = 4;
byte rowPins[ROWS] = { 33, 32, 31, 30 };
byte colPins[COLS] = { 29, 28, 27, 26 };
char key;

char keys[ROWS][COLS] = {
  { '1', '2', '3', 'A' },
  { '4', '5', '6', 'B' },
  { '7', '8', '9', 'C' },
  { '*', '0', '#', 'D' }
};

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
extern LiquidCrystal_I2C lcd(0x27, 20, 4);

void Initialisation_LCD(){
Wire.begin();
lcd.init();
lcd.noBacklight();
}

void mainMenu() {
  lcd.clear();lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print(DateHeure());  
  lcd.setCursor(0, 2);
  lcd.print("A-RELAIS  B-INFO");
  lcd.setCursor(0, 3);
  lcd.print("D-QUITTER");

  char key = keypad.waitForKey();
  switch (key) {
    case 'A': relaisMenu(); break;
    case 'B': infoMenu(); break;
    case 'D': lcd.clear(); lcd.noBacklight(); break;
  }
}

void relaisMenu() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Choix relai #");

  int relai_choisi = getKeypadValue(1, Relais_Nb, "Entrez numero relai #");
  relai_choisi = relai_choisi - 1 ;
  lcd.setCursor(0, 2);
  lcd.print("A:ON/OFF B:TIMER ");
  lcd.setCursor(0, 3);
  lcd.print("C:PROGRAM D:EXIT ");

bool exitFlag = false;
while (!exitFlag) {
  char key = keypad.waitForKey();
  int value;

  switch (key) {
    case 'A':
      updateRelayState(relai_choisi, !Relais_Statut[relai_choisi]);
      lcd.clear(); 
      lcd.setCursor(0, 0);
      lcd.print("Relai : ");
      lcd.print(relai_choisi + 1);
      lcd.setCursor(0, 1);
      if (Relais_Statut[relai_choisi] == 1) {lcd.print("ON!");} else {lcd.print("OFF!");}      
      delay(1500);
      exitFlag = true;
      lcd.clear(); lcd.noBacklight(); break;

      
    case 'B':
      value = getKeypadValue(0, 999, "Durée : ");
      if (value > -1) {
        updateRelayState(relai_choisi, !Relais_Statut[relai_choisi]);
        Relais_Timer[relai_choisi] = value;
      lcd.clear(); 
      lcd.setCursor(0, 0);
      lcd.print("Relai : ");
      lcd.print(relai_choisi + 1);
      lcd.setCursor(0, 1);
      if (Relais_Statut[relai_choisi] == 1) {lcd.print("ON!");} else {lcd.print("OFF!");}
      lcd.setCursor(0, 2);
      lcd.print("Durée : ");
      lcd.print(value);   
      delay(1500);
      lcd.clear(); lcd.noBacklight();        
          }
      exitFlag = true;
      break;

    case 'C':
      int Prog_dispo =  Renvoi_Programme_Horaire_Dispo(relai_choisi);
          Relais_Prog_Actif[relai_choisi][Prog_dispo] = 1;
          Relais_Prog_Consigne[relai_choisi][Prog_dispo] = getKeypadValue(0, 1, "Consigne 1=ON/0=OFF");          
          Relais_Prog_Heure[relai_choisi][Prog_dispo] =  getKeypadValue(0, 24, "Heure programme ");
          Relais_Prog_Minute[relai_choisi][Prog_dispo] =  getKeypadValue(0, 60, "Minute programme ");
          Relais_Prog_Timer[relai_choisi][Prog_dispo] =  getKeypadValue(0, 999, "Timer ");
          Relais_Prog_Minute[relai_choisi][Prog_dispo] =  getKeypadValue(0, 60, "Recurrent 1=O/0=N ");         
      exitFlag = true;
      lcd.clear();lcd.noBacklight();
      break;

    case 'D':
      exitFlag = true;
      lcd.clear();lcd.noBacklight();
      break;
  }
}
}

int getKeypadValue(int minVal, int maxVal, char* infoText) {
  lcd.clear();
  lcd.setCursor(0, 3);
  lcd.print("A-VALIDER D-QUITTER");

  lcd.setCursor(0, 0);
  lcd.print(infoText);
    
  int value = 0;
  bool exitFlag = false;
  while (!exitFlag) {
    char key = keypad.waitForKey();

    if (key >= '0' && key <= '9') {
      int newVal = value * 10 + (key - '0');
      if (newVal >= minVal && newVal <= maxVal) {
        value = newVal;
        lcd.print(key);
        delay(1000);
      }
    } else if (key == 'D') {
      return -1; // Annuler l'entrée
    } else if (key == 'A') {
      exitFlag = true;
    }
  }

  return value;
}

void infoMenu() {
  // Gérer l'affichage et l'interaction avec le menu d'informations
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("A-Temp   B-Hum");
  lcd.setCursor(0, 1);
  lcd.print("D-Quit");

  bool quit = false;
  while (!quit) {
    char key = keypad.waitForKey();
    switch (key) {
      case 'A': 
        showTemps();
        quit = true; 
        lcd.clear();lcd.noBacklight();
        break;

      case 'B': 
        ShowElec(); 
        quit = true; 
        lcd.clear();lcd.noBacklight();
        break;

      case 'D': 
        quit = true; 
        lcd.clear();lcd.noBacklight();
        break;
    }
  }
}

void showTemps() {
  lcd.clear();
    for (int i = 0; i < Nb_Dallas; i++) {
    lcd.setCursor(0, i);
    lcd.print("T1: ");
    lcd.print(tab_Dallas[i]);
    lcd.setCursor(10, i);
    }

char key;
do {
  key = keypad.waitForKey();
} while (key != 'D');
}

void ShowElec() {
  lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("T: ");
    lcd.print(elec3.voltage);
    for (int i = 0; i < Nb_Capteurs_Intensite; i++) {
    lcd.setCursor(0, i+1);
    lcd.print("I1: ");
    lcd.print(elec3.intensite[i]);
    lcd.setCursor(10, i+1);
    lcd.print("P1: ");
    lcd.print(elec3.puissance[i]);
    }

  char key;
  do {
    key = keypad.waitForKey();
  } while (key != 'D');
}