Réalisation d'un débimètre

Salut,

Je tente de réaliser un débitmètre pour connaitre une consommation d'eau. Mais je rencontre quelques soucis au niveau du code.

J'utilise ce débitmètre pour mon projet : B.I.O-TECH e.K. Contrôleur de débit d'air FCH-M-POM-LC AD 6 MM FLOWMETER Tension de fonctionnement (gamme): 5 - 24 V/DC | Conrad.fr

Le débitmètre est sans la buse fournie avec ce qui me donne un débit possible 0.05 à 3.0 L/min
Et il est "estimé" dans la notice 2500 impulsions du débitmètre pour 1 litre.

J'ai commandé également une carte Arduino Micro pour ce projet.

Les branchements sont corrects et je reçoit bien un signal du débitmètre quand je souffle dedans. Mais je n'arrive pas à retranscrire, les données produite en débit.

J'ai trouvé un code sur un tachymètre (capteur à effet hall aussi) mais je ne comprends pas tout :

#define PULSE_PIN 7
#define PULSE_TIMEOUT 1000000
 
unsigned long rpm; 
int i = 0;  

void setup () {  
  Serial.begin(9600);
  pinMode(PULSE_PIN, INPUT);  
  digitalWrite(PULSE_PIN, HIGH);
} 
 
void loop () { 
  rpm = pulseIn(PULSE_PIN, LOW, PULSE_TIMEOUT); 
  rpm = 60 / (rpm / 1000000.0)
  Serial.println(rpm, DEC);
  delay(500);
}

pourquoi definir la variable "PULSE_TIMEOUT" sur 1000000 ?

Sur d'autres exemples de débimètre la fonction "attachInterrup" est utilisée, mais je n'en comprends pas l'utilisation.

J'ai regardé la documentation ici : Référence Arduino français Main/Attach Interrupt

La syntaxe recommandée est : attachInterrupt(digitalPinToInterrupt(pin), ISR, mode);

Et pour la micro je dois utiliser les pins 0, 1, 2, 3 ou 7 ? Est-ce bien ça ?

Pouvez-vous me donner un exemple avec cette fonction ?

Merci

Vous avez regardé la fonction pulseIn?

Pour simplifier on peut imaginer que Le flux du liquide entraîne une turbine sur laquelle une (ou plusieurs) ailette a un aimant qui passe sous un capteur à effet hall ce qui déclenche un front haut sur une sortie numérique pendant que l'aimant est sous le capteur.

La spécification associée à votre produit dit que pour de l'eau (H2O) à 20°C vous aurez 2.500 Impulsiions par litre d'eau.

Donc pour calculer le débit en litre / secondes vous pouvez

  • compter le nombre d'impulsions que vous recevez en un certain temps, par exemple en supposant que le flux est continu et régulier, vous comptez le nombre d'impulsions en 1 seconde vous divisez par 2500 (référence d'impulsion par secondes pour 1l) et multipliez par 3600 (secondes dans une heure) et vous avez votre débit en litres par heure.
  • mesurer la durée d'un front bas. C'est ce que fait pulseIn ci dessus (avec un timeout grand). Il attend un prochain LOW, commence à compter le temps en microsecondes avant que le signal ne remote à HIGH. ça vous donne la durée instantanée entre 2 impulsions, si,vous connaissez le nombre d'impulsions pour 1 tour de turbine vous pouvez calculer le nombre de tour par minute instantanné (rpm). dans l'exemple que vous avez il font le calcul avec 1 impulsion par tour d'ou leur formule. ici la spec ne le dit pas mais vous avez le temps pour 1 impulsion en multipliant par 2500 vous aurez le temps (en microseconde) pour 1 litre - et par simple; règle de trois vous trouvez le débit.

pour calculer le volume d'eau consommée il suffit de compter les impulsions au bout de 2500 vous savez qu'un litre est passé. Compter des impulsions se fait simplement avec une interruption. Si vous voulez le débit, mesurez combien de temps passe en même temps que les interruptions défilent et avec une simple règle de trois vous aurez le débit.

Voilà donc pourquoi on peu soit soit faire du pulseIn - ça donne une valeur instantanée et par intégration dans le temps vous trouvez les volume et volume moyen, ou l'option interruption qui vous donne la consommation et par division par la durée un débit moyen;

Ok?

Bonjour,

Il faut que tu utilises les interruptions.
L'utilisation des interruptions est très simple avec arduino (comme le montre l'exemple dont tu donnes le lien).
Tu fais la même chose que dans ton exemple mais au lieu de faire clignoter tu incrémentes un compteur.

Les pins utilisables sont 2 pour l'it 0 et 3 pour l'it 1.

Salut,

Merci pour vos réponses J-M-L et kamill

Voici mon nouveau programme en utilisant les interruptions :

volatile int pulseCount = 0;
uint32_t curTime;

void setup()
{
Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(0), countImpulsions, RISING); // fil du capteur connecté sur le pin 2
}

void loop()
{
//ajout du temps
curTime = millis(); // temps depuis le début d'execution du programme
// 2500 impulsions pour 1 litre
// débit pas forcement constant ==> calculer le nombre d'impulsions sur une seconde
// Q = ( NbrImpulsions / sur une seconde ) / 2500
Serial.print(pulseCount); //nombre d'impulsions totales depuis le début 
}

void countImpulsions()
{
pulseCount++;
}

Je dois ensuite ajouter la notion de temps :
Il faut prendre en compte que le signal envoyé par le débitmètre n'est pas constant. Comme a dit J-M-L il faut compter le nombre d'impulsions sur une seconde.

Q = ( NbrImpulsions / sur une seconde ) / 2500

j'ai vu la fonction millis() qui permet d'obtenir le temps depuis le démarrage du programme.

Mais comment mettre en place le calcul sur 1 seconde ?

Il faut que tu utilises millis() pour mesurer le temps écouler et faire le calcul toutes les secondes en divisant la différence du compteur par la différence du temps.

volatile unsigned long pulseCount = 0;
uint32_t curTime;
unsigned long startTime=0;    // début du nouveau comptage
unsigned long pulseCountPrec=0;


void setup()
{
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(2), countImpulsions, RISING); // fil du capteur connecté sur le pin 2
}

void loop()
{
  //ajout du temps
  curTime = millis(); // temps depuis le début d'execution du programme
  if (curTime-startTime>1000)     // calcul du débit toutes les secondes
  {
    // 2500 impulsions pour 1 litre
    // débit pas forcement constant ==> calculer le nombre d'impulsions sur une seconde
    // Q = ( NbrImpulsions / sur une seconde ) / 2500
    float q=(pulseCount-pulseCountPrec)/((curTime-startTime)/1000.0)/2500.0;
    startTime=curTime;
    pulseCountPrec=pulseCount;
    Serial.println(q);
  }
//  Serial.println(pulseCount); //nombre d'impulsions totales depuis le début
}

void countImpulsions()
{
  pulseCount++;
}

J'ai rectifié attachInterrupt dans digitalPinToInterrupt() c'est le numéro de pin et non le numéro d'interruption.

Salut le diamètre de la buse est de combien, car dans la doc, il est écrit : Nombre d'impulsions D = 1,6 mm : 8500 impulsions/l, D = 3 mm : 2500 impulsions/l

Sinon tu n'a pas d'autre information sur le débitmètre, car j'ai est utilisé un cette année pour un projet et il faisait référence à une fréquence en fonction du débit , de toute façon cela ne change pas grand chose, il faut juste compter le nombre d'impulsions sur 1 seconde, puis de faire un calcul simple afin de determiner le volume de liquide passé dans le débitmètre. (voir programme de Kamill)

@+

@kamill (et les autres)

le programme proposé par Kamill a la bonne approche, d'une part la boucle principale n'a pas besoin d'imprimer en permanence le débit - une fois par seconde c'est effectivement suffisant.

Je propose possiblement 3 modifications au programme de Kamill:

1/ si on ne veut meusrer que le débit
pulseCountPrec=pulseCount; ne sert pas à grand chose. autant mettre pulseCount à zéro et on repart pour un cycle. Bien sûr si on conserve pulseCountPrec alors on a aussi une idée du volume de liquid consommé depuis le début de la mesure, ce qui peut être utile. mais si on ne s'en sert pas, autant ne pas le mémoriser :slight_smile:

2/ les calculs sur des float prennent du temps, autant aider un peu le compilateur

    float q=(pulseCount-pulseCountPrec)/((curTime-startTime)/1000.0)/2500.0;

--> si on a viré pulseCountPrec alors on gagne une soustraction et on peut simplifier un peu, le calcul devient
    float q= pulseCount/((curTime-startTime) * 2.50); l/s
--> sinon a viré pulseCountPrec alors le calcul devient
    float q=(pulseCount-pulseCountPrec)/((curTime-startTime)*2.50); l/s

3/ lorsque l'on fait les calculs de débit, on est en section critique car une de nos variables peux évoluer entre chacune de nos lignes de calcul. Dans l'absolu il vaut mieux arrêter les interruptions pendant ce temps là, comme cela pulseCount ne va pas varier (par exemple le pulseCount que kamill propose à la fin dans pulseCountPrec=pulseCount; pourrait ne pas être le même que celui utilisé dans le calcul du débit à la ligne avant). Pour cela encadrer le code dans le if par cli(); et sei(); et bien entendu

if (curTime-startTime>1000) {    // calcul du débit toutes les secondes
      cli(); // désactive global interrupts
          .. // le code qui va bien
          startTime= millis(); // pour avoir le compteur au plus proche de la réalité des mesures
      sei(); // active global interrupts
}

Si le débit est vraiment élevé et que l'on a plusieurs milliers d'interruptions par seconds, alors la gestion du temps devrait être effectuée de la même manière mais avec micros() pour avoir plus de précisions dans le calcul de la moyenne.

Bonjour J-M-L,

  1. On peut effectivement remettre le compteur à 0, mais avoir le compte total permet de pouvoir calculer la quantité débitée (ce qi je te l'accorde n'est pas demandé ici).

  2. Moi j'ai tendance à privilégier la lisibilité du programme et à penser que c'est au compilateur à optimiser.

  3. J'ai un peu simplifié. Effectivement si on n'a pas de bol la valeur de pulseCount peut changer durant la lecture des différents octets de la variable. Et si on n'a vraiment pas de bol on a pu avoir ne retenue d'un octet de poids faible sur l'octet suivant ce qui peut donner une valeur fausse.
    Pour minimiser le temps de masquage des interruption, la bonne pratique est de ranger la variable dans une variable temporaire et d'utiliser ensuite cette variable temporaire.

 if (curTime-startTime>1000)     // calcul du débit toutes les secondes
 {
   cli();
   unsigned long pulseCountL=pulseCount;
   sei();
   ...
 }

kamill:
...
Pour minimiser le temps de masquage des interruption, la bonne pratique est de ranger la variable dans une variable temporaire et d'utiliser ensuite cette variable temporaire.

oui se pose quand même le pb de pulseCount qui va continuer alors à tourner alors que vous avez figé le temps dans une variable. Bon ça se joue à qques microsondes donc globalement on ne manque rien, au pire 1 tick..

Bonjour je vous solicite car je suis en terminale STI2D en projet de BAC et je dois programmer un débitmètre de séries 210 et de diamètre nominal DN8 qui fait aussi capteur de température et je n'ai pas la moindre idée de comment le programmer :frowning: car je dois aussi le liée à un LCD afin que dans mon montage et avec mon programme, le LCD affiche le débit et la température mesurée à 5 endroits différents en utilisant un lcd.clear je pense. :o

J'ai trouvé un PDF qui me donne des informations : file:///D:/LYCEE/TSTI2D/SIN/PROJET_DE_BAC/210_Debitmetre_SURLIGNE.pdf

Voila j'espere avoir été claire et merci à vous d'avoir pris le temps de lire ce post ;D

Marshadow-_-:
Bonjour je vous solicite car je suis en terminale STI2D en projet de BAC et JE dois programmer un débitmètre....

Bonjour - lisez comment utiliser le forum (les posts épinglés en haut du forum comme « Bien éditer son post pour les nuls » , « Faire un Nouveau Sujet ou le corriger avec les Balises... » et « Règles du forum francophone »), et faites un post « propre »