Amélioration d'une gestion de boutons

Bonjour a tous,
Projet en cours de developpement sous Uno, carte finale Nano.
Mon projet a 2 boutons et 3 LED. en temps normal, ces bouton ont une fonction geree par la loop. Une fonction settings permet d'enregistrer les parametres dans la carte afin de modifier son fonctionnement normal. ces parametres peuvent etre modifie en entrant a nouveau dans le settings par maintient d'un des deux boutons lors de la mise sous tension.
je developpe actuellement uniquement cette fonction de Settings.
Une fois dans la fonction Settings, un des boutons permet de selectionner la page. la page est visualisee avec le clignotement d'une des LED par cycle repetitifs. Le second bouton permet de modifier la valeur de la page.
par la suite, un enregistrement des valeurs sera effectuee en fin de settings. (pas encore ecrit).
J'ai fait ce code et il fonctionne plus ou moins comme je le souhaite, sauf que je le trouve mal ecrit et donc difficile a maintenir.
J'ai cherche a eviter toute fonction delay() supperieure a 50 ms pour que l'appuie sur les bouttons soient correctement gere.
Je souhaiterai obtenir de l'aide pour soit pouvoir trouver un code mieux ecrit et qui reponde a ce que j'attends, soit modifier ce code pour qu'il soit plus fluide.
Merci pour votre aide. Voici le code, les commentaires sont en Anglais pour le cas ou je post la meme question sur un forum international.
rien de complique mais, si vous avez des questions...

#include <EEPROM.h>
#define BTW 2
#define BTF 3
#define Lre1 8
#define Lre2 9
#define Lgr1 10
#define Lgr2 11
#define Lgr3 12
#define Lre3 13
#define EAdr1 1
#define EAdr2 2
#define EArd3 3
#define EAdr4 4
#define EAdr5 5
#define EAdr6 6
int page = 1; 
int maxPage = 6;
void Settings();
void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
pinMode(BTW, INPUT);
pinMode(BTF,INPUT);
pinMode(Lgr1,OUTPUT);
digitalWrite(Lgr1,HIGH);
pinMode(Lgr2,OUTPUT);
digitalWrite(Lgr2,HIGH);
pinMode(Lgr3,OUTPUT);
digitalWrite(Lgr3,HIGH);
pinMode(Lre1,OUTPUT);
digitalWrite(Lre1,HIGH);
pinMode(Lre2,OUTPUT);
digitalWrite(Lre2,HIGH);
pinMode(Lre3,OUTPUT);
digitalWrite(Lre3,HIGH);
/*
digitalWrite(Lgr1,LOW);
Pze();
digitalWrite(Lgr1,HIGH);
digitalWrite(Lgr2,LOW);
Pze();
digitalWrite(Lgr2,HIGH);
digitalWrite(Lgr3,LOW);
Pze();
digitalWrite(Lgr3,HIGH);
digitalWrite(Lre1,LOW);
Pze();
digitalWrite(Lre1,HIGH);
digitalWrite(Lre2,LOW);
Pze();
digitalWrite(Lre2,HIGH);
digitalWrite(Lre3,LOW);
Pze();
digitalWrite(Lre3,HIGH);
*/
if(digitalRead(BTF)==HIGH){
  while(digitalRead(BTF)==HIGH){
    delay(50);
  }
  Settings();
}
Settings(); // a retirer en production
}
void Pze(){
  delay(1000);
}
void loop() {
  if(digitalRead(BTW)==HIGH){
    //delay(50);
    while(digitalRead(BTW)==HIGH){
      delay(50);
    }
    digitalWrite(Lgr1,!digitalRead(Lgr1));
  }
    if(digitalRead(BTF)==HIGH){
      //delay(500);
      while(digitalRead(BTF)==HIGH){
        delay(50);
      }
    digitalWrite(Lgr2,!digitalRead(Lgr2));
  }
}

void Settings() {
  int n = 0;
  int b = 0;
  long delay1 = 30000;
  long d1 = 30000;
  long delay2 = 20000;
  long d2 = 20000;
  long delayP = 60000;
  long dP = 60000;
  int optCount = 1;
  bool P = false;
  bool led3State = false;
  bool pauseState = false;
  int maxPageValue =8;
  int actPage =1;
  while (true) {
    while (n < page or b < optCount ) {
      if (!P) {
        if (d1 == delay1 and n < page) { // in this case the page light is ON
          digitalWrite(Lre3, LOW);
          d2 = delay2;
        }
        if (d1 == delay1 and b < optCount){
          digitalWrite(Lre1,LOW); //this will start the second light
        }
        if (d2 == delay2) {
          d1--;
        } else if (d1 == delay1) {
          d2--;
        }
        if (d1 < 1) {
          d2--;
          digitalWrite(Lre3, HIGH); //put the page light off
          digitalWrite(Lre1,HIGH);
        }
        if (d2 < 1) {
          d1 = delay1;
          d2 = delay2;
          n++;
          b++;
        }
      }

      if (digitalRead(BTF) == HIGH) {// change page
        while (digitalRead(BTF) == HIGH) {
          delay(50);
        }
        n = page; //define a new page
        page++;//increase page number
        P = false;//stop waiting timebetween cycle
        dP = delayP;//reset the counter for the pause between cycles
        optCount = 1;//reset the value of the page
        b=1;//reset du compteur
        if (page > maxPage) {// if last page, quit
          break;
        }
      }
      if (digitalRead(BTW) == HIGH) {
        while (digitalRead(BTW) == HIGH) {
          delay(50);
        }
        optCount++;//increase the value of the option for this page
        if (optCount > maxPageValue) { //if we arrive at themaximum function for this page ( var to be modified as table matching max var for each page)
          optCount = 1;
        }
        n = page;
        P=false;
        dP=delayP;
      }
      if (P) { //get out if the blinking of the page is in pause (between 2 cycles of blinking, the off moment is longer)
        break;
      }
    }

    n = 0;
    b = 0;

    if (page <= maxPage) {
      if (!P) {
        P = true;
        n = 0;
      }
      dP--;

      if (dP < 1) {
        P = false;
        d1 = delay1;
        d2 = delay2;
        dP = delayP;
      }
    }
    if (page > maxPage) {
      digitalWrite(Lre3, HIGH);
      digitalWrite(Lre1, HIGH);
      break;
    }
  }
}

Merci d'avoir pri le temps de le lire.

Je me reponds a moi meme, il y a probablement une facon beaucoup plus simple de gerer cela avec des INT sur pin 2 et 3. semble etre possible sur Nano et Uno.
Je vais parallelement essayer ca.

Pour simplifier votre gestion des boutons, utilisez une bibliothèque comme Button dans easyRun ou OneButton ou encore Toggle

Une approche par la programmation par machine à états (cf mon tuto éventuellement) améliorerait grandement la lisibilité du code

les interruptions vont juste vous compliquer la vie

une spécification plus claire de ce que fait la fonction Settings serait aussi utile (c'est quoi une page et une valeur de page ?)

1 Like

Merci JML, effectivement, je viens de passer 2 heures sur les interruptions et ce, cela fonctionne, mais de facon alleatoire, le gestion des antirebons hard ou soft ne change rien. Je vais rester sur mon code initiale et explorer vos suggestions concernant la prog machine a etats.
Merci pour vote aide.
Amicalement,

Bonjour @michel-eesr
Si, comme la conseillé @J-M-L , vous décidez d'utiliser la librairie OneButton pour faire une machine à état, et que vous avez besoin d'un tuto d'utilisation en français :

Cordialement
Pandaroux007

1 Like

Merci Pandaroux, effectivement, un bouton, meme correctement gere par du hard (resistance de charge et capa), cela reste un element mecanique et, suivant sa qualite, son age et son degre d'utilisation, fini tres souvent par amener des problemes d'utilisation, il est donc important de le gerer correctement.
Je vais regarder ce tuto et, si possible (en fonction de la memoire requise por la LIB...) integrer cela dans mon code. Merci pour l'info.
Amicalement.

N’oubliez pas que la fonction tick() est à appeler souvent donc il ne faut pas que le code comporte de delay() significatifs sinon la gestion des boutons ne fonctionne plus. C’est pour cela qu’une approche par machine à états est souvent adaptée

Merci Pandaroux, Merci JML.
J'ai integre la bibliotheque OneButton a mon projet et, non seulement cela fonctionne parfaitement mais surtout j'ai apris plein de trucs.
Merci a vous deux.
Je marque en resolu.
Amicalement

Super !

Toujours curieux sur cette histoire de page :slight_smile:

Bonjour @michel-eesr

Je viens de corriger le titre pour qu'il reflète mieux le contenu du fil de discussion :wink:
Le moteur de recherche devrait ainsi le faire ressortir.

1 Like

l'idee est de programmer le mode de fonctionnement d'une carte

Si c'est une question, le code est en developpement, l'idee est d'avoir 2 boutons qui commandent des cycles de fonctionnement d'un moteur, d'une pompe et d'une electrovanne (optionelle), il y a aussi 2 capteurs egalement optionnels.
Le setting a des valeurs par defaut. il est modifiable par appuie sur un des bouton lors de la mise sous tension ou au reset. ce setting contient 7 pages et est sauvegarde en EEprom en fin de setting.
chaque page contient differente options (entre 3 et 8) definie dans un tableau (partie en cours de developpement).
lors du setting, on defini les differents choix et temps de fonctionnement.
La page en cours est visualisee par le clignotement d'une des diodes,
La valeur de cette page est visualisee par le clignotement de l'autre diode.
on augmente la page ou la valeur suivant le bouton sur lequel on appuie.
si tu veux, je fini ma modif en cours et je poste le code mais je n'imagine meme pas pouvoir te surprendre et encore moins t'apprendre quelque chose, toutefois, tes conseils sont toujours judicieux et tes remarques pertinentes donc, si tu veux prendre quelques instant pour regarder ma machine a gaz, je posterai le code en ligne avec plaisir.
Merci a toi.
Amicalement.

bonjour c'était bien une question sans point d'interrogation :slight_smile:

merci - c'était juste de la curiosité de ma part sur l'objectif final et comprendre ce que vous appeliez une page.

(l'usage de tableaux et de structure pour la sauvegarde en EEPROM vous simplifiera la vie)

pas de souci pour jeter un oeil si vous postez le code, ou mieux faites un wokwi

je ne connaissai pas Wokwi, c'est genial.

le bouton noir selectionne les pages, l'autre les valeurs.
Je sais que cela peut etre ameliore mais mon niveau est encore insuffisant pour ca. Merci pour tes conseils.

PS: il y a un fonctionnement curieux niveau clignotement juste apres l'appuie sur le bouton noir (valeur de la page). au cycle suivant, ca se passe bien au niveau affichage. j'ai du mal a trouver une solution.

Bon dimanche. Amicalement,
Michel

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