Go Down

Topic: mesure durée de vérité d'une variable (Read 361 times) previous topic - next topic

peter52

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.

Code: [Select]
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);

        }
      }
    }

  }
}



biggil

déjà tu as BtnPin=6 et tu fais un digitalRead(3) ...
Aide toi, le compilateur t'aidera

J-M-L

#2
Jan 24, 2021, 08:49 am Last Edit: Jan 24, 2021, 08:50 am by J-M-L
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)
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

peter52

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.



J-M-L

vous dites
Quote
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.

Quote
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.


Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

peter52

#5
Jan 24, 2021, 05:06 pm Last Edit: Jan 24, 2021, 05:08 pm by peter52
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".

J-M-L

#6
Jan 24, 2021, 05:45 pm Last Edit: Jan 24, 2021, 05:46 pm by J-M-L
voici un code d'exemple de la machine à état.
Code: [Select]
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
Code: [Select]
verification(maVariable);le plus souvent possible si on veut avoir un temps proche de la réalité.
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

peter52

#7
Jan 24, 2021, 09:37 pm Last Edit: Jan 25, 2021, 01:52 am by peter52
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.

Code: [Select]
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);
}

J-M-L

#8
Jan 25, 2021, 05:26 am Last Edit: Jan 25, 2021, 10:18 am by J-M-L
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

Code: [Select]
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à !! :))
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

peter52

j'avais bien compris comme cela.
Code: [Select]
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.

Code: [Select]
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.

J-M-L

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

Je n'avais pas vu votre code - vous aviez trouvé la solution !
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

peter52

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.

J-M-L

#12
Jan 25, 2021, 11:57 am Last Edit: Jan 25, 2021, 12:01 pm by J-M-L
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
Code: [Select]
   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;



Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

peter52

#13
Jan 25, 2021, 05:14 pm Last Edit: Jan 25, 2021, 05:16 pm by peter52
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.

J-M-L

Je ne vais pas tout faire ;)

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....
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

Go Up