Menus choix d'une fonction

Bonjour,
J'ai fais un menu pour le LCD me permettant de choisir un paramètre.
Je souhaite aussi faire un menu permettant de choisir mon programme.
Actuellement programme() est le seul mais à terme il y aura programme 1(), 2(), 3()...etc
Dans le code suivant je n'ai qu'un programme :

#include <LiquidCrystal.h>
#include <EEPROM.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
int entree_menus = 44;
int commande_monter = 50;
int commande_retour = 51;
int securite = 53;
int contact_moteur = 22;
int electro_vanne_1 = 24;
int tempo_retour_automatique;

enum etat : byte {
  BUTTON_NONE, 
  BUTTON_UP,    
  BUTTON_DOWN,  
  BUTTON_LEFT,  
  BUTTON_RIGHT, 
  BUTTON_SELECT,
  PROGRAMME_EN_ATTENTE,
  PROGRAMME_MONTEE,
  PROGRAMME_ARRET_MONTEE,
  PROGRAMME_SECURITE,
  PROGRAMME_RETOUR_AUTO,
  REGLAGES_EN_ATTENTE,
  MENU_TEMPORISATION,
  REGLAGES_RETOUR
};
etat etat_programme = PROGRAMME_EN_ATTENTE;
etat etat_reglages = REGLAGES_EN_ATTENTE;

void setup() {
  lcd.begin(16, 2);
  EEPROM.get(10,tempo_retour_automatique);
  lcd.setCursor(0, 0);
  lcd.write("Digital Dock");
  delay (1000);
  lcd.setCursor(0, 1);
  lcd.write("v1.11");
  delay(5000);
  pinMode(entree_menus, INPUT);
  pinMode(commande_monter, INPUT);
  pinMode(commande_retour, INPUT);
  pinMode(securite, INPUT);
  pinMode(contact_moteur, OUTPUT);
  pinMode(electro_vanne_1, OUTPUT);
  lcd.clear();
}

byte getPressedButton() {
int value = analogRead(A0);
  if (value < 50)
    return BUTTON_RIGHT;
  else if (value < 250)
    return BUTTON_UP;
  else if (value < 410)
    return BUTTON_DOWN;
  else if (value < 550)
    return BUTTON_LEFT;
  else if (value < 850)
    return BUTTON_SELECT;
  else
    return BUTTON_NONE;
}

void loop()
{
  if (digitalRead(entree_menus) == HIGH){
  reglages();
  } 
  else{
  programme();
  }
}

void programme()
{
  static unsigned long lancement_retour;

    switch (etat_programme) {
        case PROGRAMME_EN_ATTENTE:
        digitalWrite(electro_vanne_1,HIGH);
        if ((digitalRead(securite) == HIGH)&&(digitalRead(commande_monter) == HIGH)) {
            lcd.setCursor(0, 0);
            lcd.print("MONTER          ");
            lcd.setCursor(0, 1);
            lcd.print("                ");
            digitalWrite(contact_moteur,HIGH);
            etat_programme = PROGRAMME_MONTEE;
        }
        if (digitalRead(securite) == LOW){
            lcd.setCursor(0, 0);
            lcd.print("SECURITES       ");
            lcd.setCursor(0, 1);
            lcd.print("P1              ");
            digitalWrite(contact_moteur,LOW);
            digitalWrite(electro_vanne_1,LOW);
            etat_programme = PROGRAMME_SECURITE;
        }
        if ((digitalRead(securite) == HIGH)&&(digitalRead(commande_retour) == HIGH)){
            lcd.setCursor(0, 0);
            lcd.print("RETOUR          ");
            lcd.setCursor(0, 1);
            lcd.print("AUTOMATIQUE     ");
            digitalWrite(contact_moteur,HIGH);
            lancement_retour = millis();
            etat_programme = PROGRAMME_RETOUR_AUTO;
        }     
        break;
      
        case PROGRAMME_MONTEE:
        if ((digitalRead(securite) == HIGH)&&(digitalRead(commande_monter) == HIGH)){
            digitalWrite(contact_moteur,HIGH);
            etat_programme = PROGRAMME_ARRET_MONTEE;
        }
        break;
      
        case PROGRAMME_ARRET_MONTEE:
        if ((digitalRead(securite) == HIGH)&&(digitalRead(commande_monter) == LOW)) {
            lcd.clear();
            digitalWrite(contact_moteur,LOW);
            etat_programme = PROGRAMME_EN_ATTENTE;
        }
        break;

        case PROGRAMME_SECURITE:
        if (digitalRead(securite) == HIGH) {
            lcd.clear();
            delay (1000);
            etat_programme = PROGRAMME_EN_ATTENTE;
        }
        break; 
       
        case PROGRAMME_RETOUR_AUTO:
        if (digitalRead(commande_retour) == HIGH) {
            digitalWrite(contact_moteur,HIGH);
            etat_programme = PROGRAMME_EN_ATTENTE;
        }
        if (digitalRead(securite) == LOW){
            lcd.setCursor(0, 0);
            lcd.print("SECURITES       ");
            lcd.setCursor(0, 1);
            lcd.print("P1              ");
            digitalWrite(contact_moteur,LOW);
            digitalWrite(electro_vanne_1,LOW);
            etat_programme = PROGRAMME_SECURITE;
        }
        else {
            if (millis() - lancement_retour >= tempo_retour_automatique) {
            digitalWrite(contact_moteur,LOW);
            lcd.clear();
            etat_programme = PROGRAMME_EN_ATTENTE;
            }
        }
        break; 
    }
}


void reglages()
{
    switch (etat_reglages) {
        case REGLAGES_EN_ATTENTE:
            if (digitalRead(entree_menus) == LOW){
            delay (500);
            programme();
            }
            else {
            digitalWrite(contact_moteur,LOW);
            digitalWrite(electro_vanne_1,LOW);
            etat_reglages = MENU_TEMPORISATION;
            }
        break;

        case MENU_TEMPORISATION:
            lcd.setCursor(0, 0);
            lcd.print("TEMPORISATION   ");
            lcd.setCursor(0, 1);
            lcd.print("RETOUR AUTO     ");
            
            if (getPressedButton() == BUTTON_RIGHT) {
            lcd.clear();
            etat_reglages = REGLAGES_RETOUR;
            }
            if (digitalRead(entree_menus) == LOW){
            lcd.clear();
            etat_reglages = REGLAGES_EN_ATTENTE;
            delay (200);
            }
        break;

        case REGLAGES_RETOUR:
            lcd.setCursor(0, 0);
            lcd.print("TEMPORISATION   ");
            lcd.setCursor(15, 1);
            lcd.print("S");
            lcd.setCursor(12, 1);
            lcd.print(tempo_retour_automatique/1000);

            if (getPressedButton() == BUTTON_UP) {
            delay (100);
            tempo_retour_automatique = tempo_retour_automatique + 1000;
            tempo_retour_automatique = constrain(tempo_retour_automatique,1000,30000);
            lcd.clear();
            etat_reglages = REGLAGES_RETOUR;
            }

            if (getPressedButton() == BUTTON_DOWN) {
            delay (100);
            tempo_retour_automatique = tempo_retour_automatique - 1000;
            tempo_retour_automatique = constrain(tempo_retour_automatique,1000,30000);
            lcd.clear();
            etat_reglages = REGLAGES_RETOUR;
            }  
    
            if (getPressedButton() == BUTTON_LEFT) {
            EEPROM.put(10,tempo_retour_automatique);
            lcd.clear();
            lcd.setCursor(0,0);
            lcd.print("    REGLAGES    ");
            lcd.setCursor(0,1);
            lcd.print("   ENREGISTRES  ");
            delay(1500);
            etat_reglages = MENU_TEMPORISATION;
            }
        
            if (digitalRead(entree_menus) == LOW){
            lcd.clear(); 
            etat_reglages = REGLAGES_EN_ATTENTE;
            }
        break;  
    }
}

Vous avez une question?

Oui
Je souhaite créer d'autres programme()1evA 1evB 2evA...etc qui ressemblent à programme()
Ça ça va.
Mais depuis les réglages l'utilisateur va sélectionner son mode de fonctionnement 1evA 1evB...etc et lorsque il sortira du menu et retourne donc dans la boucle programme 1evA() sera appelé.

Je ne sais pas comment m'y prendre.

le souci c'est que c'est un peu spaghetti déjà... Dans la loop() vous appelez reglages() ou programme() en fonction du mode (switch entree_menus) mais dans reglages vous appelez directement programme() si le switch a été inversé et que vous étiez dans REGLAGES_EN_ATTENTE. vous n'êtes pas obligé de faire cela, laissez le tranquillement revenir à la loop et tester à ce ne niveau.

ensuite vous devriez avoir une liste de pointeur sur fonctions qui correspondent au différents "programmes" que vous pouvez choisir. La loop devrait uniquement appeler en boucle le programme en cours et le menu sert à changer ce programme

Merci vous résumer ce que je souhaite faire mais je ne connais pas ces "pointeurs" et je ne sais pas comment faire avez vous une piste ou tuto à me conseiller. Votre tuto sur la machine a état m'ayant déjà bien servit :wink:

Concernant la vérification régulière du switch entrées menus je vais régler cela.

Merci

voici un exemple ou 3 fonctions (programmes) sont appelée dans la loop jusqu'à ce qu'ils soient terminés auquel cas je passe au suivant (et boucle à la fin)

enum t_etatPgm : byte {DEBUT, ENCOURS, FIN};

typedef t_etatPgm (*t_pgmPtr)(); // le type t_pgmPtr est un pointeur sur une fonction qui retourne un t_etatPgm et ne prend pas de param

t_etatPgm pgm1() {
  static t_etatPgm etat = DEBUT;
  if (etat == DEBUT) {Serial.println("Debut PGM 1"); etat = ENCOURS;} // INITIALISATION
  // le coeur du code, ici 0.5% de chance d'avoir fini
  if (random(0, 101) < 5) {etat = DEBUT; Serial.println("Fin PGM 1"); delay(100); return FIN;}
  return ENCOURS;
}

t_etatPgm pgm2() {
  static t_etatPgm etat = DEBUT;
  if (etat == DEBUT) {Serial.println("Debut PGM 2"); etat = ENCOURS;} // INITIALISATION
  // le coeur du code, ici 0.5% de chance d'avoir fini
  if (random(0, 1001) < 5) {etat = DEBUT; Serial.println("Fin PGM 2"); delay(100); return FIN;}
  return ENCOURS;
}

t_etatPgm pgm3() {
  static t_etatPgm etat = DEBUT;
  if (etat == DEBUT) {Serial.println("Debut PGM 3"); etat = ENCOURS;} // INITIALISATION
  // le coeur du code, ici 0.5% de chance d'avoir fini
  if (random(0, 1001) < 5) {etat = DEBUT; Serial.println("Fin PGM 3"); delay(100); return FIN;}
  return ENCOURS;
}

t_pgmPtr lesPgms[]={pgm1, pgm2, pgm3};
const byte nbPgm = sizeof lesPgms / sizeof * lesPgms;

void setup() {
  Serial.begin(115200); Serial.println();
  Serial.print("Il y a "); Serial.print(nbPgm); Serial.println(" programmes");
}

void loop() {
  static byte pgmCourant = 0;
  if (lesPgms[pgmCourant]() == FIN) { // si l'appelle au programme en cours nous dit qu'il a fini, on passe au suivant
    if (++pgmCourant >= nbPgm) pgmCourant = 0;
  }
}

les programmes ne font rien de bien magique, il y a un état initial qui permet une initialisation au moment du premier déclenchement , puis l'État reste ENCOURS tant que le code n'est pas fini. Quand il a fini (ici un tirage aléatoire avec 5% de chances de finir) le programme retourne FIN ce qui permet à l'appelant de passer au programme suivant.

Le code suivant

typedef t_etatPgm (*t_pgmPtr)(); 

est ce qui définit un type pointeur sur une fonction qui retourne un t_etatPgm et ne prend pas de param

le nom de la fonction est le pointeur sur la fonction , donc je peux créer un tableau avec mes 3 pointeurs sur fonctions

t_pgmPtr lesPgms[]={pgm1, pgm2, pgm3};

l'appel de la fonction (par exemple la première) se fait simplement par

lesPgms[0]();

ça aide ?

j'ai pas testé, je n'ai pas mon arduino sous la main, mais ça devrait marcher si je n'ai pas tapé de bêtises

Merci du retour, je vais essayer cela et surtout bien comprendre.
En attendant j'ai un peu modifié mon code, bon c'est pas propre mais cela fonctionne.
En fait cela me convient sauf que dans le menu pour regler les modes de fonctionnement au lieu de voir apparaitre 1 2 ou 3 je souhaite que l'utilisateur lise 1EV A ou 2EV A...

#include <LiquidCrystal.h>
#include <EEPROM.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
int entree_menus = 44;
int commande_monter = 50;
int commande_retour = 51;
int securite = 53;
int contact_moteur = 22;
int electro_vanne_1 = 24;
int tempo_retour_automatique;
int modnumero;

enum etat : byte {
  BUTTON_NONE, 
  BUTTON_UP,    
  BUTTON_DOWN,  
  BUTTON_LEFT,  
  BUTTON_RIGHT, 
  BUTTON_SELECT,
  PROGRAMME_EN_ATTENTE,
  PROGRAMME_MONTEE,
  PROGRAMME_ARRET_MONTEE,
  PROGRAMME_SECURITE,
  PROGRAMME_RETOUR_AUTO,
  REGLAGES_EN_ATTENTE,
  MENU_TEMPORISATION,
  REGLAGES_RETOUR,
  MENU_MOD,
  REGLAGES_MOD
};
etat etat_programme = PROGRAMME_EN_ATTENTE;
etat etat_reglages = REGLAGES_EN_ATTENTE;

void setup() {
  lcd.begin(16, 2);
  EEPROM.get(10,tempo_retour_automatique);
  EEPROM.get(30,modnumero);
  lcd.setCursor(0, 0);
  lcd.write("Digital Dock");
  delay (1000);
  lcd.setCursor(0, 1);
  lcd.write("v1.11");
  delay(5000);
  pinMode(entree_menus, INPUT);
  pinMode(commande_monter, INPUT);
  pinMode(commande_retour, INPUT);
  pinMode(securite, INPUT);
  pinMode(contact_moteur, OUTPUT);
  pinMode(electro_vanne_1, OUTPUT);
  lcd.clear();
}

byte getPressedButton() {
int value = analogRead(A0);
  if (value < 50)
    return BUTTON_RIGHT;
  else if (value < 250)
    return BUTTON_UP;
  else if (value < 410)
    return BUTTON_DOWN;
  else if (value < 550)
    return BUTTON_LEFT;
  else if (value < 850)
    return BUTTON_SELECT;
  else
    return BUTTON_NONE;
}



void loop()
{
  if (digitalRead(entree_menus) == HIGH){
  reglages();
  } 
  else{
  if (modnumero == 1){
  programme_1();
  }
  if (modnumero == 2){
  programme_2();
  }
  }
}

void programme_2()
{
            lcd.setCursor(0, 0);
            lcd.print("MOD2            ");
            lcd.setCursor(0, 1);
            lcd.print("                ");
}
           
void programme_1()
{
  static unsigned long lancement_retour;

    switch (etat_programme) {
        case PROGRAMME_EN_ATTENTE:
        digitalWrite(electro_vanne_1,HIGH);
        if ((digitalRead(securite) == HIGH)&&(digitalRead(commande_monter) == HIGH)) {
            lcd.setCursor(0, 0);
            lcd.print("MONTER          ");
            lcd.setCursor(0, 1);
            lcd.print("                ");
            digitalWrite(contact_moteur,HIGH);
            etat_programme = PROGRAMME_MONTEE;
        }
        if (digitalRead(securite) == LOW){
            lcd.setCursor(0, 0);
            lcd.print("SECURITES       ");
            lcd.setCursor(0, 1);
            lcd.print("P1              ");
            digitalWrite(contact_moteur,LOW);
            digitalWrite(electro_vanne_1,LOW);
            etat_programme = PROGRAMME_SECURITE;
        }
        if ((digitalRead(securite) == HIGH)&&(digitalRead(commande_retour) == HIGH)){
            lcd.setCursor(0, 0);
            lcd.print("RETOUR          ");
            lcd.setCursor(0, 1);
            lcd.print("AUTOMATIQUE     ");
            digitalWrite(contact_moteur,HIGH);
            lancement_retour = millis();
            etat_programme = PROGRAMME_RETOUR_AUTO;
        }     
        break;
      
        case PROGRAMME_MONTEE:
        if ((digitalRead(securite) == HIGH)&&(digitalRead(commande_monter) == HIGH)){
            digitalWrite(contact_moteur,HIGH);
            etat_programme = PROGRAMME_ARRET_MONTEE;
        }
        break;
      
        case PROGRAMME_ARRET_MONTEE:
        if ((digitalRead(securite) == HIGH)&&(digitalRead(commande_monter) == LOW)) {
            lcd.clear();
            digitalWrite(contact_moteur,LOW);
            etat_programme = PROGRAMME_EN_ATTENTE;
        }
        break;

        case PROGRAMME_SECURITE:
        if (digitalRead(securite) == HIGH) {
            lcd.clear();
            delay (1000);
            etat_programme = PROGRAMME_EN_ATTENTE;
        }
        break; 
       
        case PROGRAMME_RETOUR_AUTO:
        if (digitalRead(commande_retour) == HIGH) {
            digitalWrite(contact_moteur,HIGH);
            etat_programme = PROGRAMME_EN_ATTENTE;
        }
        if (digitalRead(securite) == LOW){
            lcd.setCursor(0, 0);
            lcd.print("SECURITES       ");
            lcd.setCursor(0, 1);
            lcd.print("P1              ");
            digitalWrite(contact_moteur,LOW);
            digitalWrite(electro_vanne_1,LOW);
            etat_programme = PROGRAMME_SECURITE;
        }
        else {
            if (millis() - lancement_retour >= tempo_retour_automatique) {
            digitalWrite(contact_moteur,LOW);
            lcd.clear();
            etat_programme = PROGRAMME_EN_ATTENTE;
            }
        }
        break; 
    }
}


void reglages()
{
    switch (etat_reglages) {
        case REGLAGES_EN_ATTENTE:
            if (digitalRead(entree_menus) == LOW){
            delay (500);
            loop();
            }
            else {
            digitalWrite(contact_moteur,LOW);
            digitalWrite(electro_vanne_1,LOW);
            etat_reglages = MENU_TEMPORISATION;
            }
        break;

        case MENU_TEMPORISATION:
            lcd.setCursor(0, 0);
            lcd.print("TEMPORISATION   ");
            lcd.setCursor(0, 1);
            lcd.print("RETOUR AUTO     ");
            
            if (getPressedButton() == BUTTON_RIGHT) {
            lcd.clear();
            etat_reglages = REGLAGES_RETOUR;
            }
            if (getPressedButton() == BUTTON_DOWN) {
            lcd.clear();
            etat_reglages = MENU_MOD;
            }
            if (digitalRead(entree_menus) == LOW){
            lcd.clear();
            etat_reglages = REGLAGES_EN_ATTENTE;
            delay (200);
            }
        break;

        case REGLAGES_RETOUR:
            lcd.setCursor(0, 0);
            lcd.print("TEMPORISATION   ");
            lcd.setCursor(15, 1);
            lcd.print("S");
            lcd.setCursor(12, 1);
            lcd.print(tempo_retour_automatique/1000);

            if (getPressedButton() == BUTTON_UP) {
            delay (100);
            tempo_retour_automatique = tempo_retour_automatique + 1000;
            tempo_retour_automatique = constrain(tempo_retour_automatique,1000,30000);
            lcd.clear();
            etat_reglages = REGLAGES_RETOUR;
            }

            if (getPressedButton() == BUTTON_DOWN) {
            delay (100);
            tempo_retour_automatique = tempo_retour_automatique - 1000;
            tempo_retour_automatique = constrain(tempo_retour_automatique,1000,30000);
            lcd.clear();
            etat_reglages = REGLAGES_RETOUR;
            }  
    
            if (getPressedButton() == BUTTON_LEFT) {
            EEPROM.put(10,tempo_retour_automatique);
            lcd.clear();
            lcd.setCursor(0,0);
            lcd.print("    REGLAGES    ");
            lcd.setCursor(0,1);
            lcd.print("   ENREGISTRES  ");
            delay(1500);
            etat_reglages = MENU_TEMPORISATION;
            }
        
            if (digitalRead(entree_menus) == LOW){
            lcd.clear(); 
            etat_reglages = REGLAGES_EN_ATTENTE;
            }
        break;  


        case MENU_MOD:
            lcd.setCursor(0, 0);
            lcd.print("MODES DE        ");
            lcd.setCursor(0, 1);
            lcd.print("FONCTIONNEMENT  ");

            if (getPressedButton() == BUTTON_UP) {
            lcd.clear();
            etat_reglages = MENU_TEMPORISATION;
            }
            if (getPressedButton() == BUTTON_RIGHT) {
            lcd.clear();
            etat_reglages = REGLAGES_MOD;
            }
            if (digitalRead(entree_menus) == LOW){
            lcd.clear();
            etat_reglages = REGLAGES_EN_ATTENTE;
            delay (200);
            }
        break;

        case REGLAGES_MOD:
            lcd.setCursor(0, 0);
            lcd.print("MOD             ");
            lcd.setCursor(5, 1);
            lcd.print(modnumero);

            if (getPressedButton() == BUTTON_UP) {
            delay (200);
            modnumero = modnumero + 1;
            modnumero = constrain(modnumero,1,3);
            lcd.clear();
            etat_reglages = REGLAGES_MOD;
            }

            if (getPressedButton() == BUTTON_DOWN) {
            delay (200);
            modnumero = modnumero - 1;
            modnumero = constrain(modnumero,1,3);
            lcd.clear();
            etat_reglages = REGLAGES_MOD;
            }  
    
            if (getPressedButton() == BUTTON_LEFT) {
            EEPROM.put(30,modnumero);
            lcd.clear();
            lcd.setCursor(0,0);
            lcd.print("    REGLAGES    ");
            lcd.setCursor(0,1);
            lcd.print("   ENREGISTRES  ");
            delay(1500);
            etat_reglages = MENU_MOD;
            }
        
            if (digitalRead(entree_menus) == LOW){
            lcd.clear(); 
            etat_reglages = REGLAGES_EN_ATTENTE;
            }
        break;
    }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.