Calcul d'un débitmètre avec Arduino

Bonjour,

je vous sollicite car je pense que mon calcul de débit est faux. La doc de mon débitmètre : https://cdn.store-factory.com/www.compteur-energie.com/media/Bmeters-compteur-eau-impulsion-mid-r160_compteur-energie_com.pdf
Ce qu'il faut surtout retenir : 1 impulsion = 1 litre

const int broche_debit = 2;
volatile int compteurImpulsions;
unsigned long oldTime = 0;

void ISRImpulsions(){
  compteurImpulsions++;
}

void setup() {
  Serial.begin(9600);
  pinMode(broche_debit, INPUT_PULLUP); // Utilise la résistance de 1'Arduino
  attachInterrupt(digitalPinToInterrupt(broche_debit), ISRImpulsions, RISING); // passe de LOW a HIGH = RISING
}

void loop(){
      sei(); // Active l'interruption
      delay (1000); // Attend 1 seconde
      cli(); // Désactive l'interruption
    
      float pulseCount = compteurImpulsions;
      Serial.print("Consommation d'eau utilisée = "); // 1 litre = 1 impulsion
      Serial.print(pulseCount); 
      Serial.println(" L");
    
      // Calcul du débit Q = volume / durée
      float q = pulseCount/1000;
      Serial.print("Q = ");
      Serial.print(q); 
      Serial.println(" L/sec"); 
    
      // Convertir en L/min : 1 L/sec -> 60 L/min
      //                      q L/sec -> ?
      float qmin = q*60;
      Serial.print("Q = ");
      Serial.print(qmin); 
      Serial.println(" L/min"); 
      Serial.println();
}

Lorsque je met un jet d'eau très faible :

image

: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

Bonjour

Avec un code en fichier joint tu perds des opportunités de réponses (nombreux visiteurs sur smartphone ou tablette)

Regardes la partie 'Quelques outils ' des 'Bonnes Pratique' pour découvrir comment poster correctement du code

désolé. j'ai modifé

Ce qu'il faut surtout retenir : **1 impulsion = 1 litre**

VU ! donc 1 impulsion chaque seconde c'est 1 litre par seconde

Apparement tu actives l'interruption pendant une seconde , le décompte des interruptions survenues pendant ce laps de temps est donc un nombre de litres par seconde ou l/s, si tu divises ça par 1000 tu as des m3/s

Quand prévois-tu la remise à zéro du décompte d'interruptions ? sans cela pas de débit-mètre , mais un compteur totalisateur, un cumul des litres ayant traversé le compteur

Bonjour,

Par défaut Serial.print() affiche les floats avec deux décimales, les chiffres significatifs sont au delà de la deuxième décimale.
Affiche avec plus de décimales
Serial.print(q,5);

Bonjour @al1fch,

  1. Merci d'avoir répondu. En effet, j'avais un doute s'il fallait diviser par 1000 vu qu'il y avait déjà un delay(1000) au dessus. le compteur, je l'ai remis en entier (int). Je l'avais mit en float pour des testes.

  2. De plus, j'ai remarqué que quand je compilais, le moniteur série affichait les anciennes valeurs. Donc oui il faut une remise à 0, donc compteurImpulsions = 0. Mais je sais pas où je dois le placer dans mon code.

  3. Enfin, si j'enlève le "/1000" mes calculs de débit sont justes. Il y a juste ma variable pulseCount qui n'affiche plus le volume en L mais des L/sec ? Ainsi, si je veux avoir également la consommation d'eau : je dois faire Q = Volume/durée <=> Volume = Q * durée = pulseCount * 1000 ?

si tu veux la consommation d'eau en litres il faut cumuler à part les impulsions (=les litres) dans une variable spécifique.

les comptage des interruptions va lors faire progresser :
-une variable remise à zéro après chaque intervalle de comptage pour le débit en litre/s
-une variable non remise à zéro pour la consommation en litres

Merci @kamill, avoir des chiffres plus précis c'est mieux.

La doc de mon débitmètre

c'est un compteur , le débitmetre c'est toi qui le fabriques en y ajoutant ta carte et ton programme à un compteur d'eau !!

(le compteur que tu utilises donne des informations sur les volumes qui l'ont traversé, mais aucune information sur le débit )

Ok, si je prends en compte tes indications dans mon code.

const int broche_debit = 2;
volatile int compteurImpulsions;

void ISRImpulsions(){
  compteurImpulsions++;
}

int recupVolume(){
  // Stock le volume de litre dans une autre variable
  int consommation = compteurImpulsions; // 1 litre = 1 impulsion
  return consommation;
}

void setup() {
  Serial.begin(9600);
  pinMode(broche_debit, INPUT_PULLUP); // Utilise la résistance de 1'Arduino
  attachInterrupt(digitalPinToInterrupt(broche_debit), ISRImpulsions, RISING); // passe de LOW a HIGH = RISING
}

void loop(){
      Serial.print("Consommation d'eau utilisée = "); 
      Serial.print(recupVolume()); 
      Serial.println(" L");

      pulseCount = compteurImpulsions
      compteurImpulsions = 0; // Remise à 0 
      sei(); // Active l'interruption
      delay (1000); // Attend 1 seconde
      cli(); // Désactive l'interruption
 
      float debitSeconde = pulseCount;
      Serial.print("Q = ");
      Serial.print(debitSeconde, 5); 
      Serial.println(" L/sec"); 
    
      float debitMinute = pulseCount*60;
      Serial.print("Q = ");
      Serial.print(debitMinute, 5); 
      Serial.println(" L/min"); 
      Serial.println();
}

Je pense, il doit y avoir des erreurs dans ma compréhension car ça m'affiche 0 L et pareil pour le débit en L/sec.

si quelqu'un s'y connait, je dis pas non à de l'aide.

Je sais que je suis pas loin c'est juste la remise à 0 je sais pas ou la mettre :thinking:

ou alors faire un autre attachInterrupt avec une autre fonction qui incrémente une autre variable ?

Bonjour,

Le code que vous proposez ne compile pas.
Il manque au moins l'initialisation de la variable « pulseCount ». Du coup, comment obtenez-vous l'affichage 0L ? Avez-vous vérifié que programme a bien été uploadé dans l'Arduino ?

Par ailleurs, avec cette partie de la loop :

      sei(); // Active l'interruption
      delay (1000); // Attend 1 seconde
      cli(); // Désactive l'interruption

vous activez l'interruption pendant 1 seconde. Êtes-vous sûr « d'intercepter » un pulse durant cette durée ? Si il n'y a pas de pulse pendant que l'interruption est active, le volume est forcément à 0 ainsi que le débit.

Si vous voulez pouvoir calculer un débit, il faut maintenir l'interruption active, incrémenter le nombre d'impulsions détectées tout en comparant avec l'instant courant par rapport au démarrage de l'Arduino :

  • le volume en L est donné par le nombre d'impulsion (d'après **1 impulsion = 1 litre**)
  • le débit en L/s est donné par le nombre d'impulsions/intervalle de temps depuis le démarrage de l'Arduino (ou depuis l'initialisation d'un temps de référence correspondant à l'activation de l'interruption) : debit=nombre d'impulsion/(instant courant-instant référence).

Charlot

Bonjour nythix

Non, ce n'est pas nécessaire.
Ton delay (1000); // Attend 1 seconde n'est pas très bon, cette fonction est dite bloquante, c'est à dire que ton programme ne peut plus rien faire pendant ce temps, sauf le comptage en interrupt. Il y a mieux à faire avec millis() (Exemple BlinkWithoutDelay.ino).
Je te donne l'exemple en adaptant ton programme, la variable mesureTempo assure le rythme des mesures à toi de l'ajuster à ta guise. La fonction int recupVolume() n'est plus nécessaire.
Je te laisse rajouter tout les autres calculs.

const int broche_debit = 2;
volatile int compteurImpulsions;
int consommation =0;
 
unsigned long mesureTempo = 1000;     // Toutes les secondes
unsigned long mesureMillis = millis;     // Chronomètre

void setup() 
{
	Serial.begin(9600);
	pinMode(broche_debit, INPUT_PULLUP); // Utilise la résistance de 1'Arduino
	attachInterrupt(digitalPinToInterrupt(broche_debit), ISRImpulsions, RISING); // passe de LOW a HIGH = RISING
}

void loop()
{
	if (millis()-mesureMillis >= mesureTempo)     // Si fin de periode de mesures
	{
		consommation = compteurImpulsions;
		compteurImpulsions = 0;

		Serial.println("consommation = " + String(consommation));

		mesureMillis = millis();     // Redémarrage du chrono
	}
}


void ISRImpulsions()
{
	compteurImpulsions++;
}

//int recupVolume()
//{
	//// Stock le volume de litre dans une autre variable
	//int consommation = compteurImpulsions; // 1 litre = 1 impulsion
	//return consommation;
//}

Cordialement
jpbbricole

Il y a quelque chose que je ne comprends pas. On a déjà réglé ces problèmes ici il y a une semaine.

Pourquoi avoir ouvert un nouveau fil de discussion pour reposer sensiblement les mêmes questions. On tourne en rond!!
@nythix Tu avais d'ailleurs conclu

" Du coup, j'ai repris ce que vous avez fait avec la fonction millis(). Il y a juste le "debit = litres*60" à modifier et normalement c'est bon."

Donc pourquoi avoir tout cassé pour repartir avec le soft à l'origine de tes problèmes?

car quand j'ai effectué le branchement avec mon tuyau d'arrosage, j'ai vite remarqué un problème dans les calculs ou ailleurs.

merci d'avoir répondu @jpbbricole

j'ai écris ça :

if (millis() - mesureMillis >= mesureTempo)     // Si fin de periode de mesures
  {
    consommation = compteurImpulsions;
    compteurImpulsions = 0;
    Serial.println("consommation = " + String(consommation) + " L");

    debit = consommation*60;
    Serial.println("Debit = " + String(debit) + " L/min");
    Serial.println();
    mesureMillis = millis();     // Redémarrage du chrono
  }
}

j'ai testé avec mon tuyau d'arrosage. Le résultat que j'obtiens n'a pas l'air très bon :

Donc vu les résultats que j'obtiens, tu as surement raison @MB_F_45, en 1 seconde il n'a pas le temps de détecter une impulsion ce qui affiche la valeur 0.

Peut-être mettre la période de mesures toutes les 3 secondes ?
Mais ducoup faut modifier le calcul et écrire : debit = consommation/3000*60000 L/min (pas sur du calcul)

Voire même plus, quand j'ai mis
unsigned long mesureTempo = 1000; // Toutes les secondes
C'était pour l'exemple :wink:

Ensuite tu mets cette variable dans ton calcul (pour autant qu'il soit juste)
debit = consommation/mesureTempo*60000 L/min

Cordialement
jpbbricole