Mesure de puissance thermique & data logging

lundi 12 mai 2014
par  Finizi
popularité : 31%

Toujours dans le but de surveiller les énergies reçues et consommées, voici un montage qui permet de mesurer et d’envoyer sur un server Internet toutes les données concernant une puissance thermique, qu’elle soit produite ou consommée.
L’installation décrite ici à été posée sur un système solaire thermique de façon à enregistrer la puissance fournie au ballon d’eau chaude par le soleil.


 Le matériel

Le matériel utilisé est composé de :


 La théorie

La puissance thermique s’obtient en mesurant un flux de chaleur, exprimé en Watts. La formule est la suivante : P (W) = m (L/h) * cp * dT * 1.16.
Il faut donc mesurer :

  • une différence de température, donc la température d’entrée et le température de sortie, en °K (ou en °C puisqu’on calcul une différence).
  • le débit du fluide caloporteur en litres par heure.

Le coefficient cp vaut 1 pour l’eau. Il diminue légèrement si l’eau est glycolée.
Il nous faut donc deux capteurs de température et un débitmètre.

Data logging
Les données sont envoyées à un server Internet via une requête GET. Tout est dans l’Url.
Celle ci sera de la forme : http://ip_de_mon_server:port/page/etat=Stop&in=23.88&out=23.81&flow=225.21&Wh=2700&millis=16019
Sont donc envoyées les informations suivantes :

  1. Etat
  2. Température d’entrée
  3. Température de sortie
  4. Débit du fluide caloporteur
  5. Puissance
  6. millis() qui est le temps le temsp interne du microcontrôleur, de façon à surveiller son fonctionnement.

Bien entendu, il est possible d’envoyer les données de différentes manières. Il faut juste que le server Internet sache les récupérer.


 Le montage

Le shield Ethernet vient se brancher sur la carte Arduino, et le protoshield au dessus.
Les broches utilisées directement dans le montage sont :
- 2 : Débitmètre
- 3 : Capteur température entrée
- 5 : Capteur température sortie

D’autres broches ne sont pas disponibles, car utilisées par la carte Ethernet :
- 4 : carte SD
- 10 : contrôleur Ethernet
- 11 : SPI bus : MOSI
- 12 : SPI bus : MISO
- 13 : SPI bus : SCK

Bien que les capteurs de température DS18B20 puissent être utilisés en réseau (comme par exemple dans ce montage), ici, pour des raisons de simplicité, chaque capteur est assigné à une broche de l’arduino.
Ceci évite d’avoir à connaitre l’adresse du capteur dans son réseau, comme cela est expliqué dans cet article sur la régulation simple.

PNG - 93.7 ko
Plan général

Au niveau de l’électronique, il y a une résistance de 4,7 kΩ entre le +5v et la broche data des capteurs de température, ainsi qu’une résistance de 10 kΩ entre le +5v et la broche de signal (data) du débit mètre.

PNG - 46.6 ko
Schéma électronique

 Le programme

Pour avoir tous les détails concernant la programmation d’une carte Arduino, reportez-vous à l’excellent site francophone mon-club-elec.fr qui propose de nombreux tutoriaux.
Le programme est largement commenté.
Le code se décompose en 4 parties, dans cet ordre :

  • 1. Les déclarations
  • 2. L’initialisation
  • 3. La boucle
  • 4. Les fonctions diverses

1. Les déclarations

  • Avec la plateforme Arduino, il existe de nombreuses bibliothèques prêtes à l’emploi. C’est ici qu’il faut les déclarer :
    • avr/wdt.h : Pour le WatchDog
    • OneWire.h : Pour gérer les bus OneWire
    • DallasTemperature.h : Pour les capteurs de température
    • SPI.h : Pour la carte Ethernet
    • Ethernet.h : Pour la carte Ethernet
    • EthernetServer.h : Pour la communication Ethernet
    • EthernetClient.h : Pour la communication Ethernet
    • stdlib.h : Bibliothèque générique
  • On va aussi déclarer les variables globales, c’est à dire en gros, les variables toujours disponibles, ainsi que les objets et différents paramètres.

2. L’initialisation

  • C’est la fonction setup(). Cette fonction n’est exécutée qu’une seule fois au démarrage du microcontrôleur. Il s’agit d’initialiser le microcontrôleur avant de pouvoir s’en servir pleinement.
  • Les initialisations suivantes sont effectuées :
    • Communication série, pour le debug
    • WatchDog pour réinitialiser la carte en cas de plantage. Quelques informations ici.
    • Débimétre
    • Capteurs de température, températures d’entrée puis de sortie.
    • Connexion Ethernet.
    • Initialisation de l’état du programme. Il ne faut pas perdre de vue qu’on ne sait pas à priori dans quel état se trouve l’installation.
    • Envoi au server Internet de l’adresse IP locale de la carte Ethernet.

3. La boucle

  • La fonction loop() est le cœur du programme. Une fois l’initialisation terminée, le microcontrôleur va exécuter cette fonction en boucle infinie. C’est à dire que aussitôt terminée, elle est relancée.
  • C’est ici que vont être gérés les différents états de l’installation, et que les décisions vont se prendre en fonction des informations renvoyées par les capteurs de température et le débitmètre.
  • Les opération suivantes sont effectuées dans cet ordre :
    • Réinitialisation du WatchDog.
    • Lecture des températures
    • Vérification de la cohérence des températures. Si incohérence, la lecture effectuée est rejetée.
    • Calcul du débit
    • Décisions sur les actions a mener en fonction des lectures faites sur les capteurs et changement éventuel de l’état.
    • Envoie éventuel des données vers le server Internet
    • Une pause, rien ne sert de recommencer rapidement.

4. Les fonctions diverses

  • Le but de ces fonctions est de structurer le code de la boucle. Soit c’est un bout de code utilisé à plusieurs endroits, auquel cas il est intéressant de ne l’écrire qu’une seule fois, soit c’est juste un bout de code que l’on isole et qui aura désormais un nom. Au niveau du programme en lui même, cela ne change rien, par contre, au niveau de la lecture du code et de sa compréhension par l’auteur ou un autre auteur, cela clarifie grandement les choses.
  • Ici, nous trouvons les fonctions suivantes :
    • SIGNAL : Fonction système liée aux interruptions.
    • useInterrupt : Initialise la récupération des interruptions.
    • url : Mise en forme des données à envoyer.
    • flow : Effectue le calcul de la puissance thermique.
    • sendToServer : Envoie des données au server
    • printAddress : Envoie au terminal série l’adresse du capteur de température. (fonction de debug)

 Le code complet

Le code est aussi disponible sur GitHub.

Et voici l’intégralité du code.

  1.  
  2. // --- Programme Arduino ---
  3. // Copyright finizi - Créé le 20 janvier 2014
  4. // www.DomoEnergyTICs.com
  5. //  Code sous licence GNU GPL :
  6. //  This program is free software: you can redistribute it and/or modify
  7. //  it under the terms of the GNU General Public License as published by
  8. //  the Free Software Foundation, either version 3 of the License,
  9. //  or any later version.
  10. //  This program is distributed in the hope that it will be useful,
  11. //  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. //  GNU General Public License for more details.
  14. //  You should have received a copy of the GNU General Public License
  15. //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16. //
  17. /*
  18. ****************************************************************************************************
  19.     Dispositif pour mesurer une puissance thermique.
  20.     Obtenir une différence de température entre 2 capteurs.
  21.     Obtenir le débit de fluide caloporteur.
  22.     Calculer la puissance par la formule : P (W) = m (L/h) * cp * dT * 1.16  avec cp = 1 pour l'eau
  23.      
  24.      
  25.     Utilisation des broches
  26.      
  27.       Analogiques
  28.         aucune
  29.       Digitales
  30.         2 :  => Flow Meter
  31.         3 :  => Capteur température entrée
  32.         4 :  Net - SS for SD card
  33.         5 :  => Capteur température sortie
  34.         10 : Net - SS for ethernet controller
  35.         11 : Net - SPI bus : MOSI
  36.         12 : Net - SPI bus : MISO
  37.         13 : Net - SPI bus : SCK
  38.        
  39. ****************************************************************************************************
  40. */
  41. /*
  42. ****************************************************************************************************
  43. **
  44. **  Plan
  45. **    Déclarations
  46. **     . Includes
  47. **     . Defines
  48. **     . Variables globales
  49. **     . Objets
  50. **    Fonctions obligatoires
  51. **     . setup
  52. **     . loop
  53. **    Fonctions utilisateur
  54. **     . SIGNAL
  55. **     . useInterrupt
  56. **     . url
  57. **     . flow
  58. **     . power
  59. **     . sendToServer
  60. **     . printAddress
  61. **
  62. ****************************************************************************************************
  63. */
  64. #include <avr/wdt.h>               // Pour le WatchDog
  65. #include <OneWire.h>               // Pour gérer les bus OneWire
  66. #include <DallasTemperature.h>     // Pour les capteurs de température
  67. #include <SPI.h>                   // Pour la carte Ethernet
  68. #include <Ethernet.h>              // Pour la carte Ethernet
  69. #include <EthernetServer.h>        // Pour la communication Ethernet
  70. #include <EthernetClient.h>        // Pour la communication Ethernet
  71. #include <stdlib.h>
  72. /*
  73. **  Declaration des parametres de fonctionnement
  74. */
  75. const byte netServerIP[4] = { 192, 168, 22, 44 };           // Adresse IP du server vers lequel envoyer les infos
  76. const int netServerPort = 8901;
  77. const float CoefLitHour = 60.0 / 7.5;                       // FlowMeter 1/2 : Coefficient de conversion de tick par secondes en litres par heures
  78. const unsigned long temperatureReadInterval = 9L * 1000L;   // Delai entre deux lectures de température (9 secondes)
  79. const float flowSartLimit = 2.0;                            // Débit, en L/H séparant l'état de marche et l'état d'arrêt
  80. const unsigned long serverPostingIntervalOn = 1L;           // Intervale, en minutes, d'envoi des données lorsque la pompe est en marche (toutes les minutes)
  81. const unsigned long serverPostingIntervalOff = 15L;         // Intervale, en minutes, d'envoi des données lorsque la pompe est à l'arrêt (toutes les 15 minutes)
  82. const float temperatureMini = -40.0;                        // Température en dessous de la quelle elle n'est pas prise en compte
  83. const float temperatureMaxi = 130.0;                        // Température au dessus de la quelle elle n'est pas prise en compte
  84. /*
  85. **  Declaration des parametres de l'installation
  86. */
  87. byte netMac[6] = { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60};     // Adresse MAC de la carte ethernet arduino
  88. const int pinFlowMeter = 2;            // Débitmètre
  89. const int pinTempIn = 3;               // Capteur température entrée
  90. const int pinTempOut = 5;              // Capteur température sortie
  91. /*
  92. **  Declaration des constantes
  93. */
  94. const int etatInconnu = 0; // L'état est inconnu. C'est la valeur par défaut. C'est donc l'état au démarrage
  95. const int etatStop = 1;    // Le fluide caloporteur ne circule pas
  96. const int etatMarche = 2;  // Le fluide caloporteur circule. La pompe est donc en fonctionnement
  97. const int etatDefaut = 3;  // L'installation se met en défaut
  98. /*
  99. ** Déclaration des variables et initialisations
  100. */
  101. int etat = etatInconnu;
  102. int lastEtat = etatInconnu;
  103. int beforeDefaultEtat = etatInconnu;
  104. float tempIn = -99.9;
  105. float tempOut = -99.9;
  106. // Chaines d'état à afficher
  107. const String etatsText[4] = {
  108.   "Inconnu",         // #define etatInconnu 0
  109.   "Stop",            // #define etatStop 1
  110.   "Marche",          // #define etatMarche 2
  111.   "Defaut"           // #define etatDefaut 3
  112. };
  113. unsigned long serverLastConnectionTime = 0L;  // Dernière fois que l'on a envoyé des données au server, en millisecondes
  114. unsigned long temperatureTime = 0L;           // Dernière fois que les températures ont été lues, en millisecondes    
  115. char fBuf[32];                                // Buffer char pour recevoir un float converti en string
  116. unsigned long loopFlowMeterLastCalcTime = 0L; // Dernière fois que l'on a calculé le débit
  117. unsigned long loopLastPulses = 0L;
  118. float loopMeanFlow = 0.0;
  119. unsigned long sendFlowMeterLastCalcTime = 0L; // Dernière fois que l'on a envoyé le débit
  120. unsigned long sendLastPulses = 0L;
  121. float sendMeanFlow = 0.0;
  122. /*
  123. **  Variables utilisées dans les interruptions
  124. */
  125. volatile unsigned long pulses = 0L;           // Pour compter le nombre de battements
  126. volatile unsigned char lastFlowPinState;      // Pour conserver l'état précédent d'une boucle à la suivante
  127. volatile unsigned int lastFlowRateTimer = 0;  // Conserver le temps entre 2 battements
  128. volatile float flowRate;                      // Calcul du débit
  129. /*
  130. **  Création des objets
  131. */
  132. OneWire oneWireIn(pinTempIn);            // on défini la broche utilisée pour la température d'entrée
  133. OneWire oneWireOut(pinTempOut);          // on défini la broche utilisée pour la température de sortie
  134. // Passer une référence OneWire à l'objet Dallas Temperature.
  135. DallasTemperature sensorIn(&oneWireIn);
  136. DallasTemperature sensorOut(&oneWireOut);
  137. // Tableaux indiquant l'adresse des capteurs
  138. DeviceAddress thermoIn;
  139. DeviceAddress thermoOut;
  140. // On instancie un objet client pour pouvoir se connecter à un server Internet
  141. EthernetClient netClient;
  142.  
  143.  
  144.  
  145. /*
  146. ****************************************************************************************************
  147. **
  148. **  setup  ==>  Fonction obligatoire d'initialisation
  149. **
  150. ****************************************************************************************************
  151. */
  152. void setup() {
  153.   // Initialisation de la communication série, pour le débuggage
  154.   Serial.begin(115200);
  155.   Serial.println("Serial init OK");
  156.   // Initialisation du WatchDog
  157.   wdt_enable(WDTO_8S);
  158.   Serial.println("Watchdog OK");
  159.   // Initialisation du débitmètre
  160.   pinMode(pinFlowMeter, INPUT);
  161.   digitalWrite(pinFlowMeter, HIGH);
  162.   lastFlowPinState = digitalRead(pinFlowMeter);
  163.   useInterrupt(true);
  164.   Serial.println("FlowMeter init OK");
  165.   // Initialisation du capteur de température d'entrée
  166.   Serial.print("Input temperature sensor :");
  167.   sensorIn.begin();
  168.   Serial.print("  Found ");
  169.   Serial.print(sensorIn.getDeviceCount(), DEC);
  170.   Serial.println(" devices.");
  171.   // Vérifie le mode d'alimentation
  172.   Serial.print("  Parasite power is: ");
  173.   if (sensorIn.isParasitePowerMode()) {
  174.      Serial.println("ON");
  175.   }
  176.   else {
  177.     Serial.println("OFF");
  178.   }
  179.   if (!sensorIn.getAddress(thermoIn, 0)) {
  180.     Serial.println("  Unable to find address for Device 0");
  181.   }
  182.   Serial.print("  Device 0 Address: ");
  183.   printAddress(thermoIn);
  184.   sensorIn.setResolution(thermoIn, 12);
  185.   Serial.print("  Device 0 Resolution: ");
  186.   Serial.println(sensorIn.getResolution(thermoIn), DEC);
  187.   // Initialisation du capteur de température de sortie
  188.   Serial.print("Output temperature sensor :");
  189.   sensorOut.begin();
  190.   Serial.print("  Found ");
  191.   Serial.print(sensorOut.getDeviceCount(), DEC);
  192.   Serial.println(" devices.");
  193.   // Vérifie le mode d'alimentation
  194.   Serial.print("  Parasite power is: ");
  195.   if (sensorOut.isParasitePowerMode()) {
  196.     Serial.println("ON");
  197.   }
  198.   else {
  199.     Serial.println("OFF");
  200.   }
  201.   if (!sensorOut.getAddress(thermoOut, 0)) {
  202.     Serial.println("  Unable to find address for Device 1");
  203.   }
  204.   Serial.print("  Device 1 Address: ");
  205.   printAddress(thermoOut);
  206.   sensorOut.setResolution(thermoOut, 12);
  207.   Serial.print("  Device 1 Resolution: ");
  208.   Serial.println(sensorOut.getResolution(thermoOut), DEC);
  209.   Serial.println("Sensors OK");
  210.   // Initialisation de la connexion Ethernet avec l'adresse MAC, l'adresse IP et le masque
  211.   if (Ethernet.begin(netMac) == 0) {
  212.     Serial.println("Failed to configure Ethernet using DHCP");
  213.     // On peut éventuellement essayer de configurer la carte avec une IP fixe
  214.     //Ethernet.begin(netMac, IpFixe);
  215.   }  
  216.   Serial.println("Ethernet DHCP OK");
  217.   Serial.print("Local IP = ");
  218.   Serial.println(Ethernet.localIP());
  219.   Serial.println("Ethernet OK");
  220.   // Initialisation de l'état
  221.   etat = etatInconnu;
  222.   lastEtat = etatInconnu;
  223.   beforeDefaultEtat = etatInconnu;
  224.   Serial.println("End Etat");
  225.   // Informer le server du setup en lui envoyant l'IP locale
  226.   String setupUrl;
  227.   setupUrl = "ip=";
  228.   for (byte thisByte = 0; thisByte < 4; thisByte++) {
  229.     // print the value of each byte of the IP address:
  230.     setupUrl += Ethernet.localIP()[thisByte];
  231.     if (thisByte < 3) {
  232.       setupUrl += ".";
  233.     }
  234.   }
  235.   Serial.println(setupUrl);
  236.   sendToServer("ip", setupUrl);
  237.   Serial.println("End Setup");
  238. }
  239.  
  240.  
  241.  
  242. /*
  243. ****************************************************************************************************
  244. **
  245. **  loop  ==>  Fonction obligatoire. Boucle infinie de fonctionnement
  246. **
  247. ****************************************************************************************************
  248. */
  249. void loop() {
  250.  
  251.   /*************************************************************
  252.   **
  253.   ** Reset du watchDog : C'est reparti pour 8 secondes
  254.   */
  255.   wdt_reset();
  256.   /*************************************************************
  257.   **
  258.   ** Lecture des températures
  259.   */
  260.   boolean temperatureRead = false;
  261.   // Ce n'est pas la peine de lire les températures à chaque boucle. Toutes les [temperatureReadInterval] millisecondes suffit
  262.   if ( (temperatureTime == 0) || ( (millis() - temperatureTime > temperatureReadInterval) && (millis() >= temperatureTime) ) ) {
  263.     temperatureTime = millis();
  264.     // Lecture des températures
  265.     sensorIn.requestTemperatures();
  266.     tempIn = sensorIn.getTempC(thermoIn);
  267.     sensorOut.requestTemperatures();
  268.     tempOut = sensorOut.getTempC(thermoOut);
  269.     temperatureRead = true;
  270.   }
  271.  
  272.   /*************************************************************
  273.   **
  274.   ** Cohérence des températures
  275.   */
  276.   // Si les températures autour du ballon sont trop basses, c'est qu'il y a un problème
  277.   if ( (etat == etatMarche) && ( (tempIn < 0.5) || (tempOut < 0.5) ) ) {
  278.     // On est en défaut
  279.     Serial.println("Default status !");
  280.     // Si on ne l'était pas avant, il faut enregistrer l'état en cours
  281.     if (etat != etatDefaut) {
  282.       beforeDefaultEtat = etat;
  283.     }
  284.     // On peut passer en défaut
  285.     etat = etatDefaut;
  286.   }
  287.   else {
  288.     // On n'est pas (on n'est plus) en défaut
  289.     // Si on était en déafut auparavant, on remet l'état d'avant le défaut
  290.     if (etat == etatDefaut) {
  291.       etat = beforeDefaultEtat;
  292.     }
  293.   }
  294.   /*************************************************************
  295.   **
  296.   ** Calcul du débit à chaque boucle
  297.   **   Permet de calculer l'état du capteur
  298.   */
  299.   unsigned long loopPulses = pulses;
  300.   unsigned long loopMillis = millis();
  301.   if (loopMillis > loopFlowMeterLastCalcTime) {
  302.     loopMeanFlow = (loopPulses - loopLastPulses) * 1000.0 / (loopMillis - loopFlowMeterLastCalcTime);
  303.   }
  304.   loopMeanFlow *=  CoefLitHour;
  305.   loopFlowMeterLastCalcTime = loopMillis;
  306.   loopLastPulses = loopPulses;
  307.  
  308.  
  309.   /*************************************************************
  310.   **
  311.   ** Actions à mener en fonction des mesures effectuées et de l'état en cours
  312.   */
  313.   switch(etat) {
  314.     case etatInconnu:       // ==> Survient normalement au démarrage
  315.       // Vérifier la circulation du fluide
  316.       if (loopMeanFlow > flowSartLimit) {
  317.         etat = etatMarche;
  318.       }
  319.       else {
  320.         etat = etatStop;
  321.       }
  322.       break;  
  323.     case etatStop:          // ==> Pas de circulation de fluide
  324.       // Vérifier si le fluide circule
  325.       if (loopMeanFlow > flowSartLimit) {
  326.         etat = etatMarche;
  327.       }
  328.       break;
  329.     case etatMarche:        // ==> Le fluide caloporteur circule.
  330.       // Vérifier si le fluide ne circule plus
  331.       if (loopMeanFlow < flowSartLimit) {
  332.         etat = etatStop;
  333.       }
  334.       break;
  335.     case etatDefaut:        // ==> L'installation s'est mise en défaut
  336.       // Ne rien faire et laisser ainsi
  337.       break;  
  338.   }
  339.   /*************************************************************
  340.   **
  341.   ** Envoyer les données sur un server si :
  342.   **   - L'état a changé
  343.   **   - OU  * L'interval est écoulé  
  344.   **         * ET une lecture vient d'avoir lieu
  345.   ** Le but est d'envoyer des infos le plus fraiches et pertinentes possibles au server
  346.   */
  347.   if (  (lastEtat != etat)
  348.         || ( (etat == etatMarche)
  349.             && (millis() - serverLastConnectionTime > serverPostingIntervalOn * 60L * 1000L)
  350.             && (temperatureRead)
  351.             && ( millis() >= serverLastConnectionTime) )
  352.         || ( (etat == etatStop)
  353.             && (millis() - serverLastConnectionTime > serverPostingIntervalOff * 60L * 1000L)
  354.             && (temperatureRead)
  355.             && ( millis() >= serverLastConnectionTime) )
  356.       ) {
  357.    
  358.     // Calcul du débit moyen à envoyer
  359.     unsigned long sendPulses = pulses;
  360.     unsigned long sendMillis = millis();
  361.     if (sendMillis > sendFlowMeterLastCalcTime) {
  362.       sendMeanFlow = (sendPulses - sendLastPulses) * 1000.0 / (sendMillis - sendFlowMeterLastCalcTime);
  363.     }
  364.     sendMeanFlow *=  CoefLitHour;
  365.     sendFlowMeterLastCalcTime = sendMillis;
  366.     sendLastPulses = sendPulses;
  367.        
  368.     String sendUrl = url(0);
  369.     if (sendToServer("data", sendUrl) == true) {
  370.       serverLastConnectionTime = millis();   // Réinitialise le compteur
  371.     }
  372.     // Debug : On imprime les données envoyées au port série
  373.     Serial.println(sendUrl);
  374.   }
  375.   lastEtat = etat;
  376.  
  377.   // Attendre avant de boucler (2 secondes)
  378.   delay(2000);
  379. }          
  380.  
  381.  
  382. /*
  383. ****************************************************************************************************
  384. **
  385. **  SIGNAL  ==>  Fonction système
  386. **               Interrupt is called once a millisecond, looks for any pulses from the sensor!
  387. **               source : https://github.com/adafruit/Adafruit-Flow-Meter
  388. **
  389. ****************************************************************************************************
  390. */
  391. SIGNAL(TIMER0_COMPA_vect) {
  392.   uint8_t x = digitalRead(pinFlowMeter);
  393.  
  394.   if (x == lastFlowPinState) {
  395.     lastFlowRateTimer++;
  396.     if (lastFlowRateTimer > 1000) {
  397.       flowRate = 0;
  398.       lastFlowRateTimer = 0;
  399.     }
  400.     return; // nothing changed!
  401.   }
  402.  
  403.   if (x == HIGH) {
  404.     //low to high transition!
  405.     pulses++;
  406.   }
  407.   lastFlowPinState = x;
  408.   flowRate = 1000.0;
  409.   flowRate /= lastFlowRateTimer;  // in hertz
  410.   lastFlowRateTimer = 0;
  411. }
  412.  
  413.  
  414. /*
  415. ****************************************************************************************************
  416. **
  417. **  useInterrupt  ==>  Fonction qui initialise la récupération des interruptions
  418. **                     source : https://github.com/adafruit/Adafruit-Flow-Meter
  419. **
  420. ****************************************************************************************************
  421. */
  422. void useInterrupt(boolean v) {
  423.   if (v) {
  424.     // Timer0 is already used for millis() - we'll just interrupt somewhere
  425.     // in the middle and call the "Compare A" function above
  426.     OCR0A = 0xAF;
  427.     TIMSK0 |= _BV(OCIE0A);
  428.   } else {
  429.     // do not call the interrupt function COMPA anymore
  430.     TIMSK0 &= ~_BV(OCIE0A);
  431.   }
  432. }
  433.  
  434.  
  435. /*
  436. ****************************************************************************************************
  437. **
  438. **      Fonctions diverses
  439. **
  440. ****************************************************************************************************
  441. */
  442. /*
  443. ** Formatte les données à envoyer au format url
  444. **     example : {"etat":"Stop","in":23.88,"out":23.81,"flow":225.21,"Wh":2700, "millis":16019}
  445. **            => "etat=Stop&in=23.88&out=23.81&flow=225.21&Wh=2700&millis=16019"
  446. */
  447. String url(boolean etatOnly) {
  448.   String x;
  449.   x = "etat=";
  450.   x += etatsText[etat];
  451.   if (!etatOnly) {
  452.     x += "&in=";
  453.     dtostrf(tempIn, 3, 2, fBuf);
  454.     x += fBuf;
  455.     x += "&out=";
  456.     dtostrf(tempOut, 3, 2, fBuf);
  457.     x += fBuf;
  458.     x += "&flow=";
  459.     dtostrf(flow(), 3, 2, fBuf);
  460.     x += fBuf;
  461.     x += "&Wh=";
  462.     dtostrf(power(), 3, 2, fBuf);
  463.     x += fBuf;
  464.     x += "&millis=";
  465.     x += millis();
  466.   }
  467.   return(x);
  468. }
  469.  
  470. /*
  471. ** Calcul du débit. Le but est d'avoir un chiifre si il n'y a rien
  472. */
  473. float flow() {
  474.   float tr = sendMeanFlow;
  475.   if (isnan(tr)) {
  476.     tr = 0;
  477.   }
  478.   return(tr);
  479. }
  480.  
  481. /*
  482. ** Calcul de la puissance thermique
  483. **   P (kW) = m (m3/h) * cp * dT * 1.16
  484. **   P (W) = m (L/h) * cp * dT * 1.16
  485. **    avec cp = 1 pour l'eau
  486. */
  487. float power() {
  488.   float wh = 0;
  489.   wh = flow() * 1.0 * (tempIn - tempOut) * 1.16;
  490.   return(wh);
  491. }
  492.  
  493. /*
  494. ** Envoie des données au server
  495. */
  496. boolean sendToServer(String lRoot, String datas) {
  497.   boolean ret = false;
  498.   if (netClient.connect(netServerIP, netServerPort)) {
  499.     netClient.print("GET /");
  500.     netClient.print(lRoot);
  501.     netClient.print("/");
  502.     netClient.print(datas.cstr());
  503.     netClient.println(" HTTP/1.0");
  504.     netClient.println();
  505.     delay(2);
  506.     netClient.stop();
  507.     ret = true;
  508.   }
  509.   else {
  510.     Serial.println("No connection");
  511.   }
  512.   return(ret);
  513. }
  514.  
  515. /*
  516. ** Envoie au terminal série l'adresse du capteur
  517. */
  518. void printAddress(DeviceAddress deviceAddress) {
  519.   for (uint8_t i = 0; i < 8; i++) {
  520.     if (deviceAddress[i] < 16) {
  521.       Serial.print("0");
  522.     }
  523.     Serial.print(deviceAddress[i], HEX);
  524.   }
  525.   Serial.println("");
  526. }
  527.  
  528.  
  529. /*
  530. ****************************************************************************************************
  531. **
  532. **      FIN
  533. **
  534. ****************************************************************************************************
  535. */

Navigation

Mots-clés de l'article