Voici donc le code final :
// La librairie de gestion des boutons
#include <OneButton.h>
const byte buttonPin = 4; // notre bouton est sur la pin 4
OneButton button(buttonPin, true); // true pour le mettre en INPUT_PULLUP
// les pins utilisées pour les LEDs
const byte pinLedRouge = 8;
const byte pinLedOrange = 9;
const byte pinLedJaune = 10;
const byte pinLedVerte = 11;
// On introduit le temps comme évènement supplémentaire
unsigned long chrono; // attention, type unsigned long comme millis()
const unsigned long TimeOut = 15000ul; // 15 secondes (le ul à la fin pour unsigned long)
// la liste des états possible de notre système
// ainsi qu'une variable etatCourant prenant une de ces valeurs
enum {REPOS, ETAT_V, ETAT_VJ, ETAT_VJO, ETAT_VJOR} etatCourant;
// ------------------------------------------------------
// Cette fonction installe l'état initial
// ------------------------------------------------------
void mettreAuRepos()
{
digitalWrite(pinLedVerte, LOW);
digitalWrite(pinLedJaune, LOW);
digitalWrite(pinLedOrange, LOW);
digitalWrite(pinLedRouge, LOW);
etatCourant = REPOS;
}
// ------------------------------------------------------
// La fonction de call back, appellée automatiquement quand on clique
// ------------------------------------------------------
void simpleclick()
{
switch (etatCourant) {
case REPOS: // on était au repos et on a un appui, on allume la verte
digitalWrite(pinLedVerte, HIGH); // LED verte alimentée
etatCourant = ETAT_V; // on note le nouvel état de notre système
break;
case ETAT_V: // on était led verte allumée et on a un appui, on allume la jaune
digitalWrite(pinLedJaune, HIGH); // LED jaune alimentée
etatCourant = ETAT_VJ;// on note le nouvel état de notre système
break;
case ETAT_VJ: // vert et jaune allumées, on a un appui, on allume la orange
digitalWrite(pinLedOrange, HIGH); // LED orange alimentée
etatCourant = ETAT_VJO;// on note le nouvel état de notre système
break;
case ETAT_VJO:// vert, orange et jaune allumées, on a un appui, on allume la rouge
digitalWrite(pinLedRouge, HIGH); // LED rouge alimentée
etatCourant = ETAT_VJOR;// on note le nouvel état de notre système
break;
case ETAT_VJOR: // tout était allumé, on a un appui, on retourne au repos
mettreAuRepos(); // on retourne à l'état initial
break;
}
chrono = millis(); // on vient d'avoir une action donc on ré-arme notre chronomètre
}
// ------------------------------------------------------
// La fonction de call back, appellée automatiquement quand on double clique
// ------------------------------------------------------
void doubleclick()
{
switch (etatCourant) {
case REPOS: // dans tous les états
case ETAT_V: // sauf celui où tout était allumé
case ETAT_VJ: // en cas de double click on veut
case ETAT_VJO: // allumer toutes les LEDs
digitalWrite(pinLedVerte, HIGH);
digitalWrite(pinLedJaune, HIGH);
digitalWrite(pinLedOrange, HIGH);
digitalWrite(pinLedRouge, HIGH);
etatCourant = ETAT_VJOR; // et on déclare notre nouvel état courant
break;
case ETAT_VJOR: // on a tout qui est allumé et on reçoit le double click
mettreAuRepos(); // donc on retourne à l'état de repos
break;
}
chrono = millis(); // on vient d'avoir une action donc on ré-arme notre chronomètre
}
// ------------------------------------------------------
// La fonction de appellée en cas de dépassement du délai
// (on pourrait aussi faire un if (etatCourant != REPOS) mettreAuRepos(); )
// ------------------------------------------------------
void timeOut()
{
/* // version longue si on veut le switch case
switch (etatCourant) {
case ETAT_V: // pour tous les états
case ETAT_VO: // sauf celui au repos
case ETAT_VOJ: // on doit tout éteindre
case ETAT_VOJR: // et revenir à l'état initial
mettreAuRepos(); // ce que fait cette fonction
break;
}
*/
// version courte, si on n'est pas au repos, alors passer au repos
if (etatCourant != REPOS) mettreAuRepos();
// à noter que le timeOut continuera de se déclencher toutes les 15 secondes
// mais ne fera rien puisqu'on sera au repos
// ça peut être utile pour continuer à faire autre chose
// sinon il faut tester avant de l’appeler qu’on n’est pas au repos
}
// ------------------------------------------------------
// On initialise notre système dans le setup
// ------------------------------------------------------
void setup() {
pinMode (pinLedRouge, OUTPUT);
pinMode (pinLedOrange, OUTPUT);
pinMode (pinLedJaune, OUTPUT);
pinMode (pinLedVerte, OUTPUT);
//conditions Initiales
mettreAuRepos();
// On attache la fonction simpleClick() comme callBack en cas de simple click
button.attachClick(simpleclick);
// On attache la fonction doubleClick() comme callBack en cas de double click
button.attachDoubleClick(doubleclick);
}
void loop() {
// On vérifie l'état des boutons, ce qui déclenche l'appel d'une des fonctions callBack si nécessaire
button.tick();
// On vérifie le timer et on déclenche l'évènement si nécéssaire
// rajouter dans la condition “&& (etatCourant != REPOS)” si vous ne souhaitez pas
// appeler la fonction au repos
if (millis() - chrono >= TimeOut) {
timeOut();
chrono = millis(); // on ré-arme notre chronomètre
}
// ici on peut faire autre chose du moment que ça ne prend pas trop longtemps
}
Ce code correspond à l'ensemble du diagramme d'états
Qui bien que "compliqué" car il y a beaucoup de choses à gérer, n'est pas compliqué à programmer, même si on vous rajoute des transitions et des contraintes, car vous avez créé une structure de code saine et évolutive.
Cette technique s'applique à de nombreux cas, donc il est bon de la maîtriser
Bon codage à toutes et tous !
