まこと の ブログ

MaKoTo no burogu — Journal de bord…

Aller au contenu | Aller au menu | Aller à la recherche

Un anémomètre WiFi -1-

dsc03927.jpg

Récemment on m'a indiqué l'existence d'une plaquette électronique du genre Arduino, mais qui a la particularité de pouvoir « faire du WiFi ».
D'abord dubitatif quant à l'utilité du truc, étant donné que je m'étais très bien passé de la chose jusqu'à présent, le truc est resté en idle dans un coin de mon esprit malade, jusqu'à ressurgir suite à mes derniers travaux sur l'Éolienne du jardin
Hé oui ! Je me suis dit que ce serait pas mal de savoir quelle vitesse de vent serait nécessaire pour pousser sur les ailes et la faire tourner, de savoir à quelle vitesse elle tournait aussi, et de pouvoir ainsi régler la tension du ressort de vitesse de rotation constante, un peu mieux qu'au… pif.

  • J'avais donc une plaquette NodeMCUv3 LoLin (à base de puce ESP8266) sous la main et après quelques tests j'ai constaté que bah c'est comme Arduino, rien de compliqué.
  • Et puis pour faire client ou serveur Web, bah c'était pas comme Arduino… et qu'il faudrait se sortir les doigts…

Oui car on peut servir des pages web, alors on pense assez vite à ordi-phone et une jauge de visualisation.
Enfin en vrai, réflexe électronicien, j'ai tout de suite pensé afficheur à leds, mais récupérer les données via du web… wé, je garde l'idée… Alors :

Pour mon projet final j'aurais besoin d'une plaquette NodeMCU en mode serveur web, perchée sur l'éolienne, pour remonter les mesures de rotation de l’anémomètre (vent) et de l'éolienne (rpm).
Les data seraient consultables via un navigateur sur un ordi ou un ordi-phone, sous forme de jauge de vitesse instantanée.
Elles seraient aussi récupérable pour former des graphiques de statistiques.
Un second NodeMCU avec des afficheurs à leds serait utilisé pour s'affranchir d'un ordi.

  • Bon c'est pas forcément facile à suivre, alors voici un dessin :

anemometre3.png

Simple anémomètre :

  • Bref, pour le moment on va juste fabriquer un anémomètre simple, avec une jauge sur ordi.

(voir même sur internet si on fait le nécessaire pour faire « sortir » les pages web).

Matériel requis :
dsc03947.jpg

- La mécanique imprimée en 3D disponible ici.
- 1 Capteur à effet Hall US1881 (absent de cette photo).
- 2 aimants permanents au néodyme ∅6 mm x 3 mm (absent de cette photo).
- 1 plaquette NodeMCUv3 LoLin.
- 1 résistance 10kΩ.
- 2 roulements à billes : ∅5 int x ∅10 ext x 4 mm.
- 1 tige filetées : ∅5 mm de 10 mm de long.
- 5 écrous de ∅5 mm.
- 3 vis : ∅3 mm de 10 mm de long (tête fraisée).
- 3 vis : ∅4 mm de 12-15 mm de long (tête poêlée).
- Un ordi avec port USB et le soft Arduino IDE.


Compétences requises :

- Électronique.
- Web design (html, css, JavaScript, Json).
Où sinon t'as du temps et l'âme d'un bidouilleur et t'y arriveras !… du coup j'ai appris plein de trucs.


Le montage :

  • Commençons par insérer les écrous dans les logements prévu après avoir percé les opercules (permettant l'impression au dessus des trous sans supports), puis à fermer la structure avec les vis de ∅3 mm.

dsc03944.jpg dsc03946.jpg

  • Insérer un roulement dans son support, puis insérer le support dans le fond.

dsc03935.jpg dsc03934.jpg

  • Préparer la tige filetée avec deux écrous bloqués à 3 mm du bord de la tige. L'idée c'est qu'une fois en place sur le roulement la tige puisse tourner librement.

dsc03936.jpg dsc03937.jpg

  • Ensuite, régler la hauteur du support d'aimants (en gris, aimants pas encore dispo sur la photo) pour qu'il soit à hauteur du logement du capteur Hall (une des petites fentes, capteur pas encore dispo sur la photo). Le NodeMCU se loge simplement à l'endroit prévu.

dsc03940.jpg dsc03941.jpg

  • Voilà, on peut mettre le roulement du haut et fermer le bas avec les vis de ∅4 mm après avoir taraudé les trous de vis. Le socle est donc ici adapté pour s'enficher sur le mât de l'éolienne, en lieu et place du cône que j'avais imprimé alors.

dsc03943.jpg dsc03932.jpg

  • Coller le chapeau à la cyanoacrylate par dessus (après avoir percé l'opercule) puis placer un écrou pas trop bas, et visser le col par dessus après l'avoir taraudé au ∅5 mm, voire même ajouté du vernis/résine de blocage au filetage. Ceci devrait permettre de protéger le boîtier et le roulement de la pluie.

dsc03931.jpg dsc03930.jpg

  • Reste à visser les hélices, et serrer le tout avec un écrou. (Photo en début de billet)



Le schéma :

  • Pas trop compliqué…

Anemometre01_bb.png

Le câblage :

  • C'est facile à câbler… Et il suffit de glisser le capteur à effet Hall dans une des deux fentes prévues. Avec le capteur US1881 il faut placer deux aimants sur le support, un orienté pôle nord, et l'autre pôle sud (cf.datasheet).

dsc03949.jpg dsc03952.jpg

Programmation du NodeMCU :

  • Pour programmer un NodeMCU avec l'Arduino IDE il faudra rajouter le support du module esp8266, voici 3 pages qui vous expliqueront comment faire : Via fais-le-toi-meme.fr ou henrys-bench.

Tout le code de l'anémomètre est téléchargeable ici ou en annexe à ce billet.
Créer un dossier qui contiendra cette arborescence :

Anemometre_esp8266_WifiSVR_SPIFFS_Hall/Anemometre_esp8266_WifiSVR_SPIFFS_Hall.ino
Anemometre_esp8266_WifiSVR_SPIFFS_Hall/data/index.html
Anemometre_esp8266_WifiSVR_SPIFFS_Hall/data/css/style.css
Anemometre_esp8266_WifiSVR_SPIFFS_Hall/data/js/java_vent.js
Anemometre_esp8266_WifiSVR_SPIFFS_Hall/data/js/jquery.min.js
Anemometre_esp8266_WifiSVR_SPIFFS_Hall/data/js/loader.js
  • Ainsi pour programmer la plaquette, il suffira de procéder au téléversement du projet Arduino, ça c'est comme d'habitude avec l'Aruino IDE.
  • Et pour téléverser les fichiers html, css et JavaScript, il faudra cliquer sur Outils et sélectionner Upload Speed : 921600; Ensuite à nouveau Outils et cliquer ESP8266 Sketch Data Upload, ce qui aura pour effet d'immédiatement copier les fichiers contenu dans le dossier data sur la plaquette.

Fonctionnement :
Ensuite ouvrir Outils > Moniteur série , qui devrait afficher l'adresse IP de la plaquette (sinon appuyer sur le bouton Reset), et rendez-vous sur un navigateur avec cette IP en URL et voila !
anemometre.png
C'est une petite entrée en matière intéressante de la conception d'un « appareil connecté », j'ai découvert comment tout ça s'articule…
Plus à l'aise avec l'électronique, je touche mes limites techniques concernant la partie développement web, avec pas mal de méconnaissances du sujet qu'il faut que je travaille (wé j'en suis resté au web 1.0…), en vue dans de prochains billets, d'aborder les divers éléments liés à mes besoins plus spécifiques.

Principe :
L'aimant passe devant le capteur à effet Hall à chaque rotation de l'axe de l'anémomètre, ce qui envoie une impulsion qui est alors réccupérée par le NodeMCU pour être traitée afin de mesurer la vitesse de rotation, puis de la convertir en Km/h. Cette mesure est envoyée au serveur Web sous la forme d'un fichier JSON écrit en zone SPIFFS, qui est mis à jour toutes les secondes (valeur réglable au début du code Arduino)

Présentation du contenu des fichiers :
J'ai commenté assez largement le code, mais n'espérez pas tout comprendre si un des langages vous échappe…

Le fichier JSON ressemble à ceci :

{
  "VitesseVent":"25"
}

Lorsqu'on consulte la page Web, le JavaScript contenant la jauge est appelé et celui-ci récupére la valeur du JSON pour animer l'aiguille et afficher la valeur, toutes les secondes (en adéquation avec le réglage du code Arduino)

  • Le fichier data/js/jquery.min.js est une libraire standard (ou un truc du genre) qui se télécharge sur internet.
  • Le fichier data/js/loader.js est une libraire google (ou un truc du genre) qui se télécharge chez google chart.
google.charts.load('current', {
        'packages': ['gauge']
      });
      google.charts.setOnLoadCallback(drawChart); //  https://developers.google.com/chart/interactive/docs/gallery/gauge

      function drawChart() {    // Fonction principale : 

        // Create and populate the data table.
        var dataGaugeVent = google.visualization.arrayToDataTable([
          ['Label', 'Value'],
          ['Vent', 0],
        ]);

        // formatage avec un suffixe et # pour arrondir
        var formatter = new google.visualization.NumberFormat({
          suffix: ' Km/h',
          pattern: '#'
        });

        // définition des options documentée ici https://developers.google.com/chart/interactive/docs/gallery/gauge
        var options = {
          width: 800, height: 720,
          greenFrom:0, greenTo: 60,   // zones de couleurs
          yellowFrom:60, yellowTo: 80,
          redFrom: 80, redTo: 100,
          majorTicks: ['0', 10, 20, 0, 0, 50, 0, 0, 80, 90, 100], // graduations
          minorTicks: 5, // graduations
          max: 100, min: 0,
          animation: {
            duration: 100,  // vitesse de l'aiguille
            easing: 'linear',   // comportement de l'aiguille
          }
        };

        // init du graphisme
        var GaugeVent = new google.visualization.Gauge(document.getElementById('chart_div_vent'));

        // tracé du graphisme
        GaugeVent.draw(dataGaugeVent, options);
        updateGauge();  // exécute la fontion
        setInterval(updateGauge, 100); // appelle les données de la fonction et définit la vitesse de rafraichissement

        function updateGauge() {     // fonction de mise raffraichissement des données réccupérée dans le fichier json https://www.w3schools.com/jquery/ajax_getjson.asp

          $.getJSON('/mesures.json',

            function(data) {

              $.each(data,

                function(nom, valeur) {

                  dataGaugeVent.setValue(0, 1, valeur); // premier nb pour le N° de la gauge si plusieurs, puis 0 pour modifier le champ label (sinon:1 pour le champ Value), puis la valeur extraite du json
                  GaugeVent.draw(dataGaugeVent, options); // tracé du graphisme
                  formatter.format(dataGaugeVent, 1); // applique le formattage à la seconde collonne du tableau (1) qui correspond à la valeur

                });
            });
        }
      }
  • Le fichier data/css/style.css pour la mise en page :
.container_inner {
   background-color: #555555;
  width: 450px;
  margin-left: -165px;
  padding-left: 60px;
  padding-top: 160px;
  padding-bottom: 160px;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
  • Le fichier data/index.html, où l'on charge les 3 JavaScripts et la feuille de style css. Puis on y appelle le graphisme de la gauge.
<!DOCTYPE html>
<html>
	<head>
		<title>Eolienne</title>
		<link rel="stylesheet" type="text/css" href="css/style.css">
		<script type="text/javascript" src="js/jquery.min.js"></script>
		<script type="text/javascript" src="js/loader.js"></script>
		<script type="text/javascript" src="js/java_vent.js"></script>
	</head>
  
	<body>
		<div class="container_inner">
			<div id="chart_div_vent"></div>
      </div>
	</body>
</html>
  • Le fichier Anemometre_esp8266_WifiSVR_SPIFFS_Hall.ino, qui contient le code C++ type « Arduino », pour mesurer la vitesse de rotation et envoyer les données au serveur Web.
#include <ESP8266WebServer.h>
#include <FS.h>

/****************/
/* DÉCLARATIONS */
/****************/
ESP8266WebServer server ( 80 );  // on instancie un serveur ecoutant sur le port 80
#define pinHall D2  // le capteur à effet Hall est connecté à la pin D2
#define ssid      "xxxx"      // WiFi SSID
#define password  "****"      // WiFi password
int dureeMesVitVent = 1000; // en ms, durée de la mesure. Choisir un multiple de 1000 pour le calcul de la vitesse du vent.
volatile int rpmcount = 0;
int rpm = 0;
volatile float vitVentMS = 0;
volatile float vitVentKMH = 0;
unsigned long lastmillis = 0;

/*********/
/* SETUP */
/*********/
void setup() {
  Serial.begin ( 115200 );  // init du mode débug
  // Connexion au WiFi
  WiFi.begin ( ssid, password );
  // Attente de la connexion au réseau WiFi / Wait for connection
  while ( WiFi.status() != WL_CONNECTED ) {
    delay ( 500 ); 
    Serial.print ( "." );
  }
  // Connexion WiFi établie
  Serial.println ( "" );
  Serial.print ( "Connected to " ); Serial.println ( ssid );
  Serial.print ( "IP address: " ); Serial.println ( WiFi.localIP() );

  // Montage de la zone mémoire SPIFFS
  if (!SPIFFS.begin()) {
    Serial.println("SPIFFS Mount failed");
  } 
  else {
    Serial.println("SPIFFS Mount succesfull");
  }
  delay(50);

  // Pin capteurs
  attachInterrupt(pinHall, rpm_vent, FALLING); 

  // Pages web du serveur
  server.serveStatic("/js", SPIFFS, "/js");       // dossier js qui contient les fichiers JavaScripts
  server.serveStatic("/css", SPIFFS, "/css");     // dossier css qui contient les fichiers css
  server.serveStatic("/", SPIFFS, "/index.html"); // racine du serveur, pointe l'index.html
  server.on("/mesures.json", sendMesures);        // écrit le fichier json à l'appel de la fonction
  server.begin();                                 // démarre le serveur
  Serial.println ( "HTTP server started" );
}


/*************/
/* FONCTIONS */
/*************/
void rpm_vent(){  // appelée par l'interruption
  rpmcount++;
}

void sendMesures() {  // appelée par le serveur web
  String json = "{"VitesseVent":"" + String(vitVentKMH) + ""}"; // prépare et formate la valeur pour le fichier jspn
  server.send(200, "application/json", json);               // écrit dans le valeur dans le fichier json
  //Serial.println("Mesures envoyees");
}

void getVitesseVent() {   // appelée par la boucle programme
  if (millis() - lastmillis >= dureeMesVitVent ){ 
    detachInterrupt(pinHall);   // relâche l'interruption

    rpm = rpmcount * ( 60 / ( dureeMesVitVent / 1000 ) ); 
    
    if ( rpm > 0 ) {    // calcul pour calibration de l'anémométre (par relevé de mesure à diverses vitesses en voiture à défaut de soufflerie)
      vitVentKMH = ( rpm + 6.174 ) / 8.367;
      vitVentMS = ( ( ( rpm + 6.174 ) / 8.367 ) * 1000 ) / 3600; 
    } else {
      vitVentKMH = 0;
      vitVentMS = 0;
    }
    Serial.print("vitVentKMH : "),
    Serial.println(vitVentKMH);

    rpmcount = 0;           // Redémarre le compte tour
    lastmillis = millis();  // et réinitialise le chrono
    attachInterrupt(pinHall, rpm_vent, FALLING); // Rélance l'interruption du compte tour
  }
}


/*************/
/* PROGRAMME */
/*************/
void loop() {
  server.handleClient();  // à chaque iteration, on appelle handleClient pour que les requetes soient traitees
  getVitesseVent();
  delay(10);
}

Projet inspiré de celui-ci :
https://projetsdiy.fr/projet-diy-anemometre-girouette-objet-connecte-esp8266/
https://projetsdiy.fr/esp8266-web-serveur-partie5-gauges-graphiques-google-charts/#top_ankor

À Suivre…

Ajouter un commentaire

Les commentaires peuvent être formatés en utilisant une syntaxe wiki simplifiée.

Fil des commentaires de ce billet