Projet Station Meteo Pro #2 : les capteurs météo

Rentrons dans le vif du sujet et commençons à explorer les différents capteurs qui vont composer la station. Focus sur les éléments Lextronic et leur intégration arduino : anémomètre, girouette, pluviomètre.

Présentation du kit

Je suis parti sur le kit Lextronic Grove Station, incluant :

  • un anémomètre, pour mesurer la vitesse du vent
  • une girouette, pour mesurer la direction du vent
  • un pluviomètre, pour mesurer la quantité de pluie tombée
  • une interface Grove
Le kit Lextronic, image Lextronic (c)

L’interface Grove est à souder soi-même (2 connecteurs RJ11, 4 connecteurs blanc 4 fils et 3 résistances).

Image Lextronic (c)

Il va permettre ensuite de se raccorder à un module SLD01099P, qui lui sera par dessus l’arduino. Ce module va permettre de raccorder via l’interface grove les différents éléments sans avoir un câblage avec des sucres partout pour brancher les alimentations par exemple. Voici un rendu à blanc de ce que cela donne, avouez que c’est plutôt sexy.

Module SLD01099P
Le module SDP sur l’arduino mega
La platine Grove qui relie les modules météo en RJ11

Fonctionnement des modules

L’anémomètre

L’anénomètre, à brancher sur une des prises digitales du module SLD, se comporte de la manière suivante : un ILS (Interrupteur à Lame Souple) se ferme à chaque tour de roue complet des ailettes. Le jeu va donc consister à compter le nombre de tour en un temps donné pour déduire la vitesse du vent.

Pour effectuer le premier test, j’ai pris le bout de code qui est sur le site Lextronic et fait tourner les ailettes pour vérifier les passages : la led de l’arduino s’allume et s’éteint à chaque tour. Premier test OK !

void setup() {
pinMode(13, OUTPUT);
pinMode(4, INPUT);
}
// Boucle principale:
void loop() {
int BP = digitalRead(4); // Lecture du capteur
if (BP == LOW) {
digitalWrite(13, HIGH); // Allume la Led
}
else {
digitalWrite(13, LOW); // Eteind la Led
}
} 

La girouette

La girouette se branche elle sur un port analogique. La girouette génère une valeur de la tension (générée par la variation de la résistance de la girouette). Elle dispose de 16 positions intermédiaires permettant de repérer 16 positions sur la rose des vents.

Rose des vents 16 positions

Il sera alors facile de déterminer, en fonction de la valeur la position de la girouette. Le code ci dessous va afficher la valeur convertie (entre 0 et 1023).

void setup() {
Serial.begin(9600);
}
void loop() {
int sensorValue = analogRead(A1);
Serial.println(sensorValue);
delay(100);
}

Le pluviomètre

Le pluviomètre se branche aussi sur un port digital. Comme l’anémomètre, il dispose d’un ILS qui se ferme lors de la bascule de l’auget.

fonctionnement d’un pluviomètre à augets basculants

On comptera alors le nombre de passage en un temps donné pour déterminer la pluie tombée. Le constructeur nous donne l’info suivante : 1 bascule = 0,2794mm de pluie. Le code ci dessous permet de faire clignoter la led de l’arduino à chaque passage.

void setup() {
pinMode(13, OUTPUT);
pinMode(2, INPUT);
}
// Boucle principale:
void loop() {
int BP = digitalRead(2); // Lecture du capteur
if (BP == LOW) {
digitalWrite(13, HIGH); // Allume la Led
}
else {
digitalWrite(13, LOW); // Eteind la Led
}
} 

Problème : ca compte plus que ca devrait !

En effet, vous vous apercevrez assez vite que pour un passage d’ILS, la LED clignote plusieurs fois. Et c’est normal ! C’est l’effet rebond de l’arduino. Lorsque l’on appuie 1 fois, en fait on a un état instable avant d’avoir la valeur haute.

source : http://arduino.blaisepascal.fr/le-bouton-poussoir/

Pour corriger cela, le plus simple est de faire un montage à base d’un condensateur (non polarisé 1000pF pour moi) et d’une résistance (1kohm pour moi). Ce montage va permettre de lisser le rebond et de n’avoir qu’un seul changement d’état (au lieu de n durant la phase). On va donc pouvoir compter correctement le nombre de fermeture d’ILS et avoir des valeurs fiables.

source : http://arduino.blaisepascal.fr/le-bouton-poussoir/

Voici donc le schéma qu’il convient de réaliser pour supprimer cet effet rebond.

Schéma de l’anti-rebond

Et voici ce que cela donne en vrai sur la platine

Conseil : je vous conseille d’acheter des cordons grove que vous couperez pour faire des raccords de montage.

J’ai donc comme cheminement : anemometre -> montage anti rebond -> platine grove -> platine SDP -> arduino

Interruptions

Ca y est, je sais compter comme il faut mes impulsions. Mais comment faire pour compter des impulsions, pendant que l’arduino va continuer ses traitements … ? En passant par les interruptions de l’arduino.

Elles permettent de faire un traitement court tout en continuant d’exécuter le programme courant.

Sur l’arduino (uno et méga), les interruptions sont situées sur les pin D2 (interruption 0) et D3 (interruption 1). On raccordera donc le pluviomètre et l’anémomètre sur ces pins là.

On commence donc par définir nos 2 pins d’interruption dans le programme et les deux compteurs qui s’incrémenteront à chaque passage. Noter que les variables d’interruption doivent être ‘volatile’.

#define ANEMOMETRE  1   //pin D3, interruption n°1
#define PLUVIOMETRE 0   //pin D2, interruption n°0
volatile unsigned int countAnemometre = 0;  
volatile unsigned int countPluviometre = 0; 

Puis, dans le setup, il nous faut déclarer les deux interruptions. Le premier paramètre est le numéro de l’interruption. Puis, le deuxième sera le nom de la fonction chargée de traiter l’interruption. Le troisième paramètre est le choix du front de déclenchement : ici on prend RISING, c’est à dire montant.

void setup()
{
...
  attachInterrupt(PLUVIOMETRE,interruptPluviometre,RISING) ;
  attachInterrupt(ANEMOMETRE,interruptAnemometre,RISING) ;
...
}

Puis il faut donc décrire les deux fonctions d’interruptions :

/* 
 *  Fonction d'interruption de l'anémomètre qui incrémente un compteur à chaque impulsion
 */
void interruptAnemometre(){
  countAnemometre++;
}

/* 
 *  Fonction d'interruption du pluviomètre qui incrémente un compteur à chaque impulsion
 */
void interruptPluviometre(){
  countPluviometre++;
}

Il est alors facile dans le programme principal d’afficher les compteurs respectifs.

Pour la girouette, c’est un peu plus compliqué. Il faut associer un tableau de valeur à la valeur analogique retournée, puis définir l’angle associé. Concrètement, le nord (N) = 0°, le nord-nord-est = 22,5°, etc … Il faut donc mesurer à la main les 16 valeurs analogiques et faire une fonction de correspondance.

PS : le N et le S sont inscrits sur la girouette, il faut donc bien associer les valeurs à ces repères (important pour la suite).

PS2 : les valeurs bougent de 1 ou 2, le programme prend donc des tranches de 10 valeurs pour définir l’angle.

/* 
 *  Fonction qui converti en angle la valeur analogique renvoyée par l'arduino (valeurs fixes)
 *  RETURN : angle en degré
 */
float getGirouetteAngle(int value){
  float angle = 0;
  if (value > 280 && value < 290) angle = 180;
  if (value > 240 && value < 250) angle = 202.5;
  if (value > 628 && value < 636) angle = 225;
  if (value > 598 && value < 606) angle = 247.5;
  if (value > 940 && value < 950) angle = 270;
  if (value > 824 && value < 832) angle = 292.5;
  if (value > 884 && value < 892) angle = 315;
  if (value > 700 && value < 710) angle = 337.5;
  if (value > 784 && value < 792) angle = 0;
  if (value > 402 && value < 412) angle = 22.5;
  if (value > 458 && value < 468) angle = 45;
  if (value > 78 && value < 85)   angle = 67.5;
  if (value > 88 && value < 98)   angle = 90;
  if (value > 60 && value < 70)   angle = 112.5;
  if (value > 180 && value < 190) angle = 135;
  if (value > 122 && value < 132) angle = 157.5;
  return angle;
}

Concrètement, comment je mesure ?

L’anémomètre

Pour l’anémomètre, je mesure le nombre de tour pendant 3 secondes. Puis, pour trouver la vitesse, il faut multiplier le nombre de tour par la circonférence du cercle décrit par les ailettes de l’anémomètre en mètres (2 x Pi x rayon). On aura la vitesse en m/s. On la divise par 3 (pour l’avoir sur 1 sec) et je multiplie par 3,6 pour l’avoir en km/h. Le rayon des ailettes fait 7 cm.

Ensuite, je mesure toutes les 3 secondes cette valeur et je la stocke en cumulé (plus simple que de gérer un tableau de valeur) dans une variable (avec le nombre d’itérations). Au bout de 1 min, je divise le nombre cumulé par les itérations pour avoir le vent moyen sur 1 min. Je stocke aussi la valeur maxi de la minute, qui deviendra la rafale maxi sur 1 min.

Cela permet de pouvoir avoir les valeurs de vent avec une résolution de 3 sec, ce qui permet de ne rater aucune rafale. Je ne détaillerais en revanche pas la gestion du temps avec millis.

#define PI        3.1415
#define RAYON     0.07  //rayon en mètre de l'anémomètre en mètre
...
unsigned long previousMillis=   0;
unsigned long previousMillis2=  0;
unsigned long delaiAnemometre = 3000L;    //3 secondes
unsigned long delaiProgramme =  60000L;   //60 sec
...
float gust(0);        //vent max cumulé sur 1 min
float wind(0);        //vent moyen cumulé sur 1 min
int nbAnemo = 0;      //nb d'occurence de mesure Anemo
float vitesseVent(0); //vent moyen cumulé sur 1 min
...
void loop(){    
  ...
  unsigned long currentMillis = millis(); // read time passed
//Récupération des infos de l'anémomètre et girouette toutes les 3 sec
  //Enregistrement cumulé des valeurs
  if (currentMillis - previousMillis > delaiAnemometre){
    previousMillis = millis();
    vitesseVent = (PI * RAYON * 2 * countAnemometre)/3*3.6; //3 = durée de prise de mesure (3sec)
    
    if(vitesseVent>gust) gust = vitesseVent;
    wind += vitesseVent;
    nbAnemo++;
    countAnemometre = 0;
    Serial.print("Vent:");
    Serial.println(vitesseVent); 
    ...
  }
  //Toutes les minutes, compilation des valeurs et envoi au serveur  
  if (currentMillis - previousMillis2 > delaiProgramme){
    previousMillis2 = millis();
    float avgwind = wind / nbAnemo;
    ...
    Serial.print("Wind AVG : ");
    Serial.println(avgwind);
    Serial.print("Gust : ");
    Serial.println(gust);
    ...
    //RAZ des compteurs qui ont servi a calculé les valeurs moyennes sur 1 min
    wind = 0;
    gust = 0;
    nbAnemo = 0;
  }
}

La girouette

Comme pour l’anémomètre, on va lire la valeur de la position toutes les 3 secondes, on la convertira en angle et on va l’ajouter dans une variable cumulée. On divisera la valeur obtenue par le nombre d’occurrence pour obtenir une direction moyenne sur 1 min.

float gir(0);         //direction moyenne de la girouette sur 1 min (en degrés)
int nbGir = 0;        //nb d'occurence de mesure Anemo
...
void loop(){  
  //Récupération des infos de l'anémomètre et girouette toutes les 3 sec
  //Enregistrement cumulé des valeurs
  if (currentMillis - previousMillis > delaiAnemometre){
    int gdir = analogRead(GIROUETTE);
    gir += getGirouetteAngle(gdir);
    nbGir++;
    Serial.print("#");
    Serial.println(nbGir);
  }
  //Toutes les minutes, compilation des valeurs et envoi au serveur  
  if (currentMillis - previousMillis2 > delaiProgramme){
    previousMillis2 = millis();
    ...
    float avggir = gir / nbGir;
    Serial.print("Girouette : ");
    Serial.println(avggir);    
    ...
    //RAZ des compteurs qui ont servi a calculé les valeurs moyennes sur 1 min
    gir = 0;
    nbGir = 0;
  }
}

Pluviomètre

Pour la pluviomètre, étant donné que nous stockons le compteur dans une variable, on va lire directement le compteur toutes les minutes, et afficher sa valeur. On remet ensuite à zéro et c’est reparti pour un tour.

#define VALEUR_PLUVIOMETRE 0.2794 //valeur en mm d'eau à chaque bascule d'auget
...
float pluvio1min(0);  //pluie sur 1 min
...
void loop(){
  //Toutes les minutes, compilation des valeurs et envoi au serveur  
  if (currentMillis - previousMillis2 > delaiProgramme){
    previousMillis2 = millis();
    pluvio1min = countPluviometre*VALEUR_PLUVIOMETRE;
    countPluviometre = 0;
    ...
  }
}
    

Conclusion

On voit rapidement que ce n’est pas si simple que de mesurer une valeur au bout d’un fil, pas mal d’étapes sont nécessaires pour arriver à une solution fiable. J’ai tâtonné pas mal avant d’arriver à ce résultat, mais j’en suis content ! Le prochain article sera sur le capteur de température BME280 !

25 Comments

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.