Explication du code

bonjour

je suis a la recherche d explication du code pour le capteur de debit YF-B2

j y ai passé du temps à travers les differents sites qui traitent arduino

volatile int flow_frequency; // Measures flow sensor pulsesunsigned 

int l_hour; // Calculated litres/hour
unsigned char flowsensor = 2; // Sensor Input
unsigned long currentTime;
unsigned long cloopTime;

void flow () // Interrupt function

{
   flow_frequency++;
}

   void setup()
 {
   pinMode(flowsensor, INPUT);
   digitalWrite(flowsensor, HIGH); // Optional Internal Pull-Up
   Serial.begin(9600);
   attachInterrupt(0, flow, RISING); // Setup Interrupt
   sei(); // Enable interrupts
   currentTime = millis();
   cloopTime = currentTime;
}

   void loop ()
{
   currentTime = millis();
   // Every second, calculate and print litres/hour
   if(currentTime >= (cloopTime + 1000))
   {
      cloopTime = currentTime; // Updates cloopTime
      // Pulse frequency (Hz) = 7.5Q, Q is flow rate in L/min.
      l_hour = (flow_frequency * 60 / 7.5); // (Pulse frequency x 60 min) / 7.5Q = flowrate in L/hour
      flow_frequency = 0; // Reset Counter
      Serial.print(l_hour, DEC); // Print litres/hour
      Serial.println(" L/hour");
   }
}

j aimerai savoir à quoi servent les 2 variables currentTime et cloopTime
et pourquoi il y est affirme :

saisissez ou collez du code ici

currentTime = millis();
cloopTime = currentTime;

je vous remercie pour votre attention et le temps que je passerai a y repondre
cdt

:warning:
Post mis dans la mauvaise section, on parle anglais dans les forums généraux. déplacé vers le forum francophone.

Merci de prendre en compte les recommandations listées dans Les bonnes pratiques du Forum Francophone

Salut!
Alors pour les variables,

  • currentTime stocke le temps écoulé depuis le démarrage du programme en millisecondes. Elle est mise à jour à chaque itération de la loop avec millis().
  • et la variable cloopTime sert de point de référence pour mesurer des intervalles de temps d'une seconde. Elle est mise à jour chaque fois qu'une seconde s'est écoulée.

Dans le code currentTime = millis(); et cloopTime = currentTime; initialise les deux variables avec le même temps de départ. C'est équivalent à

currentTime = cloopTime = millis();

Ensuite, currentTime sera mis à jour à chaque loop, alors que cloopTime ne sera mis à jour que toutes les secondes.


Ton code n'étant pas très lisible, je l'ai refais à ma façon, dis moi si c'est plus clair pour toi ?

#define PIN_CAPTEUR_DEBIT 2
#define IMPULSIONS_PAR_LITRE 450.0 // 7,5 impulsions/seconde = 1 L/min, donc en une minute : 7,5 * 60 = 450 impulsions pour 1L.
volatile unsigned long compteurImpulsions = 0;

#define INTERVALLE_AFFICHAGE 1000 // 1 seconde
unsigned long dernierAffichage = 0;

void compterImpulsion()
{
  compteurImpulsions++; // on incrémente le compteur d'impulsion avec ++ (donc +1)
}

void setup()
{
  Serial.begin(115200);
  pinMode(PIN_CAPTEUR_DEBIT, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(PIN_CAPTEUR_DEBIT), compterImpulsion, RISING);
  sei(); // on active les interruptions globalement
}

void loop()
{
  if ((millis() - dernierAffichage) >= INTERVALLE_AFFICHAGE) // à chaque seconde
  {
    // on récupère le nombre d'impulsion et on met le conteur d'impulsion à 0
    noInterrupts();
    unsigned long impulsions = compteurImpulsions;
    compteurImpulsions = 0;
    interrupts();
    // on calcule le débit (pas besoin de variable intermédiaire !)
    float debit = (impulsions * 60.0) / IMPULSIONS_PAR_LITRE; // L/heure
    // on affiche le débit en litre par heure
    Serial.print(debit, 2);
    Serial.println(" L/heure");
    // on affecte la valeur du temps courant à la valeur du temps précédent, pour savoir quand 1 seconde se sera écoulée
    dernierAffichage = millis();
  }
}

Tapé ici, non testé
En gros, on utilise une interruption matérielle pour compter le nombre d'impulsion (avec RISING c'est un front montant - donc quand on passe de 0 à 1 sur la pin) - pour en savoir plus sur les interruptions, un bon article :
https://www.locoduino.org/spip.php?article64

Le capteur YF-B2 envoie des impulsions électriques à chaque passage d'une certaine quantité d'eau. Ces impulsions sont comptées par la fonction d'interruption compterImpulsion(), qui incrémente un compteur.

Toutes les secondes, de manière non bloquante, on regarde le nombre d'impulsions, on remet à 0 le compteur, on calcule de débit, et on l'affiche sur le moniteur série (réglé à 115200 bauds/s, 9600 étant un peu trop lent :wink:). Enfin, on affecte le temps courant à la variable dernierAffichage, pour pouvoir savoir quand 1 seconde se sera écoulé ensuite (pour en savoir plus sur l'utilisation de millis, regarde l'exemple suivant).

Après n'ayant jamais utilisé ce capteur je te dis peut-être n'importe quoi autant sur le code que sur les variables, mais il me semble que c'est ça.

En espérant t'avoir aidé,
Cordialement
Pandaroux007

1 Like

En toute rigueur, il faudrait placer cette ligne juste après interrupts()

bonjour,

merci pour vos retours qui m ont eclairé; je vous ai pas remercie plus vite car j essais de progresser seul et d eviter trop de questions.

j ai un projet dans lequel la fonction millis aura du sens
du coup je recherche beaucoup de chose sur cette fonction
il y a un quelque chose que je n arrive pas à saisir dans cette fonction
voici un code :


unsigned long timer;
boolean ledState = 0;

void setup() {
   pinMode(13, OUTPUT);
   Serial.begin(9600);
   timer = millis();
}
 
void loop() {
   if (millis() - timer > 1000) {
      ledState=!ledState; // changer l'état de la LED
      digitalWrite(13, ledState);
      timer = millis();
   }

   Serial.print("Time: ");
   Serial.println(timer);
}

mon souci se trouve dans la creation de la variable qui dans cet exemple est unsigned long timer;
dans le code il est ecrit unsigned long timer=millis , or pour moi millis est le decompte du temps depuis la mise en route du programme
donc cela implique pour moi unsigned long timer= millis = duree du programme depuis sa mis en service .Donc timer et millis ont la meme duree donc timer -millis donnera toujours 0
du coup j ai du mal a comprendre comment if (millis() - timer > 1000) . Puisque millis = timer , je ne vois pas comment à un moment donne timer >millis.
la question est ici comment la variable timer peut etre superieure à millis pour declencher une action ?
bon voila question en esperant avoir qqun qui puisse m eclairer à ce sujet
merci de vos retours et desole pour derangement
cdt

Un code arduino est composé de deux fonctions principales : setup et loop.
Le setup ne s'exécute qu'une seule fois au lancement, la loop s'exécute en boucle (d'où son nom).

millis() fournit en effet le nombre de millisecondes écoulées depuis le démarrage. Il ne donne 0 qu'au tout début, mais dès que certaines lignes sont exécutées, il ne donne plus 0.

Dans ton code, il y a :

   pinMode(13, OUTPUT);
   Serial.begin(9600);

avant la ligne
timer = millis();
donc à ce moment de l'exécution, millis() ne donnera pas 0 (plutôt une valeur de l'ordre de 25 à 30 ms).

Dans la loop, tu testes si timer - millis() dépasse la valeur 1000. C'est à dire s'il s'est écoulé une seconde depuis la dernière mise à jour de timer. Si oui, la ligne
timer = millis();
met la valeur fournie par millis dans la variable timer (elle est mise à jour). Comme c'est dans la loop, c'est exécuté en boucle.

Si tu veux, on peut "déplier" la boucle : ton code devient alors

   pinMode(13, OUTPUT);
   Serial.begin(9600);
   timer = millis();
<--- ça c est le setup --->
   if (millis() - timer > 1000) {
      ledState=!ledState; // changer l'état de la LED
      digitalWrite(13, ledState);
      timer = millis();
   }

   Serial.print("Time: ");
   Serial.println(timer);
<--- première exécution de la loop --->
   if (millis() - timer > 1000) {
      ledState=!ledState; // changer l'état de la LED
      digitalWrite(13, ledState);
      timer = millis();
   }

   Serial.print("Time: ");
   Serial.println(timer);
<--- deuxième exécution de la loop --->
   if (millis() - timer > 1000) {
      ledState=!ledState; // changer l'état de la LED
      digitalWrite(13, ledState);
      timer = millis();
   }

   Serial.print("Time: ");
   Serial.println(timer);
<--- troisième exécution de la loop --->
etc.

Tu vois alors que chaque fois que la condition est remplie la variable timer est changée, et contient le nombre de millisecondes écoulées depuis le lancement du code. Ce n'est donc pas 0, mais 1001 puis 2001, puis 3001, etc.

Tes print sont hors du bloc if donc sont exécutés à chaque boucle de la loop, ce qui doit faire énormément d'affichage. Tu peux les mettre dans le bloc, ce qui permettra de n'afficher le texte que lorsque timer change donc toutes les secondes :

 unsigned long timer;
boolean ledState = 0;

void setup() {
   pinMode(13, OUTPUT);
   Serial.begin(9600);
   timer = millis();
}
 
void loop() {
   if (millis() - timer > 1000) {
      ledState=!ledState; // changer l'état de la LED
      digitalWrite(13, ledState);
      timer = millis();
   Serial.print("Time: ");
   Serial.println(timer);
   }
}

Tu verras le texte s'afficher dans la console au moment où la led changera.

Si tu veux plus de détails sur la manière d'utiliser millis pour rythmer plusieurs tâches de manière indépendante (ou non) avec un arduino, j'ai fait un tuto ici (en anglais) :

En fait, millis() est une fonction qui "donne l'heure" ou plutôt le temps (en ms) écoulé depuis le démarrage du programme.

timer = millis();

mémorise la valeur de ce temps dans la variable timer pour pouvoir l'utiliser plus tard.

if (millis() - timer > 1000) {

demande à nouveau l'heure et regarde si 1000 ms se sont écoulées depuis qu'il l'a mémorisée dans timer.
Si ce n'est pas le cas, le processeur n'exécute pas les instructions dans les accolades (on appelle ça un bloc) qui suivent le if(), il passe directement à la suite c'est à dire à

  Serial.print("Time: ");
  Serial.println(timer);

dans le listing que tu as posté.
Par contre, si 1000 ms ou plus se sont écoulées, il exécute le bloc qui :

      ledState=!ledState; // inverse l'état une variable qui "représente" la LED
      digitalWrite(13, ledState); // applique cet état sur la broche où est branchée la LED
      timer = millis(); // note la nouvelle heure qui servira de référence au 
                        //    prochain test "if(milli()) - timer > 1000)"

puis passe à la suite, c'est à dire

  Serial.print("Time: ");
  Serial.println(timer);

avant de recommencer encore et encore puisqu'on est dans la loop()

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