3. Mesurer la pluie

station

Fig. 3.1 Station météorologique autonome.

3.1. Introduction

Le projet décrit ici vise à développer une station météorologique à faible coût avec les propriétés suivantes.

  • La station est prévue pour mesurer les précipitations, la température, l’humidité et la pression,

  • elle doit être alimentée par l’énergie solaire,

  • elle doit stocker les données sur une carte SD

  • elle doit capturer le temps de bascule de l’auget du pluviomètre et non le nombre de bascules pendant une période donnée (ce que font presque tous les pluviomètres).

Les codes sont accessibles sur Github:

3.2. Pluviomètre à auget

3.2.1. Principe

reed

Fig. 3.2 Interrupteur ILS situé sous les augets (en blanc). On voit l’axe de bascule des augets ainsi que l’aimant en noir au second plan

Les instruments les plus courant de suivi des précipitations aujourd’hui sont des pluviomètres à auget basculeur. Un entonnoir de diamètre fixe collecte les précipitations qui s’accumulent dans un ensemble composé de deux augets positionnés sur une axe de bascule horizontal. La pluie s’accumule dans une auget qui, quand il est plein bascule et laisse la place au second auget et ainsi de suite. Lors de chaque bascule un aimant attaché au système des deux augets effectue un mouvement pendulaire et passe devant un interrupteur à lames (ILS ou Reed switch). Celui-ci se ferme alors un cours instant. Si l’interrupteur est connecté à un circuit électrique il est alors possible de détecter la bascule lors de la fermeture du circuit.

La précision d’un pluviomètre à auget dépend de plusieurs facteurs:

  • des facteurs externes sur lesquels ne porte pas cet article (le vent étant le plus important d’entre eux),

  • les limites physiques de l’appareil (volume des augets, diamètre des orifices de collecte),

  • le mode de comptage des bascules.

3.2.2. Limites physiques de mesures:

Une vis permet de régler la bascule des augets de façon empirique. En testant le volume avec une seringue, les augets ont été réglés pour basculer pour un volume de 10 +/- 1 ml de précipitation ce qui, connaissant le diamètre de 20.5cm de l’entonnoir (mesuré au pieds à coulisse. vendu normalement pour 8 » soit 20.32cm), correspond à une précipitation de 0.30 +/- 0.03 mm . Confortablement au dessus de ce qui est vendu.

La limite haute de mesure de l’appareil correspond à 1 basculement par seconde. Au delà de cette limite l’eau commence à s’accumuler dans l’entonnoir. La limite temporelle de mesure de l’horloge RTC (Real Time Clock) de l’Arduino étant de 1s, d’une certaine façon, cela tombe assez bien :).

Au dessus de 0.30 mm/s de précipitation le pluviomètre sature donc. Ce n’est pas forcément très grave car cela correspond tout de même à une précipitation de 1000 mm/h ce qui est plutôt rare…

Ceci étant dit lors des très gros orages de l’été 2022 nous avons enregistré pendant une très courte durée un basculement toutes les 4s soit tout de même 200 mm/h.

3.2.3. Choix du mode de comptage des bascules

Presque toutes les stations comptent le nombre de bascules sur un intervalle de temps régulier, entre 1mn et 1h en moyenne que l’on peut régler. Plus l’intervalle est petit plus la mesure sera précise mais cela a un coût en terme de consommation d’énergie et de mémoire. Une minorité de système proposent d’enregistrer non pas un nombre de bascule mais le temps de chaque bascule individuelle.

La Fig. 3.3 montre les raisons qui devraient en toute logique pousser à choisir la seconde solution. Le 16 Août 2022 a eu lieu un très gros orage à Paris. Entre 35 et 40 mm de pluie se sont abattus en moins de 2h. L’enregistrement des basculements de l’auget a permis de mettre en évidence des pointes de précipitations à ~200mm/h soit un basculement toutes les 4 secondes environ. Si à partir de ces mesures on reconstitue la forme que prendrait le signal si on effectuait des comptages sur des intervalles de temps fixes, on voit que seules des mesures toutes les minutes permettent d’approcher la précision de l’enregistrement brut sans toutefois l’égaler.

orage1608

Fig. 3.3 Orage du 16 Août 2022 à Paris. Comparaison entre le signal brut et le signal échantillonné à trois temps classiques: 1H, 5mn et 1mn.

La Fig. 3.4 montre trois enregistrements de l’orage du 16 août effectués en trois localités différentes: à l’IPG dans le 5ème, au bâtiment Lamarck B de l’université dans le 13ème, enfin par la station météo de saint Germain des Prés dans le 6ème. On retrouve bien globalement la même structure entre l’IPG et Lamarck avec deux ondées, la première entre 15h45 et 16h45, la seconde entre 16h45 et 17h15. L’enregistrement de Lamarck qui correspond à un comptage sur 5 minutes donne des valeurs d’intensités plus faible que celui de l’IPG et est donc moins précis. on ne voit pas en particulier que les pics de précipitations sont beaucoup plus importants lors de la seconde ondée et que celle-ci se décompose elle-même en deux événements.

Le signal de Saint Germain est lui assez différents. La première ondée est plus courte, suivie d’une demi-heure de faibles précipitations avant le seconde ondée dont on voit les deux temps. Comme prévu, la période de comptage plus courte (1mn) permet d’enregistrer des intensités plus fortes sans atteindre les valeurs mesurées à l’IPG. Enfin on note un défaut des comptage sur de courtes période, durant la phase de faible précipitations certaines minutes sont sans bascule et donnent une intensité nulle alors qu’il pleut. On voit donc ici qu’un comptage de bascules induit l’apparition d’un seuil de mesures ici il est de 0.3 mm/mn ou 0.005 mm/h. Un comptage du temps de bascule permet de résoudre ce problème car l’intervalle de temps de calcul de l’intensité correspond au temps séparant deux bascules successives. Ce mode de comptage revient en théorie à dire que l’intensité n’est jamais nulle. C’est faux bien sur mais la décroissance de l’intensité est en 1/t et très rapidement les intensité « mesurées » deviennent si faibles qu’on peut les négliger. L’idéal serait de disposer d’une mesure du temps de bascule associée à un capteur permettant de savoir quand celle-ci débute et fini. Nous n’en sommes pas là.

orage1608_comp

Fig. 3.4 Orage du 16 Août 2022 à Paris. Comparaison entre les mesures effectuées par trois instruments: le pluviomètre de l’IPG qui enregistre les bascules, un pluivomètre sur le toit du bâtiment Lamarck B qui compte le nombre de bascule toutes les 5 mn, le pluviomètre de la station météo de Saint Germain des Prés qui compte les bascules toutes les minutes.

3.3. La station

3.3.1. Coût

Le pluviomètre que j’ai acheté est inutilement cher (400€) car il intègre un enregistreur électronique que je ne souhaite pas utiliser ici pour plusieurs raisons. L’électronique n’inclue pas une alimentation à l’énergie solaire et elle doit être utilisé avec un programme Windows ridiculement cher (100 €) pour récupérer les données. Enfin son mode d’enregistrement des pluies est limité comme nous venons de le discuter. Des versions «nues» sont disponibles (voir Rainwise par exemple).

Tab. 3.1 Matériel

Partie

Prix

Pluviomètre à auget

100€

Capteur d’environnement Adafruit ADA3660 construit autour d’un BME680 captant Température, humidité, pression et teneur en gaz

27€

Panneau solaire 10W SOL10P

37€

Batterie plomb 12V, 5.4Ah

29€

DFRobot Tournesol 3.3/5/9/12 DFR0535 pour gérer le panneau solaire et la batterie

32€

Logement pour ADA par TFA Dostman

18€

Boite pour l’électronique

25€

Total

268€

In fine nous économisons ~ 150€ par rapport à un pluviomètre classique. Et pour ce prix, nous avons l’enregistrement du temps des événements pluviométriques (basculement de l’auget), de la température, de la pression, de l’humidité, d’un contenu en gaz et de l’enregistrement autonome de la carte SD…

Cela reste cher me direz-vous ? oui mais toutes les stations de moins de 100€ présentent deux limitations majeures: la mesure des précipitations présente la limite déjà évoquée, elles ne permettent pas un enregistrement simple sur carte SD ou sur PC mais passent forcément soit pas un service internet le plus souvent propriétaire, soit par une console bluetooth.

Seule la station fabriquée par Shenzhen electronics et vendue par les magasins d’éléctronique pour Arduino (https://www.gotronic.fr/art-jeu-de-capteurs-meteo-33052.htm) permet de faire ce que nous venons d’expliquer. Elle comprend un pluviomètre, une girouette et un anémomètre. Cependant son pluviomètre n’est pas standard. Il est petit et présente une forme rectangulaire.

3.3.2. Électronique

  • Une carte Arduino Uno Rev 3

  • Un module RTC pour la mesure du temps

  • Le pluviomètre à auget relié au port numérique 2 qui permet de remonter les interruptions. J’ajoute un condensateur et une résistance de pullup.

  • Un shield SD pour stocker les données

  • un chargeur solaire connecté à la batterie au plomb et à l’Uno.

  • Une batterie au plomb 12v 5Ah.

boite

Fig. 3.5 Boitier contenant l’électronique.

3.3.3. Code de contrôle complet

le code et les explications peuvent-être téléchargées sur Github. Vous y trouverez en outre la structure de la base de données ainsi que des codes python pour le chargement des données et des exemples d’analyse.

//SD Card lib
#include <SPI.h>
#include <SD.h>

//RTC lib
#include <Wire.h>
#include <RTClib.h>
#define ADRESSE_I2C_RTC 0x68 // RTC card address
DS1307 rtc;

//BME680 lib
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"
#define SEALEVELPRESSURE_HPA (1013.25)
#define ADRESSE_I2C_BME 0x77 // BME card address

Adafruit_BME680 bme;


const int chipSelect = 4; // SD card on Uno
const byte pluvio = 2;  // pullup for pluviometer on D2
volatile int pcount = 0;
volatile long t0 = 0;

void setup()
{
  Serial.begin(9600); // pour affichage dans le moniteur série

  /*
   * Pluvio
   */
  pinMode(pluvio, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(pluvio), pCount, FALLING);

  while (!Serial) {
   delay(100) ; // wait for serial port to connect. Needed for native USB port only
  }

  Wire.begin();
  /*
   * RTC
   */

  Wire.beginTransmission(ADRESSE_I2C_RTC);
  Serial.println(F("RTC Connection"));

  while (!rtc.begin()){
      Serial.println("Attente module HTR");
      delay(1000);
  }

  //rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  //Serial.println("Horloge mise à jour");
  Wire.endTransmission();
  delay(1000);

  /*
   *  BME
   */
  Wire.beginTransmission(ADRESSE_I2C_BME);
  Serial.println(F("Initializing BME680..."));

  if (!bme.begin()) {
    Serial.println("Could not find a valid BME680 sensor, check wiring!");
    while (1);
  }

  // Set up oversampling and filter initialization
  bme.setTemperatureOversampling(BME680_OS_8X);
  bme.setHumidityOversampling(BME680_OS_2X);
  bme.setPressureOversampling(BME680_OS_4X);
  bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
  bme.setGasHeater(320, 150); // 320*C for 150 ms


  Wire.endTransmission();
  delay(1000);

  /*
   * SD Card
   */

  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    //while (1);
  }
  else {
    Serial.println("card initialized.");
  }

  delay(1000);
}

void loop()
{

/*
 * Get time
 */
  Wire.beginTransmission(ADRESSE_I2C_RTC);
    DateTime now = rtc.now();
  Wire.endTransmission();
  delay(10);

 /*
  * Did it rain ?
  */
 if (pcount > 0){

    Serial.print(F("p,"));
    Serial.print(now.year());
    Serial.print(F(","));
    Serial.print(now.month());
    Serial.print(F(","));
    Serial.print(now.day());
    Serial.print(F(","));
    Serial.print(now.hour());
    Serial.print(F(","));
    Serial.print(now.minute());
    Serial.print(F(","));
    Serial.print(now.second());
    Serial.print(F(","));
    Serial.print(pcount);
    Serial.print("\n");

   if (SD.begin(chipSelect)){

     File dataFile = SD.open("DATALOG.TXT", FILE_WRITE);

     // if the file is available, write to it:
     if (dataFile) {
        dataFile.print(F("p,"));
        dataFile.print(now.year());
        dataFile.print(F(","));
        dataFile.print(now.month());
        dataFile.print(F(","));
        dataFile.print(now.day());
        dataFile.print(F(","));
        dataFile.print(now.hour());
        dataFile.print(F(","));
        dataFile.print(now.minute());
        dataFile.print(F(","));
        dataFile.print(now.second());
        dataFile.print(F(","));
        dataFile.print(pcount);
        dataFile.print("\n");
        dataFile.close();

     }
     // if the file isn't open, pop up an error:
     else {
       Serial.println("error opening DATALOG.TXT");
     }
   }
   else{
    Serial.println("No card available. Loosing data");
   }

  pcount=0;
  delay(500);
 } // end pluvio

   /*
   * Every 300s store a weather measurement
   */

  if (abs(now.unixtime()-t0) >= 300){

      Wire.beginTransmission(ADRESSE_I2C_BME);
      bme.performReading();
      Wire.endTransmission();

        Serial.print(F("w,"));
        Serial.print(now.year());
        Serial.print(F(","));
        Serial.print(now.month());
        Serial.print(F(","));
        Serial.print(now.day());
        Serial.print(F(","));
        Serial.print(now.hour());
        Serial.print(F(","));
        Serial.print(now.minute());
        Serial.print(F(","));
        Serial.print(now.second());
        Serial.print(F(","));
        Serial.print(bme.temperature);
        Serial.print(F(","));
        Serial.print(bme.pressure);
        Serial.print(F(","));
        Serial.print(bme.humidity);
        Serial.print(F(","));
        Serial.print(bme.gas_resistance);
        Serial.print("\n");

     if (SD.begin(chipSelect)){

       File dataFile = SD.open("DATALOG.TXT", FILE_WRITE);
      if (dataFile) {
         // if the file is available, write to it:
        dataFile.print(F("w,"));
        dataFile.print(now.year());
        dataFile.print(F(","));
        dataFile.print(now.month());
        dataFile.print(F(","));
        dataFile.print(now.day());
        dataFile.print(F(","));
        dataFile.print(now.hour());
        dataFile.print(F(","));
        dataFile.print(now.minute());
        dataFile.print(F(","));
        dataFile.print(now.second());
        dataFile.print(F(","));
        dataFile.print(bme.temperature);
        dataFile.print(F(","));
        dataFile.print(bme.pressure);
        dataFile.print(F(","));
        dataFile.print(bme.humidity);
        dataFile.print(F(","));
        dataFile.print(bme.gas_resistance);
        dataFile.print("\n");
        dataFile.close();

      }
       // if the file isn't open, pop up an error:
       else {
         Serial.println("error opening DATALOG.TXT");
       }
     }
     else{
      Serial.println("No card available. Loosing data");
     }

     t0 = now.unixtime();

  } // end bme measurements


} //end void




void pCount()
{

  static unsigned int ti = 0;

  unsigned int t = millis();

  if (t-ti > 50){
    pcount++;
    ti = t;
  }

}

Dernière modification le 2023-11-27