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
L’interface Grove est à souder soi-même (2 connecteurs RJ11, 4 connecteurs blanc 4 fils et 3 résistances).
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.
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.
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.
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.
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.
Voici donc le schéma qu’il convient de réaliser pour supprimer cet effet 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 !
bonjour
super !! bravo pour votre station météo et le partage !
je démarre la fabrication de la mienne et vais suivre votre base.
j’ai un pblem avec la girouette.
j’essaie de repérer les valeurs en fonction de l’orientation, mais le problème c’est que les valeurs ne sont pas toujours les memes pour une meme direction.
et le 2ème problème, c’est que j’ai des valeurs proches pour l’ouest et le nord. en mettant des fourchettes assez large, le nord et l’ouest sont confondues. et si valeurs ressérés, ca ne marche pas à tous les coups non plus.
exemple : nord 910
ouest 905
et 5 minutes plus tard, les valeurs bougent = nord 905/910/915 et ouest 900/910/920.
du coup, comment pourrais je faire ?
Bonjour,
merci pour le retour ! Normalement la girouette a bien 16 positions avec 16 valeurs assez précises. Vous avez une girouette Lextronic ? Quel câblage avez vous effectué ?
Vous pouvez aussi mesurer à l’ohmmetre chaque position normalement.
Mes valeurs analogiques bougaient de 10/15 max par direction, même si certaines étaient proches.
Partagez votre code de test aussi, peut être il y a qque chose à creuser aussi.
Bonsoir
Pour la girouette, tout est ok. J’ai pris le temps de noter les minis et maxi pour chaque position, et c’est ok !!
Petite question. Le condensateur … vous en mettez 1 sur l’anémomètre et 1 sur le pluvio ? Du coup, avec votre montage condensateur + resistance, vous n’utilisez plus la carte avec les connecteurs rj11 sur laquelle il y a des résistances ?
Bonsoir,
Bonne nouvelle pour les positions de la girouette !
oui, j’ai un montage condo/resistance sur l’anémomètre et 1 sur le pluviomètre. Et le montage est intercalé après les connecteurs RJ11 (que je garde mais pas indispensable, on peut récupérer les 2 fils direct) en amont et avant les connecteurs groove en aval.
Ca fait element -> RJ11 -> montage -> groove -> arduino
ok. Merci !
J’ai mis en route le programme sur une Arduino MKR1200 avec envoi de message toutes les 15 minutes.
Le code est ici :
https://github.com/charlesdego/stationmeteo/blob/master/MKR1200.ino
J’ai un soucis avec l’anémomètre qui s’arrête de temps en temps… Peut etre est ce du au condensateur pas encore installé ?
Du coup, je programme sur une Arduino Uno avec shield Sigfox.
L’anémomètre fonctionne mieux, mais j’ai un soucis avec l’écriture du message Sigfox.
Le code :
https://github.com/charlesdego/stationmeteo/blob/master/meteo2_uno_fx.ino
Pouvez vous me corriger ce dernier code sur la Uno ? Dans le début du fichier, j’ai mis le lien vers la référence du shield pour le programmer.
Bonsoir,
L’anémomètre qui s’arrête c’est bizarre, vous êtes sur que c’est pas l’arduino qui ne récupère pas bien ? Vous avez combien de mètre de fil entre les 2 ? Le condensateur est indispensable pour compter le bon nombre d’impulsion, sinon il en compte 3 ou 4 au lieu d’une à chaque fois et ca peut etre problématique.
pour votre code uno, la ligne 78 est bizarre :
char msg = msg;
pour moi elle ne sert à rien et est source d’erreur car le char est mal déclaré.
Les lignes 212 à 217 sont commentées aussi, vous n’initialisez pas donc msg donc il en manque un bout avant envoi. Vous envoyez toutes les valeurs ? Il faut décommenter les lignes que vous voulez envoyer.
Avec ces 2 corrections, cela devrait mieux marcher (par contre je ne connais pas le module mais ca m’interesse je voulais faire du sigfox ou lora, je suis preneur du retour).
PS : vous avez pris un abonnement sigfox chez qui ?
J’ai trouvé un code qui a l’air correct, je le mettrais en ligne si il valable.
Pour sigfox, on a 1 année gratuite pour l’achat d’une carte arduino MKR1200 ou d’un shield sigfox chez lextronic. Ensuite, c’est 6 euros par an chez sigfox directement en choisissant Belgique comme état… 🙂
Gardez vous le module avec les 3 résistances ? (en plus du condensateur et des résistances ajoutées)
https://www.lextronic.fr/platine-pour-capteur-meteo-57577.html
ou pas ?
charles
Non celle ci n’est vraiment pas obligatoire, je l’ai laissé dans mon projet mais j’en ai pas mis sur mon 2eme pluvio en construction (article à venir).
Merci pour les infos sigfox ca m’intéresse du coup (ainsi que le code si il marche :-p )
Condensateur reçu.
mais je ne comprends rien au branchement.
vous pouvez m’expliquer pour le pluvio par exemple. ?
Bonjour,
Désolé je ne vois que le message maintenant.
J’ai refait un schéma ici : https://www.sla99.fr/wp-content/uploads/2020/06/pluvio.png
Est-ce plus clair ?
attention, pour être en train de faire le meme montage pour l’anémomètre compte 2 impulsions par tour, il faut donc diviser par 2 l’expression de la vitesse du vent ! (J’ai vérifié avec un oscilloscope)
Bonjour Sam,
Merci pour l’info. Je ne l’avais pas constaté lors de mes tests mais ca fausserait drolement le resultat !
Je vais commander un autre exemplaire et valider cela, et le cas échéant modifier mon programme en conséquence !
Merci pour ce feedback precieux !
Bonsoir,
Je suis spéléologue, et l’installation d’une station météo nous permettrait de comprendre certaines interrogations d’un lac souterrain situé à -80 m. Votre démarche nous apporte beaucoup de réponse, principalement dans la programmation. Pour nous, cette station doit être entièrement autonome car sa situation ne permet pas le GSM. L’acquisition des données sera relevé une fois par mois.
Est-il possible de nous guider dans cette étude.
Merci d’avance.
Bonsoir François,
Joli projet que vous avez ! Oui bien sûr on peut échanger sur votre projet si vous le souhaitez.
Je suis curieux de savoir quels capteurs vous souhaitez mettre en oeuvre.
Je vous envoie un mail avec mes coordonnées.
Bonsoir,
Votre anémomètre ne fournit pas deux impulsions par tour?
Sylvain
Je l’avais mesuré à l’ohmmetre et j’en avais bien qu’une par tour
Bonjour, le lien vers le « kit Lextronic Grove Station » est obsolète, le lien du produit de remplacement est le suivant : https://www.lextronic.fr/station-meteo-compatible-arduino-microbit-grove-63660.html.
Ce produit de remplacement est il totalement compatible ?
Merci beaucoup pour votre retour et pour votre projet,
Christophe
Bonjour,
Desole du retard je n’avais pas vu votre commentaire.
Ce kit est en tout point identique au mien donc à mon avis aucun probleme !
Fabien
Bonjour , votre projet est interressant , j’aimerais juste comprendre pourquoi un mega plutot qu’un uno? le nombre d’IO semble suffisant puissance ou memoire de stockage trop faible sur le uno ?
Merci.
Bonjour,
En effet, depuis ce projet, je suis repassé sur un Arduino Uno bien suffisant. Mais à l’époque, la taille du sketch dépassait la taille admissible d’un UNO.
Un peu de ménage m’ont permis de revenir sur une situation acceptable.
Le principe de la station reste identique !
Bonjour, puis-je savoir où mettre les câbles svp ?
Bonjour,
c’est à dire pour les cables ?
Quelle librairie vous utilisez ?
Le code est à dispo sur le site, vous avez tout dedans