まこと の ブログ

MaKoTo no burogu — Journal de bord…

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

Un anémomètre WiFi -3- … ha bah non, Radio !

Suite de l'étude précédente :

Retour sur l'usage de l'anémomètre à base de NodeMCUv3 LoLin (puce ESP8266).
Après quelques mois d'utilisation que peut-on conclure ?
Et bien il fonctionne bien, mais… Il présente plusieurs défauts :

- Problème de portée, de temps en temps on perd la connexion avec le routeur WiFi.
- Je n'ai pas beaucoup creusé, mais à priori le code que j'ai écrit finit par planter.
- Il consomme beaucoup d'énergie si on envisage de rendre son alimentation autonome (batterie).
- Une seule connexion est possible. C'est à dire que c'est soit le module récepteur qui affiche les données, soit la page web avec le manomètre.
- J'aurais voulu « grapher » des statistiques, et je me voyais embarqué dans du développement complexe et laborieux pour mes maigres compétences.

Sur une suggestion de Chrismart, j'ai donc décidé de revoir le projet dans une version plus fiable et proche de mes attentes.

Fonctionnalités revues et corrigées :

- Exit l'ESP8266 pour la transmission de data, ça va se passer en Radio 433Mhz grâce à un module HC-12 afin de gagner en portée.
- Sans le WiFi qui réclamait une connexion permanente, on va pouvoir mettre les appareils en économie d'énergie lorsqu’il n'y a pas de vent.
- La réception des data, va donc aussi se passer en Radio, pour se voir affichée sur le module d'affichage client avec un rafraîchissement temps réel.
- Dans le boîtier Client, on garde l'ESP8266, qui sera chargé d'envoyer les data à un serveur Web afin de « grapher » des statistiques à l'aide d'une BDD InfluxDB et du grapheur Grafana.
- Ce qui ne change pas, c'est la partie mécanique, vue dans le premier billet.

Anemo_synoptic.svg.png
Nous allons voir tout ça étape par étape.

L'anémomètre, partie émetteur :

J'ai donc câblé un nouveau circuit :
Anemometre02.png
20190802_211343.jpg Matériel requis :

- 1 Arduino Pro Mini 5V.
- 1 plaquette HC-12 et son antenne.
- 1 condensateur électrochimique polarisé de 220µF.
- 1 diode 1N4007.
- 1 résistance 10kΩ.
- 1 Capteur à effet Hall US1881.
- Un ordi avec port USB et le soft Arduino IDE.

Pour permettre au montage de s'intégrer en lieu et place du NodeMCUv3 LoLin , j'ai tout fixé sur un morceau d'époxy.

Édit du 15 mai 2020 !
Électro-Bidouilleur a enfin sorti une vidéo sur le module HC-12 et nous informe que la librairie <SoftwareSerial.h> est à éviter, ce que j'aurais bien voulu savoir à l'époque étant donné que j'ai effectivement rencontré des problèmes de réception. Il faut donc lui préférer la librairie <AltSoftSerial.h>. Je n'ai pas le temps de me pencher dessus, donc j'ai laissé tel quel le code suivant, sur github et en annexe du billet, à vous de changer la librairie.

Le code est aussi documenté ici, et en annexe du billet :

  • Programme pour l’Arduino Pro Mini de transmission :
/*    Arduino Anemometer Radio Transmitter using HC-12    */
    
#include <SoftwareSerial.h>
/****************/
/* DÉCLARATIONS */
/****************/
SoftwareSerial HC12(10, 11); // HC-12 TX Pin, HC-12 RX Pin
// le capteur à effet Hall est connecté à la pin 2 = int0
unsigned long rpmVent = 0;
unsigned long vitVentKMH = 0;
unsigned long dateDernierChangementVent = 0;
unsigned long dateDernierChangementKMH = 0;
float intervalleKMH = 0;

/*********/
/* SETUP */
/*********/  
void setup() {
  Serial.begin(9600);             // Serial port to computer
  HC12.begin(9600);               // Serial port to HC12
  // Pin capteurs
  attachInterrupt(0, rpm_vent, FALLING); 
}

/*************/
/* PROGRAMME */
/*************/
void loop() {
  RemiseZeroVitVentKMH ();
  delay(500);
}

/*************/
/* FONCTIONS */
/*************/
void rpm_vent()   // appelée par l'interruption, Anémomètre vitesse du vent.
{ 
  unsigned long dateCourante = millis();
  intervalleKMH = (dateCourante - dateDernierChangementVent);
  Serial.print ( "intervalle en s : " );
  Serial.println (intervalleKMH/1000); // affiche l'intervalle de temps entre deux passages
  if (intervalleKMH != 0)  // attention si intervalle = 0, division par zero -> erreur
  {
    rpmVent = 60 / (intervalleKMH /1000);  
  }
  vitVentKMH = ( rpmVent + 6.174 ) / 8.367;
  Serial.print ( "vitVentKMH : " );
  Serial.println ( vitVentKMH ); // affiche les rpm  
  Serial.println ( "" );
  HC12.print(char(vitVentKMH)); 
  dateDernierChangementVent = dateCourante;
}

void RemiseZeroVitVentKMH ()
{
  unsigned long dateCouranteKMH = millis();
  if (intervalleKMH == intervalleKMH) // Si ça ne tourne plus (valeur plus mise à jour)
  {  
    float dureeKMH = (dateCouranteKMH - dateDernierChangementKMH);
    if (dureeKMH > 10000) // Si ça ne tourne plus depuis 10 secondes
    {
      Serial.print ( "dureeKMH : " );
      Serial.println ( dureeKMH ); // affiche les rpm  
      vitVentKMH = 0;  // Remsise à zero !
      dateDernierChangementKMH = dateCouranteKMH;    
    }
  }
}

J'ai donc repris la partie rpm_vent() et RemiseZeroVitVentKMH() que j'avais élaboré dans la version WiFi, en ajoutant simplement l'instruction HC12.print(char(vitVentKMH)) afin de transmettre la donnée par le module HC-12.
Et c'est tout !

Le boîtier client, partie récepteur avec affichage :

Voici le montage avec un afficheur LCD standard, plus simple que mon boîtier à base d'afficheurs DLG7137, et qui vous permettra une réalisation aisée et rapide, mais cependant moins classe que l’usine à gaz que j’avais donc monté…
ClientAfficheurLCD_bb.png Matériel requis :

- 1 Arduino Pro Mini 5V.
- 1 plaquette HC-12 et son antenne.
- 1 condensateur électrochimique polarisé de 220µF.
- 1 diode 1N4007.
- 1 afficheur LCD type HD44780 16 ou 20 x 2.
- Un ordi avec port USB et le soft Arduino IDE.

Le code est aussi documenté ici, et en annexe du billet :

  • Programme pour l’Arduino Pro Mini de réception :

Édit du 15 mai 2020 !
Électro-Bidouilleur a enfin sorti une vidéo sur le module HC-12 et nous informe que la librairie <SoftwareSerial.h> est à éviter, ce que j'aurais bien voulu savoir à l'époque étant donné que j'ai effectivement rencontré des problèmes de réception. Il faut donc lui préférer la librairie <AltSoftSerial.h>. Je n'ai pas le temps de me pencher dessus, donc j'ai laissé tel quel le code suivant, sur github et en annexe du billet, à vous de changer la librairie.

/*    Arduino Anemometer Radio Receiver using HC-12 and LCD Module   */

/*  The circuit:
 * LCD RS pin to digital pin 12
 * LCD Enable pin to digital pin 11
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 * LCD VSS pin to ground
 * LCD VCC pin to 5V
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)*/

#include <LiquidCrystal.h>
#include <SoftwareSerial.h>

const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

SoftwareSerial HC12(8, 9); // HC-12 TX Pin, HC-12 RX Pin

/*********/
/* SETUP */
/*********/  
void setup() {
  Serial.begin(9600);             // Serial port to computer
  HC12.begin(9600);               // Serial port to HC12

  lcd.begin(20, 2);
  lcd.setCursor(0, 0);  
  // Print a message to the LCD.
  lcd.print("    Anemometer"); 
  lcd.setCursor(0, 1);  
  lcd.print("    Test");           
  delay(1000); 
  lcd.clear(); 
}

/*************/
/* PROGRAMME */
/*************/
void loop() {
  while (HC12.available()) {      // If HC-12 has data
    int incomingChar = HC12.read();
    Serial.print ( "buffer : " );
    Serial.println (incomingChar); 
    lcd.setCursor(0, 0); 
    lcd.print(incomingChar); 
    lcd.setCursor(4, 0); 
    lcd.print("Km/h");     
  }
}

Pour la réception des données on récupère les caractères avec la variable incomingChar et on l'envoie sur l'écran avec lcd.print.

Le boîtier client, partie récepteur, avec statistiques graphiques :

ClientAfficheurLCD_nodemcu_bb.png Matériel requis :

- 1 NodeMCUv3 LoLin.
- Un ordi avec port USB et le soft Arduino IDE.

  • On conserve ici le même design que précédemment, et on ajoute simplement un NodeMCU (ESP8266) qui va permettre la transmission de donnée via WiFi.

Il est donc chargé d'envoyer les data à un serveur Web afin de « grapher » des statistiques à l'aide d'une base de donnée InfluxDB et du grapheur Grafana.

Grafana est une sorte de CMS web qui permet la visualisation et la mise en forme de données métriques. Il permet de réaliser des graphiques depuis plusieurs sources dont des bases de données de série temporelle (Time Series Database), et c'est InfluxDB qu'on va ici utiliser.
Pour cette partie, il faut disposer d'un serveur web, sur lequel on va installer Grafana et la base de donnée 'InfluxDB''.
Grâce à ce projet, j'ai pu récupérer le bout de code simple qui va permettre à l’ESP8266 d'écrire en base de donnée InfluxDB.
Il faudra donc ajouter ces deux fichiers ESPinfluxdb.cpp et ESPinfluxdb.h au sketch Arduino pour programmer l'ESP8266 du NodeMCU.

  • On donne au programme les paramètres de connexion au WiFi local, les paramètres de connexion à la base de donnée, qu'elle soit dans un réseau privé ou sur une adresse publique avec un nom de domaine associé.

Le code est aussi documenté ici, et en annexe du billet :

  • Programme pour le NodeMCU de réception :

Édit du 15 mai 2020 !
Électro-Bidouilleur a enfin sorti une vidéo sur le module HC-12 et nous informe que la librairie <SoftwareSerial.h> est à éviter, ce que j'aurais bien voulu savoir à l'époque étant donné que j'ai effectivement rencontré des problèmes de réception. Il faut donc lui préférer la librairie <AltSoftSerial.h>. Je n'ai pas le temps de me pencher dessus, donc j'ai laissé tel quel le code suivant, sur github et en annexe du billet, à vous de changer la librairie.

#include "ESPinfluxdb.h"
#include <SoftwareSerial.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>

/****************/
/* DÉCLARATIONS */
/****************/
const char *INFLUXDB_HOST = "domain.org";  // ou ip locale du serveur
const uint16_t INFLUXDB_PORT = 8086;

const char *DATABASE = "AnemoBDD";
const char *DB_USER = "login";
const char *DB_PASSWORD = "motdepasse";

int incomingChar;
int compteur = 1;

SoftwareSerial HC12(D5, D6); // HC-12 TX Pin, HC-12 RX Pin

ESP8266WiFiMulti WiFiMulti;

Influxdb influxdb(INFLUXDB_HOST, INFLUXDB_PORT);

/*********/
/* SETUP */
/*********/ 
void setup() {
  Serial.begin(115200);
  HC12.begin(9600);               // Serial port to HC12
        
  WiFiMulti.addAP("ssid", "password");    // indiquer ici vos paramètres WiFi
  while (WiFiMulti.run() != WL_CONNECTED) {
    delay(100);
  }
  Serial.println("Ready");

  //influxdb.opendb(DATABASE, DB_USER, DB_PASSWORD);
  // Connexion à la base InfluxDB - Connect to InfluxDB database
  while (influxdb.opendb(DATABASE, DB_USER, DB_PASSWORD)!=DB_SUCCESS) {
    Serial.println("Open database failed");
    delay(10000);
  }
}

/*************/
/* FONCTIONS */
/*************/
void ReceiveDataFromRadio() {
  while (HC12.available()) {      // If HC-12 has data
    incomingChar = HC12.read();
//    Serial.print ( "buffer : " );
//    Serial.println (incomingChar); 
  }
}

void SendDataToInfluxdbServer() {
  //Writing data with influxdb HTTP API: https://docs.influxdata.com/influxdb/v1.5/guides/writing_data/
  //Querying Data: https://docs.influxdata.com/influxdb/v1.5/query_language/
 
  // Envoi la vitesse du vent
  dbMeasurement rowAnemo("VitesseVent");
  rowAnemo.addField("VitesseVent", incomingChar);
  Serial.println(influxdb.write(rowAnemo) == DB_SUCCESS ? " - Object write success" : " - Writing failed");
  
  // Vide les données - Empty field object.
  rowAnemo.empty();
}

/*************/
/* PROGRAMME */
/*************/
void loop() {
  ReceiveDataFromRadio();

  if (compteur > 500) { // envoie la data toutes les 5 secondes (10 ms + 500)
    SendDataToInfluxdbServer();  
    compteur = 1;
  }
  else {
    compteur++;
  }
  delay(10);  // refresh la data sur l'afficheur toutes les 10 ms
//  Serial.print ( "compteur = " );
//  Serial.println(compteur);
}

Toujours pareil, c'est la variable incomingChar reçue par le HC-12 qui est envoyé périodiquement à la base de données.

Configuration de la Base de données :
Coté serveur web donc, une fois les logiciels Grafana et InfluxDB installés, on va commencer par créer la base de donnée avec les commandes suivantes.

  • Lancer l’interpréteur de commande d’InfluxDB :
influx
  • Créer la base de donnée AnemoBDD :
create database AnemoBDD
  • Indiquer qu’on veut utiliser cette base :
use AnemoBDD
  • Créer l’utilisateur de la base en spécifiant son mot de passe :
create user login with password 'motdepasse'
  • Donner les droits d’accès complet à l’utilisateur :
grant all on AnemoBDD to login
  • On peut vérifier avec ces commandes, puis quitter :
show databases
show users
quit


Configuration de la Grafana :
Reste à paramétrer Grafana avec la base InfluxDB en source et un tableau de bord qui récupére la donnée rowAnemo, sous la forme qu'on souhaitera voir afficher.

  • Ajouter une source de donnée, choisir la source de type InfluxDB :

grafana01.png grafana02.png grafana14.png

grafana03.png

  • Puis paramétrer les accès à la base InfluxDB :

On indique donc un nom de source, l’URL et le port du serveur InfluxDB, puis les identifiants de la base qu’on a crée auparavant.


  • Ensuite, créer un « tableau de bord » et ajouter une requête « Add Query » :

Choisir la source de donnée qu’on vient de faire, et renseigner les champs avec les valeurs du programme de l’ESP8266.
grafana15.png grafana04.png grafana13.png
Notez que si le NodeMCU est en marche et bien connecté à la base InfluxDB, ces champs proposeront les valeurs automatiquement quand on clique dessus, preuve que tout fonctionne comme prévu.

  • On passe à la partie « Visualization » ou l’on choisis le type « Graph », et on paramètre le graphique comme ceci :

grafana12.png grafana05.png grafana06.png

  • La partie « General » permet notamment de donner un nom au graphique.

  • De la même manière, j’ai ajouté une « Visualization » de type « Gauge » :

grafana07.png grafana08.png grafana09.png

  • Il faut bien penser à utiliser l’icône en forme de disquette pour sauvegarder à chaque étapes…

grafana10.png

Pour finir :

Nous avons donc vu une base de travail que vous pourrez adapter facilement si besoin.

  • Cependant comme j'avais ajouté une fonctionnalité supplémentaire, à savoir :

Un tachymètre qui mesure la vitesse de rotation de l'éolienne, j'ai pas mal dû modifier le code notamment pour envoyer les données en une phrase de data et ensuite bien différencier qu'elle donnée va où…
Ajouté aussi la gestion d'économie d'énergie, qui, dés que l’anémomètre s'arrête de tourner, met en veille le module HC-12, puis l'Arduino, pour être réveillé dés que la rotation reprend sous le vent.

  • Pour cette version donc, je me contente juste de poser le >> code ici << et aussi en annexe du billet.

Ainsi qu'une petite vidéo pour illustrer. J'y tourne mon appareil de test à la main :

Voici les mesures de consommation : Anémomètre/Tachymètre (1 module radio + 2 capteur Hall)
- 45 mA, qui tombent à 9 mA en mode veille.
- 5 mA en veille en dessoudant la LED Power de l'Arduino.
(Déssouder le régulateur ne change pas grand chose).

À suivre…

Commentaires

1. Le vendredi, 30 août 2019, 22:12 par Commender

Salut,

J'aime bien ta réalisation aussi je me permet de te partager une idée qui pourrait simplifier la partie serveur.

J'ai lu ça dans le dernier numéro de Hackable: on stocke les données dans la mémoire SPIFFS de l'ESP et on se sert de celui-ci pour héberger un serveur web basique en local qui envoie une page html avec un script basé sur Chart.js. Le script récupère depuis le navigateur client les données stockées dans un fichier .csv dans la mémoire de l'ESP et trace le graph directement sur l'ordinateur client.

Le principal défaut étant que les données ne sont accessibles qu'en réseau local. La mémoire de l'esp peut bien sur être étendue par une carte SD pour stocker les données sur un plus long terme. C'est plus limité que ton système mais ça simplifierait la partie serveur.

Voilà, c'était une idée comme ça, en passant ;)

2. Le samedi, 31 août 2019, 09:43 par Makoto

Merci ! C'est une possibilité intéressante.
Ça m'aurait été bien utile à l'époque car c'est vers ce genre de chose que j'orientais la partie développement abandonnée que j’évoquais en début de billet.
Cependant mes besoins ont évolués vers quelque chose de plus adapté (besoin d'externaliser les données) et que je maîtrise mieux.

Ajouter un commentaire

Le code HTML est affiché comme du texte et les adresses web sont automatiquement transformées.

Fil des commentaires de ce billet