Temporiser une sortie

Ca marche, un grand merci je vais pouvoir avancer dans mon projet

Je vois que je me suis compliqué la vie, j'ai compris le principe et le fonctionnement mais il me manque parfois la connaissance du langage.
Et je n'avais pas trouvé d'exemple qui me convienne.
Je vais pouvoir transposer à mes autres entées.

Bon dimanche

re bonjour,

bool cle()
{
bool cle; // clé ici n'est initialisé à rien
cleMA = digitalRead(pincleMA); // OK lu la valeur de l'état de la pin HIGH ou LOW
if(cleMA == true); // vous comparez un HIGH ou LOW avec true... comme vous avez mis un ; après le if même si la condition est vraie, rien ne se passe
return cle; // vous retournez quoi vraiment ici puisque clé n'a pas été initialisée ?
}
en fait je me suis basé sur un exemple que j'ai trouvé sur le net pour construire cette fonction
Avec vos explications je comprends mes erreurs.

Merci

Pour vous mettre sur le bon chemin de la machine à état, voici par exemple (en utilisant ce que vous avez déjà fait) à quoi pourrait ressembler la structure du code correspondant à la machine à état décrite plus haut un peu modifiée car pas de bouton pour annuler (j'ai pas testé bien sûr j'ai tapé cela d'un coup)

const byte pincleMA = 2;          // entrée clé Marche/Arrêt système sur pin2
const byte pinCapteurChoc = 9;    // entrée capteur sur pin9
const byte pinsirene = 8;         // Sortie sirène sur pin8


const unsigned long delaiAlarmeSonore = 10000ul; // 10 secondes pour test, mettre à 5 minutes = 300000ul

// les 4 états possibles
enum : byte {initial, alarmeActive, AlarmeSonne, AlarmeSilence} etat;

// -----------------------------------------------------------------------------------------------
// Fonction Sirène
// -----------------------------------------------------------------------------------------------

void sireneOFF()
{
  digitalWrite (pinsirene, HIGH); // sirene OFF
}

void sireneON()
{
  digitalWrite (pinsirene, LOW); // sirene ON
}


// -----------------------------------------------------------------------------------------------
// Fonction mise en marche système (clé)
// -----------------------------------------------------------------------------------------------

bool cleActive()
{
  return (digitalRead(pincleMA) == LOW); // INPUT_PULLUP donc actif à LOW
}

// -----------------------------------------------------------------------------------------------
// Fonction test de choc (par exemple, à voir avec votre capteur)
// -----------------------------------------------------------------------------------------------

bool detectionChoc()
{
  return (digitalRead(pinCapteurChoc) == LOW); // INPUT_PULLUP donc actif à LOW
}

// -----------------------------------------------------------------------------------------------

void mettreSystemeAuRepos()
{
  sireneOFF();
  digitalWrite(LED_BUILTIN, HIGH);
  // autre chose à éteindre ??
  // ....
  // ....
}

void setup() {
  Serial.begin(115200);

  pinMode(pinsirene, OUTPUT);
  sireneOFF();

  pinMode(pincleMA, INPUT_PULLUP);

  pinMode(pinCapteurChoc, INPUT_PULLUP);


  pinMode(LED_BUILTIN, OUTPUT); // la led sur la carte arduino
  // suivant l'état de la clé on est soit à l'état initial, soit déjà activé
  if (cleActive()) {
    etat = alarmeActive;
    digitalWrite(LED_BUILTIN, HIGH); // on allume la lED pour dire sous alarme
  } else {
    etat = initial;
    mettreSystemeAuRepos();
  }
}

void loop() {
  static unsigned long chrono = 0; // pour mesure un timeout

  // ----------------------------
  // comme dans tous les états si on tourne la clé on arrête tout, on peut le tester séparément
  // pour éviter de dupliquer cela dans chaque état (les flèches noires du diagramme)
  // ----------------------------

  if ((etat != initial) && (!cleActive())) {
    etat = initial;
    mettreSystemeAuRepos();
  }

  // ----------------------------
  // les actions liées aux évènements dépendent de l'état dans lequel on est
  // ici on teste toutes les évènements (les flèches qui partent) d'un état
  // et si l'évènement se produit on effectue les actions qui vont bien
  // ----------------------------

  switch (etat) {

    // ----------------------------
    case initial: // le seul évènement c'est
      if ( cleActive()) { // flèche verte du diagramme, on était au repos,  l'utilisateur a tourné la clé
        etat = alarmeActive;
        digitalWrite(LED_BUILTIN, HIGH); // on allume la lED pour dire sous alarme
      }
      break;
    // ----------------------------
    case alarmeActive:      // ici on teste uniquement le choc
      if (detectionChoc()) {
        // que faut-il faire comme actions ?
        // .....
        // .....
        // .....

        chrono = millis(); // on mémorise l'heure de début de l'alarme
        etat = AlarmeSonne; // on change d'état
      }

      break;
    // ----------------------------
    case AlarmeSonne:
      if (millis() - chrono >= delaiAlarmeSonore) { // le délai est il terminé?
        // si OUI que doit-on faire ?
        // ....
        // ....
        // ....
        etat = AlarmeSilence; // on change d'état
      }
      break;
    // ----------------------------
    case AlarmeSilence:
      // Que doit-on faire ici ? (quelles sont les flèches partant de cet état, les a-t-on déjà traitées) ?
      break;
  }

  // ici on pourrait faire autre chose, par exemple clignoter la LED


}

Bonjour J-M-L
Merci pour l'orientation.

De mon coté j'ai avancé un peu, sans avoir encore eu le temps de décortiquer votre code, j'ai vu quelque similitude avec ce que j'ai fait (surtout au niveau de void loop).

Je me suis focalisé pour l'instant à créer mes fonctions comme vous me l'aviez conseillé, j'ai fait un premier programme sans machine à état. je l'ai rentré dans mon Arduino et testé.
J'ai dû permuter quelques états HAUT/BAS de mes boutons pour avoir le comportement que je souhaitais.

// Alarme cabanon
const byte pincleMA = 2;      // entrée clé Marche/Arrêt système sur pin2
const byte pinILS_NO = 3;     // entrée ILS contact Normalement ouvert (NO) sur pin3
const byte pinILS_NF = 4;     // entrée ILS contact Normalement fermé (NF) sur pin4
const byte pinsirene = 8;     // Sortie sirène sur pin8
const byte pingyrophare = 9;  // Sortie gyrophare sur pin9
const byte pintemoin = 10;    // Sortie témoin état système sur pin10

// -----------------------------------------------------------------------------------------------  
// Fonction Sirène
// -----------------------------------------------------------------------------------------------
void sireneON()
{
    digitalWrite (pinsirene, HIGH); // sirene OFF
}

void sireneOFF()
{
    digitalWrite (pinsirene, LOW); // sirene ON
}
// -----------------------------------------------------------------------------------------------
// Fonction gyrophare
// -----------------------------------------------------------------------------------------------
void gyrophareOFF()
{
    digitalWrite (pingyrophare, LOW); // gyrophare OFF
}

void gyrophareON()
{
    digitalWrite (pingyrophare, HIGH); // gyrophare ON
} 
// -----------------------------------------------------------------------------------------------    
// Fonction Témoin état système (Marche ou Arrêt)
// -----------------------------------------------------------------------------------------------
void temoinOFF()
{
    digitalWrite (pintemoin, LOW); // témoin alarme déclenchée OFF
}

void temoinON()
{
    digitalWrite (pintemoin, HIGH); // témoin alarme déclenchée ON 
}    
// -----------------------------------------------------------------------------------------------  
// Fonction mise en marche système (clé active)
// ----------------------------------------------------------------------------------------------- 
bool cleActive()
{
  return (digitalRead(pincleMA) == LOW);
}
// -----------------------------------------------------------------------------------------------  
// Fonction détection choc ILS_NO
// ----------------------------------------------------------------------------------------------- 
bool ILS_NO_Actif()
{
  return (digitalRead(pinILS_NO) == HIGH);
}
// -----------------------------------------------------------------------------------------------  
// Fonction détection choc ILS_NF
// ----------------------------------------------------------------------------------------------- 
bool ILS_NF_Actif()
{
  return (digitalRead(pinILS_NF) == LOW);
}

// la liste des états possible de notre système
// ainsi qu'une variable etat prenant une de ces valeurs
//enum {sireneOFF, sireneON,} etatsirene;           // 2 possibilités pour etatsiene: sireneOFF ou sireneON
//enum {gyrophareOFF, gyrophareON,} etatgyrophare;  // 2 possibilités pour etatgyrophare: gyrophareOFF ou gyrophareON
//enum {temoinOFF, temoinON,} etattemoin;           // 2 possibilités pour temoin: temoinOFF ou temoinON

// -----------------------------------------------------------------------------------------------  
// Cette fonction installe l'état initial
// -----------------------------------------------------------------------------------------------  
void mettreAuRepos()
{
  digitalWrite (pinsirene, LOW);    // sirene OFF
  digitalWrite (pingyrophare, LOW); // gyrophare OFF
  digitalWrite (pintemoin, LOW);    // témoin alarme déclenchée OFF
}
// -----------------------------------------------------------------------------------------------  
// Cette fonction Alarme déclenchée
// -----------------------------------------------------------------------------------------------  
void AlarmeDeclenche()
{
  digitalWrite (pinsirene, HIGH);    // sirene OFF
  digitalWrite (pingyrophare, HIGH); // gyrophare OFF
  digitalWrite (pintemoin, HIGH);    // témoin alarme déclenchée OFF
}
  
void setup() {
  pinMode(pincleMA,INPUT_PULLUP);  // entrée contact NF mise en marche alarme
  pinMode(pinILS_NO,INPUT_PULLUP);    // entrée contact NO détecteur choc
  pinMode(pinILS_NF,INPUT_PULLUP);    // entrée contact NF détecteur choc
  pinMode(pinsirene,OUTPUT);          // sortie relais sirène
  pinMode(pingyrophare,OUTPUT);       // sortie relais témoin alarme déclenchée
  pinMode(pintemoin,OUTPUT);          // sortie relais témoin état système
  
  //conditions Initiales
  mettreAuRepos();
  }

void loop() {
 if (cleActive())
  {
   temoinON();
  } else {
   mettreAuRepos();}
   
  if ((cleActive()) && (ILS_NF_Actif() || ILS_NO_Actif()))
  {  
   AlarmeDeclenche();
   //sireneON();  
   //gyrophareON();
  } else {
   mettreAuRepos();}

Bien évidement ce programme n'est pas complet (pas de timeout de l'alarme) et n'utilise pas de machine à état
Je vais décortiquer votre code.
Je vais m'absenter quelques jours pour le travail et donc pas pouvoir avancer; mais je ne lâche pas le morceau !!!
Merci

pas d'urgence - si vous avez des soucis n'hésitez pas à reposter - je vois que ça rentre!

j'ai un bon prof :slight_smile:

Bonjour J-M-L.
Après 4 jours d'absences, me voici de retour.

Un grand merci pour votre code, il m'a permis de comprendre qu'il ne fallait pas essayer de construire la machine à état par entrée mais de façon globale, que les "cases" correspondent à un état du système et non comme je l'avais compris à une état d'une ou plusieurs entrées.

J'ai passé une bonne partie de ma soirée à faire le programme de la machine à état qui correspond à mon système.
Je vous le soumet:

// Alarme cabanon
const byte pincleMA = 2;      // entrée clé Marche/Arrêt système sur pin2
const byte pinILS_NO = 3;     // entrée ILS contact Normalement ouvert (NO) sur pin3
const byte pinILS_NF = 4;     // entrée ILS contact Normalement fermé (NF) sur pin4
const byte pinsirene = 8;     // Sortie sirène sur pin8
const byte pingyrophare = 9;  // Sortie gyrophare sur pin9
const byte pintemoin = 10;    // Sortie témoin état système sur pin10
const unsigned long delaiAlarmeSonore = 10000ul;  // Délais pendant lequel l'alarme sonne
// 4 états possibles du système
enum : byte {initial, AlarmeActive, AlarmeSonne, AlarmeSilence} etat;


// -----------------------------------------------------------------------------------------------  
// Fonction Sirène
// -----------------------------------------------------------------------------------------------
void sireneON()
{
    digitalWrite (pinsirene, HIGH); // sirene OFF
}

void sireneOFF()
{
    digitalWrite (pinsirene, LOW); // sirene ON
}
// -----------------------------------------------------------------------------------------------
// Fonction gyrophare
// -----------------------------------------------------------------------------------------------
void gyrophareOFF()
{
    digitalWrite (pingyrophare, LOW); // gyrophare OFF
}

void gyrophareON()
{
    digitalWrite (pingyrophare, HIGH); // gyrophare ON
} 
// -----------------------------------------------------------------------------------------------    
// Fonction Témoin état système (Marche ou Arrêt)
// -----------------------------------------------------------------------------------------------
void temoinOFF()
{
    digitalWrite (pintemoin, LOW); // témoin alarme déclenchée OFF
}

void temoinON()
{
    digitalWrite (pintemoin, HIGH); // témoin alarme déclenchée ON 
}    
// -----------------------------------------------------------------------------------------------  
// Fonction mise en marche système (clé active)
// ----------------------------------------------------------------------------------------------- 
bool cleON()
{
  return (digitalRead(pincleMA) == LOW);
}
// -----------------------------------------------------------------------------------------------  
// Fonction arrêt système (clé désactivé)
// ----------------------------------------------------------------------------------------------- 
bool cleOFF()
{
  return (digitalRead(pincleMA) == HIGH);
}
// -----------------------------------------------------------------------------------------------  
// Fonction détection choc ILS_NO
// ----------------------------------------------------------------------------------------------- 
bool ILS_NO_Actif()
{
  return (digitalRead(pinILS_NO) == HIGH);
}
// -----------------------------------------------------------------------------------------------  
// Fonction détection choc ILS_NF
// ----------------------------------------------------------------------------------------------- 
bool ILS_NF_Actif()
{
  return (digitalRead(pinILS_NF) == LOW);
}
// -----------------------------------------------------------------------------------------------  
// Cette fonction installe l'état initial
// -----------------------------------------------------------------------------------------------  
void mettreAuRepos()
{
  digitalWrite (pinsirene, LOW);    // sirene OFF
  digitalWrite (pingyrophare, LOW); // gyrophare OFF
  digitalWrite (pintemoin, LOW);    // témoin alarme déclenchée OFF
  etat = initial;
}
// -----------------------------------------------------------------------------------------------  
// Cette fonction Alarme déclenchée
// -----------------------------------------------------------------------------------------------  
void AlarmeDeclenche()
{
  digitalWrite (pinsirene, HIGH);    // sirene OFF
  digitalWrite (pingyrophare, HIGH); // gyrophare OFF
  digitalWrite (pintemoin, HIGH);    // témoin alarme déclenchée OFF
}
  
void setup() {
  pinMode(pincleMA,INPUT_PULLUP);  // entrée contact NF mise en marche alarme
  pinMode(pinILS_NO,INPUT_PULLUP);    // entrée contact NO détecteur choc
  pinMode(pinILS_NF,INPUT_PULLUP);    // entrée contact NF détecteur choc
  pinMode(pinsirene,OUTPUT);          // sortie relais sirène
  pinMode(pingyrophare,OUTPUT);       // sortie relais témoin alarme déclenchée
  pinMode(pintemoin,OUTPUT);          // sortie relais témoin état système
  Serial.begin(9600);
  //conditions Initiales
  mettreAuRepos();
  }

void loop() {
static unsigned long chrono = 0; //pour mesurer un timout on déclare une variable chrono
//----------------------------------------------------------------------------------------
// Dans tous les états, si on tourne la clé OFF, on arrêt tout. 
  if ((etat != initial) && (cleOFF)) {  // si on n'est pas à l'état initial ET que la clé est à Off
  etat = initial;                       //on passe à l'état initial
  mettreAuRepos();                      // on active la fonction mettreAuRepos qui coupe tout
}
//----------------------------------------------------------------------------------------
// on teste les évènements d'un état et si l'évènement se produit on effectue les actions
switch (etat) {
  //-------------------------------------
  case initial:
  if (cleON()) {            //si la clé est sur ON
    temoinON();             // on lance les focntions
    gyrophareOFF();
    sireneOFF();
    etat = AlarmeActive;    // on passe à l'état sur alarmeActive
    Serial.println(etat);
  }
  break;
 //-------------------------------------
  case AlarmeActive:
  if (ILS_NF_Actif() || ILS_NO_Actif()) {  // test des ILS NO et NF
    temoinON();
    gyrophareON();
    sireneON();
    chrono = millis();                    //on mémorise l'heure de début de l'alarme
    etat = AlarmeSonne;
    Serial.println(etat);
  }
  break;
  //-------------------------------------
  case AlarmeSonne:
  if (millis() - chrono >= delaiAlarmeSonore) {  //si le delais est terminé
    sireneOFF();
    gyrophareON();
    temoinON();
   etat = AlarmeSilence;
   Serial.println(etat);
  }
  break;
  //-------------------------------------
  case AlarmeSilence:
  if (cleOFF()) {
     mettreAuRepos();
     etat = initial;
     Serial.println(etat);
  }
  break;
 }  
}

J'ai téléversé ce code dans mon arduino, pas d'erreur de compilation mais il reste bloqué à la case initial
J'ai ajouté à chaque étape un retour "Serial.println(etat)" pour voir ou on se situe dans le code (comme expliqué dans votre tuto).
Quand j'active la clé (cleON()) le moniteur affiche 1, quand cleOFF, arrêt du défilement dans le moniteur.
Quand je suis en case initial et que j'active l'un de mes ILS, il ne passe pas en case2 (AlarmeSonne).
J'ai élagué ce code pour le limiter aux 2 états du début (initial et alarmesonne), je n'ai garder que la clé et 1 ILS pour tester... Idem, pas de passage en case2.
Auriez vous une idée?
Voyez-vous une erreur dans mon code?
Avec mes remerciements

pour faire un appel de fonction il ne faut pas oublier les parentheses...

  if ((etat != initial) && ([color=red]cleOFF[/color])) {  // si on n'est pas à l'état initial ET que la clé est à Off

il faut changer [color=red]cleOFF[/color] en cleOFF[b][color=green]()[/color][/b]

Puréeeeee, c'était sous mes yeux!!!
C'était évident que le problème venait de la condition pour changer de case mais comme j'ai fait un copier/coller de mon code pour tester le code allégé, c'est passé à la trappe!!!
Je suis dessus depuis hier soir! Erreur de débutant :confused:
Merci, je corrige et teste

Ca maaaaaaaaaaaarrrrche !!!!!!! :slight_smile: :slight_smile: :slight_smile: :slight_smile: :slight_smile: :slight_smile: :slight_smile: :slight_smile:

C'est vraiment géniale cette "machine à états"... une fois que l'on a compris le principe bien sûr!

Il ne me reste plus qu'a mettre tout ça en œuvre.
Je vois déjà des possibilités d'évolutions ( LED d'état, écran lcd)...

Un grand, grand, grand merci à vous J-M-L , qui m'avez orienté, guidé, conseillé, aidé...
Commencer par créer les fonctions était une excellente idée.
Vous êtes très pédagogue.
J'espère vous recroiser dans mes prochains postes, il y en auras d'autres j'en suis sûr.
:slight_smile:

Bravo à vous !!! Oui tout un monde de possibilité et maintenant vous avez une structure de code saine donc rajouter des capteurs / afficheurs et des transitions peut se faire sans trop de difficultés!

Bons bidouillages!

Ps: maintenant que vous avez bien compris, vous pouvez optimiser un peu le code, par exemple quand vous passez de AlarmeSonne à AlarmeSilence pas la peine de faire autre chose que sireneOFF() puisque les autres éléments (gyrophare et voyant) sont déjà déclenchés