mesure durée de vérité d'une variable

j'ai tenté vainement un code pour réaliser un test de mesure de durée de vérité d'une variable.
A partir d'un bouton générant cette variable, elle est tantôt vraie, tantôt fausse.
Le but étant d'allumer une led ou activer une sortie si elle reste vraie au moins 2 secondes,.
Sinon, à chaque retour fausse, le timer repart pour 2 secondes à la vérité suivante.
je pense mon code incomplet côté changement de valeur de la variable.

unsigned long begin_timer;
unsigned long end_timer;
bool var = false;
bool var1 = true;

bool boucle = false;
int Btnpin = 6;
int Ledpin = 8;


void setup() {
  pinMode(Btnpin, INPUT_PULLUP);
  pinMode(Ledpin, OUTPUT);

}

void loop() {

  if ((digitalRead(3) == LOW)) {                          // bouton générant la variable
    var = true;
  } else {
    var = false;

    if (var = true) {
      begin_timer = millis();                                   // départ chrono
      var1 = false;                                             // marqueur de changement d'état 
      boucle = true;                                            // chrono en cours


      if (( var == false) && (boucle == true)) {
        end_timer = millis();
        var1 = true;                                           // changement détat du marqueur
        if (end_timer - begin_timer >= 2000) {
          digitalWrite(Ledpin, HIGH);

        }
      }
    }

  }
}

déjà tu as BtnPin=6 et tu fais un digitalRead(3) ...

C’est comme mesurer la durée d’appui d’un bouton -> éventuellement utilisez la librairie de @bricoleau il a un exemple exactement pour cela

Sinon si vous voulez coder c’est typiquement une définition de programme qui se prête bien à la programmation par machine à états (cf mon tuto)

houps! je n'avais pas vu qu'en adaptant mon test pour le forum, la pin bouton avait été modifiée.
Mais, il n'y a pas que ça qui ne va pas.
En essayant d'adapter le même principe que l'appui bouton, je bloque, il doit y avoir une subtilité.
Pourquoi pas, la librairie de Bricoleau , sauf qu' il me faille,je suppose, remplacer "bouton" par "variable" et supprimer la nomination pin.
La compilation m'indique alors " no matching fonction"
Je rappelle que dans mon exemple, le bouton est censé ne pas exister,il est juste présent pour générer la variable de test.
Certes, je ne doute pas de la machine à état, je souhaite tout juste comprendre et assimiler la démarche d' adapter le principe bouton à une variable, et rester proche d'un code appui bouton long basique.

vous dites

A partir d'un bouton générant cette variable

donc j'ai supposé que votre variable c'était juste la lecture de l'état HIGH ou LOW de la pin. Il y a équivalence entre valeur de la variable et état de la pin.

En essayant d'adapter le même principe que l'appui bouton, je bloque, il doit y avoir une subtilité.

la bibliothèque de bricoleau par défaut attend une pin en INPUT_PULLUP, c'est à dire que LOW c'est "broche activée" et HIGH c'est "broche au repos"

L'approche machine à état est super basique, on a deux états et on attend un front / changement de valeur pour passer de l'un à l'autre en mémorisant le moment de changement.

L'approche par les deux méthodes m'intéresse.
Concernant la librairie de Bricoleau, je n'ai pas d'impératif, la variable peut très bien être fausse pour activer le chrono, tout comme le bouton à l'état low. Ce n'est qu'un choix de déclaration de valeur initiale, que j'inverse.
Mais remplacer " bouton " par le nom de la variable ne suffit pas!
Étudier la machine à états ensuite, me paraîtra plus simple, si je saisi mieux comment différencier la nuance de code entre une variable et un bouton, qui sont différents et à ne pas confondre, comme par exemple avec " simple bouton, appui long".

voici un code d'exemple de la machine à état.

enum : byte {VRAI, FAUX} etatVariable = VRAI;

void verification(bool variable) {
  static unsigned long t0 = 0;

  switch (etatVariable) {
    case FAUX:  // on était FAUX, est-on passé à VRAI ?
      if (variable) {
        Serial.print(F("Changement état. Durée à Faux: "));
        Serial.print( millis() - t0);
        Serial.println(F(" ms"));
        
        etatVariable = VRAI;
        t0 = millis();
      }
      break;

    case VRAI: // on était VRAI, est-on passé à FAUX ?
      if (!variable) {
        Serial.print(F("Changement état. Durée à Vrai: "));
        Serial.print(millis() - t0);
        Serial.println(F(" ms"));
        
        etatVariable = FAUX;
        t0 = millis();
      }
      break;
  }
}

bool maVariable = true;
const byte pinBouton = 2;

void setup() {
  Serial.begin(115200);
  pinMode(pinBouton, INPUT_PULLUP);
  Serial.println(F("\nC'est parti !!!"));
}

void loop() {
  bool maVariable = (digitalRead(pinBouton) == HIGH); // le bouton est relâché -> vrai
  verification(maVariable);
}

ce code suit l'évolution de la variable logique (booléenne) "maVariable" en reportant pendant combien de temps elle a été vraie et combien de temps elle a été fausse.

Pour simplifier son évolution je l'ai associée à la pin2 qui pourrait être un bouton

il faut bien sûr appeler verification(maVariable);le plus souvent possible si on veut avoir un temps proche de la réalité.

Votre code fonctionne parfaitement, merci.
Si comme prévu dans mon scénario initial, je veuille allumer une led après 2 secondes où la variable est vraie, j'ai rajouté au code la condition de dépassement des 2 secondes pour obtenir cet effet.
Si ça fonctionne, il n'est pas immédiat, il faut que la vérité change de valeur pour l'obtenir.Si la vérité dure 5 secondes, ce sera après 5 secondes que la led s'allumera. L'intention étant que systématiquement dès que la variable est vraie durant au moins 2secondes et les dépasse, la led s'allume immédiatement.

enum : byte {VRAI, FAUX} etatVariable = VRAI;

void verification(bool variable) {
  static unsigned long t0 = 0;

  switch (etatVariable) {
    case FAUX:  // on était FAUX, est-on passé à VRAI ?
      if (variable) {
        Serial.print(F("Changement état. Durée à Faux: "));
        Serial.print( millis() - t0);
        Serial.println(F(" ms"));
       
        etatVariable = VRAI;
        t0 = millis();
      }
      break;

    case VRAI: // on était VRAI, est-on passé à FAUX ?
      if (!variable) {
        Serial.print(F("Changement état. Durée à Vrai: "));
        Serial.print(millis() - t0);
        Serial.println(F(" ms"));
        if(millis() - t0  >= 2000){
          digitalWrite(9,HIGH);
        }
       
        etatVariable = FAUX;
        t0 = millis();
      }
      break;
  }
}

bool maVariable = true;
const byte pinBouton = 2;

void setup() {
  pinMode(9,OUTPUT);
  Serial.begin(115200);
  pinMode(pinBouton, INPUT_PULLUP);
  Serial.println(F("\nC'est parti !!!"));
}

void loop() {
  bool maVariable = (digitalRead(pinBouton) ==  LOW ); // le bouton est relâché -> vrai
  verification(maVariable);
}

Vous rajoutez avec cette contrainte une flèche sur chaque état, un nouvel événement qui se produit: timeout. Il suffit de le coder dans les fonctions

 case VRAI: // on était VRAI, est-on passé à FAUX ?
      if (!variable) {
        Serial.print(F("Changement état. Durée à Vrai: "));
        Serial.print(millis() - t0);
        Serial.println(F(" ms"));
        if(millis() - t0  >= 2000){
          digitalWrite(9,HIGH);
        } else 
        if (millis() - t0 > 2000) {...allumer la led....} // codage du timeout

edit : n’importe quoi.... le code était déjà là !! :))

j'avais bien compris comme cela.

if(millis() - t0  >= 2000){
          digitalWrite(9,HIGH);

Dans votre dernier post, n'y -t-il pas 2 fois la même condition écrite de 2 façon différentes?
Sachant que la led est reliée à la pin 9.

 if(millis() - t0  >= 2000){
          digitalWrite(9,HIGH);
        } else 
        if (millis() - t0 > 2000) {...allumer la led....} // codage du timeout

Je n'obtiens malgré tout un allumage qu'au changement d'état, soit jusqu'à plusieurs secondes suivant durée de la variable.

Oui c’est ce qu’il se passe quand on poste à 5h30 du matin avant le café depuis son smartphone :slight_smile:

Je n’avais pas vu votre code - vous aviez trouvé la solution !

Vous êtes extrêmement matinal!!
Mais ma solution n'est pas idéale, puisque la led ne s'allume pas immédiatement les 2 secondes écoulées.
Elle ne s'allume que lors retour variable false, cela peut largement dépasser les 2 secondes.
Donc, il me manque un élément de code déclenchant l'allumage au moment précis du terme des 2 secondes.

ah oui donc ma solution avait quand même du sens, juste que je n'ai pas copié le bon code (le mien d'origine)

il ne faut pas mettre le test du temps expiré dans le if du changement de valeur sinon ce ne sera testé que dans ce cas là. C'est vraiment un évènement séparé à traiter tout le temps, donc un second if dans le case

il faut l'écrire comme cela

   case VRAI: // on était VRAI, est-on passé à FAUX ?
      if (!variable) {
        Serial.print(F("Changement état. Durée à Vrai: "));
        Serial.print(millis() - t0);
        Serial.println(F(" ms"));
        digitalWrite(9, LOW); // au cas où on l'avait allumée
        etatVariable = FAUX;
        t0 = millis();
      }
      else if (millis() - t0 > 2000) {
        digitalWrite(9,HIGH);
      }
      break;

Cette fois, la led s'allume bien à 2 secondes tapantes.
Merci J-M-L pour ce beau résultat et votre investissement.
Et avec l' adaptation à une variable de la librairie Bricoleau simple bouton dont vous évoquiez tout au début la possibilité, comment auriez-vous procédé, pour obtenir la même chose, afin de comparer les 2 méthodes.

Je ne vais pas tout faire :wink:

Dans la bibliothèque il y a un exemple qui montre comment capturer la durée d’appui. En gros si l’appui c’est l’état de votre variable, il n’y a rien à faire....

Sans doute, je cherche compliqué alors que c'est si simple. N'ayant pas l'esprit aussi logique que vous qui êtes rompu au développement informatique.
Et le plus logique étant de remplacer la pin par la variable, juste entre ( ), alors que je m'évertuai à remplacer bouton .
N'ayant plus de module Nano libre sous la main, je testerai sous quelques jours le code suivant complété des éléments nécessaires à générer la variable et son changement de valeur. En attendant, il compile bien. Ce qui n'est pas un gage de fonctionnement, loin de là.

#include "simpleBouton.h"
bool var = true;
simpleBouton bouton(var);

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

void loop()
{
  //Lecture de la durée d'appui AVANT d'actualiser
  uint32_t duree = bouton.dureeEnfonce();
 
  bouton.actualiser();
  
  if (bouton.vientDEtreEnfonce())
  {
	Serial.print("Bouton enfonce");
  }

  if (bouton.vientDEtreRelache())
  {
    Serial.print(" pendant ");
	Serial.print(duree);
	Serial.println(" ms");
  } 
}

L’idée d’utiliser la bibliothèque dépend uniquement du fait que votre variable représente l’état d’une pin et son évolution.

Si ce n’est pas le cas il ne faut pas utiliser la bibliothèque et prendre l’approche précédente.

Si c’est le cas il ne faut plus utiliser votre variable mais en lieu est place une variable de type bouton qui est conceptuellement comme votre ancienne variable : vous pouvez l’interroger sur son état (appuyé ou pas) mais en plus elle sait faire autre chose comme mesurer le temps depuis l’appui.

C’est l’intérêt de la programmation orientée objet, vous avez une boîte noire, pas la peine de savoir comment ça marche dedans (sauf si on est curieux) et ça vous rend des services de plus haut niveau

Impatient d'en savoir plus, j'ai mis en suspend un autre projet afin d'en libérer le carte nano.
j'ai téléversé le code suivant, et en déduis suite à l'essai, qu'il ne convient pas plus.
Remplacer la pin par la variable dans la déclaration, ne suffit ou ne convient pas!

#include "simpleBouton.h"
bool var = HIGH;
simpleBouton bouton(var);

void setup()
{
  Serial.begin(115200);
  pinMode(3,INPUT_PULLUP);
  pinMode(4,OUTPUT);
  pinMode(9,OUTPUT);
}

void loop()
{
  //Lecture de la durée d'appui AVANT d'actualiser
  uint32_t duree = bouton.dureeEnfonce();
 
  bouton.actualiser();

  if(digitalRead(3)==LOW){                 // bouton générant la variable
    digitalWrite(4,HIGH);                 // temoin changement d'état variable
    var= LOW;
  }else{
    var= HIGH;
    digitalWrite(4,LOW);
  }
  
  if (bouton.vientDEtreEnfonce())
  {
  Serial.print("Bouton enfonce");
  digitalWrite(9,HIGH);             //  led témoin que l'action a été prise en compte ( ne fonctionne pas)
  delay(500);
  digitalWrite(9,LOW);
  }

  if (bouton.vientDEtreRelache())
  {
    Serial.print(" pendant ");
  Serial.print(duree);
  Serial.println(" ms");
  }}

ou si j'interprète différemment votre dernier post, la bibliothèque simple bouton n'est envisageable que si un bouton existe réellement et que son état soit mémorisé dans une variable, une variable seule ne peut être traitée au travers de cette bibliothèque.

Non... une pin c'est une pin...

je repose la question: Est-ce que votre variable représente l'état d'une pin, oui ou non ?
si c'est non, Alors la bibliothèque SimpleBouton ne convient pas

Non, étant parti sur une interprétation fausse à priori dès le début du sujet:

C'est comme mesurer la durée d'appui d'un bouton -> éventuellement utilisez la librairie de @bricoleau il a un exemple exactement pour cela