まこと の ブログ

MaKoTo no burogu — Journal de bord…

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

Un Anémomètre Radio Multifonction -4-

Suite des études précédentes : Anémomètre et Monitoring.

À ce stade, vu tous mes bidules radio, il serait légitime de se demander pourquoi avoir 2 ou 3 appareils différents (l'un pour surveiller le vent, un pour la rotation de l'éolienne et un autre pour la charge de la batterie).
En fait lors du développement il est naturel d'avancer par étape en ajoutant peu à peu des fonctions, cette suite de billet n'en est finalement que le reflet.

Il est maintenant temps de fusionner tout ça !

  • Cette fois donc, l'appareil sera chargé de récupérer les 4 informations que sont la vitesse du vent, la rotation de l'éolienne, l'énergie produite par la génératrice, et l'état de charge de la batterie; afin de les transmettre à des afficheurs et à une base de donnée pour être tracé.

La partie émetteur :

  • J'ai donc câblé un nouveau circuit :


Matériel requis :

- 1 Arduino Pro Mini 5V.
- Un ordi avec port USB et le soft Arduino IDE.
- 1 plaquette HC-12 et son antenne.
- 1 diode 1N4007.
- 2 résistances 10kΩ.
- 1 Capteur à effet Hall US1881 (anémo).
- 1 Capteur à effet Hall 3144 (éolienne).
- 1 Régulateur Négatif 9V L7909CV.
- 1 condensateur électrochimique polarisé de 220µF.
- 1 condensateur électrochimique polarisé de 2,2µF.
- 1 condensateur électrochimique polarisé de 1µF.
- 1 module ACS712 (20A) (Attention cependant !! > Je sais que mon générateur ne dépassera pas 5A, à moins d'une tempête de vent de fin du monde…).

Principe de fonctionnement :
- À intervalle régulier, l'Arduino va envoyer les valeurs lues sur les entrées analogiques A0 et A1, sur le port série du HC-12.
- A0 pour mesurer la valeur de la tension aux bornes de la batterie ( On a fabriqué un voltmètre très précis câblé en parallèle ).
- A1 pour mesurer le courant sortant du générateur ( Un Ampèremètre câblé en série ).
- Dés que le vent fera tourner l'anémomètre, l'interruption déclenche l'envoie des valeurs lues sur l'entrée numérique 2 (int0).
- Dés que le vent fera tourner l'éolienne, l'interruption déclenche l'envoie des valeurs lues sur l'entrée numérique 3 (int1).

  • Programme pour l’Arduino Pro Mini de transmission :
#include <SoftwareSerial.h>
#include <avr/sleep.h>
/****************/
/* DÉCLARATIONS */
/****************/
// Partie ANEMO
SoftwareSerial HC12(10, 11); // HC-12 TX Pin, HC-12 RX Pin
unsigned long rpmVent = 0;
unsigned long rpmEol = 0;
unsigned long vitVentKMH = 0;
unsigned long vitEolRPM = 0;
unsigned long dateDernierChangementVent = 0;
unsigned long dateDernierChangementEol = 0;
unsigned long dateDernierChangementRPM = 0;
unsigned long dateDernierChangementKMH = 0;
unsigned long vitVentCourante = 0;
unsigned long vitVentDernierChangement = 0;  
float intervalleKMH = 0;
float intervalleRPM = 0;
char MessageVent[] = " KMH / "; // message to be sent;
char MessageEol[] = " RPM / "; // message to be sent;
String chaine;
int rotaAnemo = 0;
int rotaEol = 0;
#define ATpin 7 // used to switch HC-12 to AT mode

// Partie MONITORING
float Courant=0;
float SupplyVoltage=12;
const int Voie_0=0; // declaration constante de broche analogique
int mesure_brute=0; // Variable pour acquisition résultat brut de conversion analogique numérique
float mesuref=0.0;  // Variable pour calcul résultat décimal de conversion analogique numérique
float tension=0.0;  // Variable tension mesurée
float tension_batterie=0.0; // Variable tension batterie calculée
float tension_regulateur=8925.0;  // Variable tension réelle aux bornes du régulateur -9V (en mV)

int PIN_ACS712 = A1;
double Voltage = 0;
double Current = 0;
char MessageTensionBatterie[] = " VOL / "; // message to be sent;
char MessageCourant[] = " AMP\n"; // message to be sent; '\n' is a forced terminator char


/*********/
/* SETUP */
/*********/  
void setup() {
  HC12.begin(9600);               // Serial port to HC12
  // debug uniquement, penser à commenter toutes les lignes «Serial…» pour éviter les erreurs de valeur (calcul trop long pour l'interruption)
  Serial.begin(9600);             // Serial port to computer
  // Pin capteurs
  attachInterrupt(digitalPinToInterrupt(2), rpm_vent, FALLING);  // le capteur à effet Hall Anémomètre est connecté à la pin 2 = int0
  attachInterrupt(digitalPinToInterrupt(3), rpm_eol, FALLING);  // le capteur à effet Hall Éolienne est connecté à la pin 3 = int1  
  pinMode(PIN_ACS712, INPUT);
  
  pinMode(ATpin, OUTPUT);
  digitalWrite(ATpin, LOW); // Set HC-12 into AT Command mode
  delay(500);
  HC12.print("AT+C010");  // passer sur le canal 036 (433.4Mhz + 36x400KHz)
  delay(500);
  digitalWrite(ATpin, HIGH); // HC-12 en normal mode
}

/*************/
/* PROGRAMME */
/*************/
void loop() {
  MesureCourant();
  MesureBrute();
  TensionMesuree();
  TensionBatterie();
  RemiseZeroVitVentKMHnew2 ();
  RemiseZeroVitEolRPMnew2 ();
  
  chaine = String(vitVentKMH) + MessageVent + String(vitEolRPM) + MessageEol + String(tension_batterie,3) + MessageTensionBatterie + String(Current,3) + MessageCourant;  // construction du message
  Serial.println ( "chaine String : " +chaine );
  // Message de la forme suivante : 33 KMH / 54 RPM / 12.665 VOL / 0.045 AMP

  HC12.print(chaine); // send radio data
 // Serial.println ( rpmVent ); // affiche les rpm  

  delay(100);
}

/*************/
/* 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 ( "" );
  dateDernierChangementVent = dateCourante;
  rotaAnemo = 1;

}

void rpm_eol()    // appelée par l'interruption, Tachymétre rotation éolienne.
{
  unsigned long dateCourante = millis();
  intervalleRPM = (dateCourante - dateDernierChangementEol);
//  Serial.print ( "intervalle en s : " );
//  Serial.println (intervalleRPM/1000); // affiche l'intervalle de temps entre deux passages
  if (intervalleRPM != 0)  // attention si intervalle = 0, division par zero -> erreur
  {  
    vitEolRPM = 60 / (intervalleRPM /1000);
  }
  Serial.print ( "rpm : " );
  Serial.println ( vitEolRPM ); // affiche les rpm  
  Serial.println ( "" );
  dateDernierChangementEol = dateCourante;
  rotaEol = 1;
}


void RemiseZeroVitVentKMHnew2 ()
{
  unsigned long dateCouranteKMH = millis();
  if (rotaAnemo == 1 ){   // teste si l'Anémomètre tourne
 //   Serial.println ( "Anémo tourne ");
    float dureeKMH = (dateCouranteKMH - dateDernierChangementKMH);
    if (dureeKMH > 10000) {
      rotaAnemo = 0;
      dateDernierChangementKMH = dateCouranteKMH; 
    }
  }
  else    // Si ça ne tourne plus (valeur plus mise à jour)
  {  
    float dureeKMH = (dateCouranteKMH - dateDernierChangementKMH);
    if (dureeKMH > 6000) // Si ça ne tourne plus depuis 16 secondes, délai un peu augmenté vis à vis du mode veille.
    {
 //     Serial.print ( "dureeKMH : " );
  //    Serial.println ( dureeKMH ); // affiche les rpm  
      vitVentKMH = 0;  // Remsise à zero !
      dateDernierChangementKMH = dateCouranteKMH;   
    }
  }
}

void RemiseZeroVitEolRPMnew2 ()
{
  unsigned long dateCouranteRPM = millis();
  if (rotaEol == 1 ){ // teste si l'éolienne tourne
//    Serial.println ( "Éolienne tourne ");
    float dureeRPM = (dateCouranteRPM - dateDernierChangementRPM);
    if (dureeRPM > 10000) {
      rotaEol = 0;
      dateDernierChangementRPM = dateCouranteRPM;
    }
  }
  else    // Si ça ne tourne plus (valeur plus mise à jour)
  {  
    float dureeRPM = (dateCouranteRPM - dateDernierChangementRPM);
    if (dureeRPM > 6000) // Si ça ne tourne plus depuis 65 secondes (soit moins de 1 rpm), changé pour 8 sec en charge
    {
//      Serial.print ( "dureeRPM : " );
//      Serial.println ( dureeRPM ); // affiche les rpm  
      vitEolRPM = 0;  // Remsise à zero !
      dateDernierChangementRPM = dateCouranteRPM;    
    }
  }
}

// Partie MONITORING

void MesureCourant() {
//  Serial.print("Courant : ");
//  Serial.print(Courant);
//  Serial.print(" A | Puissance : ");
//  Serial.print(Courant*SupplyVoltage);
//  Serial.println(" Watt");

// Voltage is Sensed 1000 Times for precision
for(int i = 0; i < 1000; i++) { // ça ralentis tout, mais c'est indispensable !
Voltage = (Voltage + (0.004882812 * analogRead(PIN_ACS712))); // (5 V / 1024 (Analog) = 0.0049) which converter Measured analog input voltage to 5 V Range
delay(1);
}
Voltage = Voltage /1000;
Current = (Voltage -2.5)/ 0.100; // Sensed voltage is converter to current (0.100 pour modèle 20A)

//Serial.print("\n Voltage Sensed (V) = "); // shows the measured voltage
//Serial.print(Voltage,3); // the ‘2’ after voltage allows you to display 2 digits after decimal point
//Serial.print("\t Current (A) = "); // shows the voltage measured
//Serial.println(Current,3); // the ‘2’ after voltage allows you to display 2 digits after decimal point
}

void MesureBrute() {
//-------- mesure brute --------
  mesure_brute=analogRead(Voie_0);
//  Serial.print ("Valeur brute = "); 
//  Serial.print (mesure_brute); 
//  Serial.println (" "); // espace de propreté
}

void TensionMesuree() {
//---------- tension mesurée ---------
  mesuref=float(mesure_brute)*5000.0/1024.0;
  tension=mesuref/1000.0; // en Volts
//  Serial.print ("Tension = "); 
//  Serial.print(tension,3);  // float avec 2 décimales 
//  Serial.println(" V ");  // unité et espace de propreté
}

void TensionBatterie() {
//---------- tension batterie ---------
  tension_batterie=mesuref+tension_regulateur;
  tension_batterie=tension_batterie/1000.0; // en Volts
//  lcd.setCursor(0,1) ; // positionne le curseur à l'endroit voulu (colonne, ligne)
//  lcd.print ("Batt:"); 
//  lcd.print (tension_batterie,2); // float avec 2 décimales
//  lcd.print ("V "); // unité et espace de propreté
//  Serial.print ("Batterie = "); 
//  Serial.print(tension_batterie,3); // float avec 2 décimales 
//  Serial.println(" V ");
//  Serial.println("  ");
}


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

  • J'ai conservé mes deux systèmes d'affichage distinct (et donc deux Arduino à programmer), mais rien n'empêcherait d'utiliser un seul afficheur LCD à 4 lignes !


Matériel requis :

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


Principe de fonctionnement :
- Les deux Arduino reçoivent les valeurs transmises par le port série du HC-12 et les affichent instantanément sur l'écran LCD (courant et tension) et les afficheurs DLG (vent et éolienne).
- Le NodeMCU reçoit les valeurs transmises par le port série du HC-12 et les transmet à la Base de données InfluxDB.
- Grafana s'occupera de tracer les graphiques à partir des données.

  • Programme pour l’Arduino Pro Mini de réception LCD :
//———— Que fait ce programme ? ————
// ---> Récupére les données transmise par un module HC-12,
// ---> Affichage la mesure de la tension d'une batterie au plomb 12V sur un écran LCD.
// ---> Affichage l'intensité et la puissance fournie à la batterie par une génératrice 12V. 
//———— Fonctionnalités utilisées ————
// Utilise un afficheur LCD alphanumérique2x20 en mode 4 bits 
//———— Circuit à réaliser ————
// Broche 12 sur la broche RS du LCD
// Broche 11 sur la broche E du LCD
// Broche 5 sur la broche D4 du LCD
// Broche 4 sur la broche D5 du LCD
// Broche 3 sur la broche D6 du LCD
// Broche 2 sur la broche D7 du LCD
// Broche 7 sur HC-12 to AT mode
// Broche 8 HC-12 TX Pin
// Broche 9 HC-12 RX Pin
//———— Réglages possibles ————
// Canal de réception (voir setup)
// Voltage : Utilisé pour le calcul de la puissance en Watt.
// MiniC : pour régler le courant minimum mesuré en dessous duquel la valeur est forcée à 0, pour prendre
// en compte le fait que la mesure du zero ne tombe jamais pile.

#include <LiquidCrystal.h>  // lib LCD
#include <SoftwareSerial.h> // lib Transmission série

//################
//# DÉCLARATIONS #
//################
//——— Radio HC-12 ———//
SoftwareSerial HC12(8, 9);  // HC-12 TX Pin, HC-12 RX Pin
//#define ATpin 7             // poir passer le HC-12 en AT mode
char acquis_data;
String chaine;
float Voltage=12;
float MiniC=0.08;           // courant minimum mesuré en dessous duquel la valeur est forcée à 0.
float tension_batterie_float;
float Courant_float;
int VitesseVent;
int rpmEolienne;

//——— Écran LCD ———//
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; // Déclaration LCD
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);                  // Pins LCD en mode 4 bits 
byte carre00[8] = {                                         // caractères personnalisés
  B11111,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B11111
};
byte carre01[8] = {
  B11111,
  B00000,
  B10000,
  B10000,
  B10000,
  B10000,
  B00000,
  B11111
};
byte carre02[8] = {
  B11111,
  B00000,
  B11000,
  B11000,
  B11000,
  B11000,
  B00000,
  B11111
};
byte carre03[8] = {
  B11111,
  B00000,
  B11100,
  B11100,
  B11100,
  B11100,
  B00000,
  B11111
};
byte carre04[8] = {
  B11111,
  B00000,
  B11110,
  B11110,
  B11110,
  B11110,
  B00000,
  B11111
};
byte carre05[8] = {
  B11111,
  B00000,
  B11111,
  B11111,
  B11111,
  B11111,
  B00000,
  B11111
};
byte crochetouvrant[8] = {
  B00011,
  B00010,
  B00010,
  B00010,
  B00010,
  B00010,
  B00010,
  B00011
};
byte crochetfermant[8] = {
  B11000,
  B01000,
  B01110,
  B01110,
  B01110,
  B01110,
  B01000,
  B11000
};

//——— Fonction pour pemettre le map avec variable float ———
float mapfloat(float x, float in_min, float in_max, float out_min, float out_max) {
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

//#########
//# SETUP #
//#########
void setup() {
  Serial.begin(9600);         // Debug
  //——— HC12 ———//
  HC12.begin(9600);           // Serial port to HC12

//——— LCD ———//
  lcd.begin(20,2);            // Initialise le LCD avec 20 colonnes x 2 lignes 
  delay(10);
  lcd.print("LCD OK");        // affiche LCD OK
  delay(2000);
  lcd.clear();
  delay(10);
  lcd.createChar(0, carre00); // Les 8 caractères personnalisés
  lcd.createChar(1, carre01);
  lcd.createChar(2, carre02);
  lcd.createChar(3, carre03);
  lcd.createChar(4, carre04);
  lcd.createChar(5, carre05);  
  lcd.createChar(6, crochetouvrant);
  lcd.createChar(7, crochetfermant);
} 

//#############
//# PROGRAMME #
//#############
void loop() {
  Reception();
  Jauge();
  delay(200);
} 

//#############
//# FONCTIONS #
//#############
void Reception() {
// surtout pas de delay dans cette boucle, sinon les data reçues sont erronnées.
  while (HC12.available()) {        // If HC-12 has data
    acquis_data = HC12.read();
    chaine = chaine + acquis_data;
//    Serial.println (chaine);      // Attention, chaine est donc une String

/* message reçu de la forme 
5 KMH / 60 RPM / 11.435 VOL / -11.371 AMP
pour chaque ligne on fait :*/
    if (acquis_data == 10) {      //détection de fin de ligne : méthodes ascii meilleure !
//    if (chaine.endsWith("\n")) {      //détection de fin de ligne : méthodes String
//      Serial.println ("fin de ligne");            // debug
//      String phrase = "12.665 VOL / 0.045 AMP";   //debug
      char Ventchar[5];
      char Eolchar[5];
      char tension_batterie[7];   // chaine de 6 caractères pour stocker le texte avant le mot VOL
      char Courant[3];            // chaine de 4 caractères pour stocker le texte avant le mot AMP
// scanf tout en char, puis conversion float :
//      sscanf(chaine.c_str(), "%s KMH / %s RPM / %s VOL / %s AMP", Ventchar, Eolchar, tension_batterie, Courant);  // la chaine à parser est dans une String, avec la méthode c_str()
//      VitesseVent_float = atof(Ventchar),0;               // char convertie en Float, avec 0 décimales
//      rpmEolienne_float = atof(Eolchar),0;                // char convertie en Float, avec 0 décimales
//      tension_batterie_float = atof(tension_batterie),3;  // char convertie en Float, avec 3 décimales
//      Courant_float = atof(Courant),2;                    // char convertie en Float, avec 2 décimales
//      Serial.print("VENT:");
//      Serial.println(VitesseVent_float,0);
//      Serial.print("EOLIENNE:");
//      Serial.println(rpmEolienne_float,0);

// scanf avec int et char, puis conversion float pour les valeurs en char :
      sscanf(chaine.c_str(), "%d KMH / %d RPM / %s VOL / %s AMP", &VitesseVent, &rpmEolienne, tension_batterie, Courant);  // la chaine à parser est dans une String, avec la méthode c_str()
      tension_batterie_float = atof(tension_batterie),3;  // char convertie en Float, avec 3 décimales
      Courant_float = atof(Courant),2;                    // char convertie en Float, avec 2 décimales
      Serial.print("VENT:");
      Serial.println(VitesseVent);
      Serial.print("EOLIENNE:");
      Serial.println(rpmEolienne);

      Serial.print("VOLTS: ");
      Serial.println(tension_batterie_float,3); // float avec 3 décimales
      Serial.print("AMPERES: ");
      Serial.println(Courant_float,2);
      Serial.print("Watt: ");
      Serial.println(Courant_float*Voltage,0); // float avec 0 décimales
      Serial.println(' ');
      
// Affichage LCD courant et Puissance
      if ( Courant_float < MiniC ){   // remise à zero forcée si valeur mesurée très petite
        Courant_float = 0;
      }
      lcd.setCursor(0,0);
      lcd.print ("Power:"); 
      lcd.print (Courant_float,2);    // float avec 2 décimales
      lcd.print ("A ");               // unité et espace
      lcd.setCursor(12,0);
      lcd.write(0b01111110);          // caractère : fleche, depuis le Standard Character Pattern du LCD
      lcd.print (" ");
      lcd.print (Courant_float*Voltage,0);
      lcd.print ("Watt ");   

// Affichage LCD Batterie
      lcd.setCursor(0,1);
      lcd.print ("Batt:"); 
      lcd.print (tension_batterie_float,3); 
      lcd.print ("V ");

      chaine = "";    // vide la String chaine
    }
  }
}

void Jauge() {          // Jauge de charge batterie
  lcd.setCursor(12, 1);
  lcd.write(byte(6)); // crochet ouvrant
  lcd.setCursor(19, 1);
  lcd.write(byte(7));   // crochet fermant
  float NiveauBatterie = mapfloat(tension_batterie_float, 11.4, 12.73, 0, 30); // Discrétise la valeur de la tension batterie
  int NiveauBatterieBarre = (int)NiveauBatterie;                      // conversion en entier

  if (NiveauBatterie > 30) {  // en cas de dépassement des limites haute et basse et permettre l'affichage non-erroné
    NiveauBatterieBarre = 30;
    lcd.setCursor(13, 1);
    lcd.print ("Pleine"); 
    delay (1000);
  }
  else if (NiveauBatterie < 0) {
    NiveauBatterieBarre = 0; 
    lcd.setCursor(13, 1);
    lcd.print ("Alerte"); 
    delay (1000);
  }
//  Serial.print ("NiveauBatterieBarre = "); 
//  Serial.print(NiveauBatterieBarre);
//  Serial.println("  ");
  
  switch (NiveauBatterieBarre) {
    case 0:
    lcd.setCursor(13, 1);
    lcd.write(byte(0)); // carre00  
    lcd.setCursor(14, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(15, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(16, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(17, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
    case 1:
    lcd.setCursor(13, 1);
    lcd.write(byte(1)); // carre01
    lcd.setCursor(14, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(15, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(16, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(17, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
    case 2:
    lcd.setCursor(13, 1);
    lcd.write(byte(2)); // carre02
    lcd.setCursor(14, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(15, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(16, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(17, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
    case 3:
    lcd.setCursor(13, 1);
    lcd.write(byte(3)); // carre03
    lcd.setCursor(14, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(15, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(16, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(17, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
    case 4:
    lcd.setCursor(13, 1);
    lcd.write(byte(4)); // carre04
    lcd.setCursor(14, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(15, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(16, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(17, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
    case 5:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(15, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(16, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(17, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
    case 6:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(1)); // carre01
    lcd.setCursor(15, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(16, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(17, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
    case 7:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(2)); // carre02
    lcd.setCursor(15, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(16, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(17, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
    case 8:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(3)); // carre03
    lcd.setCursor(15, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(16, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(17, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
    case 9:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(4)); // carre04
    lcd.setCursor(15, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(16, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(17, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
    case 10:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(15, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(16, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(17, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
    case 11:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(15, 1);
    lcd.write(byte(1)); // carre01
    lcd.setCursor(16, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(17, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
    case 12:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(15, 1);
    lcd.write(byte(2)); // carre02
    lcd.setCursor(16, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(17, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
    case 13:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(15, 1);
    lcd.write(byte(3)); // carre03
    lcd.setCursor(16, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(17, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
    case 14:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(15, 1);
    lcd.write(byte(4)); // carre04
    lcd.setCursor(16, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(17, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
    case 15:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(15, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(16, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(17, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
    case 16:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(15, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(16, 1);
    lcd.write(byte(1)); // carre01
    lcd.setCursor(17, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
     case 17:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(15, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(16, 1);
    lcd.write(byte(2)); // carre02
    lcd.setCursor(17, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
     case 18:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(15, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(16, 1);
    lcd.write(byte(3)); // carre03
    lcd.setCursor(17, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
     case 19:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(15, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(16, 1);
    lcd.write(byte(4)); // carre04
    lcd.setCursor(17, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
     case 20:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(15, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(16, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(17, 1);
    lcd.write(byte(0)); // carre00
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
     case 21:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(15, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(16, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(17, 1);
    lcd.write(byte(1)); // carre01
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
     case 22:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(15, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(16, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(17, 1);
    lcd.write(byte(2)); // carre02
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
     case 23:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(15, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(16, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(17, 1);
    lcd.write(byte(3)); // carre03
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
     case 24:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(15, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(16, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(17, 1);
    lcd.write(byte(4)); // carre04
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
     case 25:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(15, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(16, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(17, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(18, 1);
    lcd.write(byte(0)); // carre00
      break;
     case 26:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(15, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(16, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(17, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(18, 1);
    lcd.write(byte(1)); // carre01
      break;
     case 27:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(15, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(16, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(17, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(18, 1);
    lcd.write(byte(2)); // carre02
      break;
     case 28:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(15, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(16, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(17, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(18, 1);
    lcd.write(byte(3)); // carre03
      break;
      case 29:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(15, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(16, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(17, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(18, 1);
    lcd.write(byte(4)); // carre04
      break;    
      case 30:
    lcd.setCursor(13, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(14, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(15, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(16, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(17, 1);
    lcd.write(byte(5)); // carre05
    lcd.setCursor(18, 1);
    lcd.write(byte(5)); // carre05
      break;       
    default:
      // statements
      break;
  }
}
  • Programme pour l’Arduino Pro Mini de réception DLG7137 :
#include <SoftwareSerial.h>

/****************/
/* DÉCLARATIONS */
/****************/

// Radio HC-12
SoftwareSerial HC12(8, 9); // HC-12 TX Pin, HC-12 RX Pin
#define ATpin A3 // used to switch HC-12 to AT mode
char acquis_data;
String chaine;
//https://plaisirarduino.fr/moniteur-serie/
int VitesseVent;   // variable des data reçue
int rpmEolienne;   // variable des data reçue
float VitesseVent_float;   // variable des data reçue
float rpmEolienne_float;   // variable des data reçue
//https://forum.arduino.cc/index.php?topic=553743.0

// Partie MONITORING
float Voltage=12;
float MiniC=0.08;           // courant minimum mesuré en dessous duquel la valeur est forcée à 0.
float tension_batterie_float;
float Courant_float;

//==== Afficheurs ====//
#define Data0 2  // Input LSB Afficheur DLG7137
#define Data1 3
#define Data2 4
#define Data3 5
#define Data4 6
#define Data5 7
#define Data6 10  // Input MSB Afficheur DLG7137
#define datapin 12   // pin  pour les données vers les registres à décallages
#define clockpin 11  // pin  pour l'horloge qui coordonne les registres à décallages
static const uint8_t latchpin1 = A0; // utilise la pin RX/TX donc sérial print impossible sans désassigner
static const uint8_t latchpin2 = A1; // ces pins ni les dessouder
//static const uint8_t latchpin1 = 25;
//static const uint8_t latchpin2 = 25;
int VitesseVentC = 0;
int VitesseVentD = 0;
int VitesseVentU = 0;
int VitesseEolienneC = 0;
int VitesseEolienneD = 0;
int VitesseEolienneU = 0;
byte dataArray[16];    // Tableau de données

/*********/
/* SETUP */
/*********/
void setup() {
  Serial.begin(9600);  // init du mode débug
  HC12.begin(9600);               // Serial port to HC12
//  HC12.begin(115200);               // Serial port to HC12
  pinMode(ATpin, OUTPUT);
  digitalWrite(ATpin, LOW); // Set HC-12 into AT Command mode
  delay(500);
  HC12.print("AT+C010");  // passer sur le canal 036 (433.4Mhz + 36x400KHz)
  delay(500);
  digitalWrite(ATpin, HIGH); // HC-12 en normal mode
  
//==== Afficheurs ====//
  pinMode(Data0, OUTPUT);
  pinMode(Data1, OUTPUT);
  pinMode(Data2, OUTPUT);
  pinMode(Data3, OUTPUT);
  pinMode(Data4, OUTPUT);
  pinMode(Data5, OUTPUT);
  pinMode(Data6, OUTPUT);
  pinMode(clockpin, OUTPUT);     // pin correspondant à "clockpin" initialisée en sortie
  pinMode(datapin, OUTPUT);      // pin correspondant à "datakpin" initialisée en sortie
  pinMode(latchpin1, OUTPUT);     // pin correspondant à "latchpin" initialisée en sortie
  pinMode(latchpin2, OUTPUT);     // pin correspondant à "latchpin" initialisée en sortie

// low byte - 8 bits premier registre
  dataArray[0] = B01111111;  // Case du tableau qui contient la valeur binaire pour permettre d'adresser l'afficheur unité
  dataArray[1] = B10111111;
  dataArray[2] = B11011111; 
  dataArray[3] = B11101111; 
  dataArray[4] = B11110111; 
  dataArray[5] = B11111011; 
  dataArray[6] = B11111101;
  dataArray[7] = B11111110;
// high byte - 8 bits second registre
  dataArray[8] = B01111111;
  dataArray[9] = B10111111;
 dataArray[10] = B11011111;  
 dataArray[11] = B11101111; 
 dataArray[12] = B11110111; 
 dataArray[13] = B11111011; 
 dataArray[14] = B11111101;
 dataArray[15] = B11111110;   
}

/*************/
/* PROGRAMME */
/*************/
void loop() {
  Reception();
  CalculReception();
  Afficheurs();
  delay(500);   // délai de rafraichissement des afficheurs

//=== pour tests ===//
//  VitesseVentC = 2;
//  VitesseVentD = 7;
//  VitesseVentU = 4;
//  VitesseEolienneC = 5;
//  VitesseEolienneD = 6;
//  VitesseEolienneU = 2;
// TestAfficheurs();
}

/*************/
/* FONCTIONS */
/*************/
void Reception() {
// surtout pas de delay dans cette boucle, sinon les data reçues sont erronnées.
  while (HC12.available()) {        // If HC-12 has data
    acquis_data = HC12.read();
    chaine = chaine + acquis_data;
//    Serial.println (chaine);      // Attention, chaine est donc une String

/* message reçu de la forme 
5 KMH / 60 RPM / 11.435 VOL / -11.371 AMP
pour chaque ligne on fait :*/
    if (acquis_data == 10) {      //détection de fin de ligne : méthodes ascii meilleure !
//    if (chaine.endsWith("\n")) {      //détection de fin de ligne : méthodes String
//      Serial.println ("fin de ligne");            // debug
//      String phrase = "12.665 VOL / 0.045 AMP";   //debug
      char Ventchar[5];
      char Eolchar[5];
      char tension_batterie[7];   // chaine de 6 caractères pour stocker le texte avant le mot VOL
      char Courant[3];            // chaine de 4 caractères pour stocker le texte avant le mot AMP
// scanf tout en char, puis conversion float :
//      sscanf(chaine.c_str(), "%s KMH / %s RPM / %s VOL / %s AMP", Ventchar, Eolchar, tension_batterie, Courant);  // la chaine à parser est dans une String, avec la méthode c_str()
//      VitesseVent_float = atof(Ventchar),0;               // char convertie en Float, avec 0 décimales
//      rpmEolienne_float = atof(Eolchar),0;                // char convertie en Float, avec 0 décimales
//      tension_batterie_float = atof(tension_batterie),3;  // char convertie en Float, avec 3 décimales
//      Courant_float = atof(Courant),2;                    // char convertie en Float, avec 2 décimales
//      Serial.print("VENT:");
//      Serial.println(VitesseVent_float,0);
//      Serial.print("EOLIENNE:");
//      Serial.println(rpmEolienne_float,0);

// scanf avec int et char, puis conversion float pour les valeurs en char :
      sscanf(chaine.c_str(), "%d KMH / %d RPM / %s VOL / %s AMP", &VitesseVent, &rpmEolienne, tension_batterie, Courant);  // la chaine à parser est dans une String, avec la méthode c_str()
      tension_batterie_float = atof(tension_batterie),3;  // char convertie en Float, avec 3 décimales
      Courant_float = atof(Courant),2;                    // char convertie en Float, avec 2 décimales
      Serial.print("VENT:");
      Serial.println(VitesseVent);
      Serial.print("EOLIENNE:");
      Serial.println(rpmEolienne);

      Serial.print("VOLTS: ");
      Serial.println(tension_batterie_float,3); // float avec 3 décimales
      Serial.print("AMPERES: ");
      Serial.println(Courant_float,3);
      Serial.print("Watt: ");
      Serial.println(Courant_float*Voltage,0); // float avec 0 décimales
      Serial.println(' ');
      
      chaine = "";    // vide la String chaine
    }
  }
}

void CalculReception ()
{
//VitesseVent=359.29;
//rpmEolienne=321.00;
  VitesseVentC = VitesseVent / 100;   // par calcul, extrait la centaine  
  VitesseVentD = VitesseVent % 100 / 10;   // par calcul, extrait la dizaine
  VitesseVentU = VitesseVent % 10;  // par calcul, extrait l'unités
    Serial.print(" VitesseVentC: ");
    Serial.println(VitesseVentC);
    Serial.print(" VitesseVentD: ");
    Serial.println(VitesseVentD); 
    Serial.print(" VitesseVentU: ");
    Serial.println(VitesseVentU); 

  VitesseEolienneC = rpmEolienne / 100;   // par calcul, extrait la centaine  
  VitesseEolienneD = rpmEolienne % 100 / 10;   // par calcul, extrait la dizaine
  VitesseEolienneU = rpmEolienne % 10;  // par calcul, extrait l'unités
    Serial.println("  ");
    Serial.print(" VitesseEolienneC: ");
    Serial.println(VitesseEolienneC);
    Serial.print(" VitesseEolienneD: ");
    Serial.println(VitesseEolienneD); 
    Serial.print(" VitesseEolienneU: ");
    Serial.println(VitesseEolienneU); 
}


void Afficheurs() {
 //==== Afficheurs ====//
 
// adresse le chiffre des Dizaines sur l'afficheur du bas
  switch (VitesseEolienneD)
  {
  case 0:
  digitalWrite(latchpin1, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[0]); 
  Zero();
  digitalWrite(latchpin1, 0); 
  break;
  
  case 1: 
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[0]); 
  Un();
  digitalWrite(latchpin1, 0); 
  break;

  case 2:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[0]); 
  Deux();
  digitalWrite(latchpin1, 0); 
  break;
 
  case 3:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[0]); 
  Trois();
  digitalWrite(latchpin1, 0); 
  break;
  
  case 4:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[0]); 
  Quatre();
  digitalWrite(latchpin1, 0); 
  break;
  
  case 5:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[0]); 
  Cinq();
  digitalWrite(latchpin1, 0); 
  break;

  case 6:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[0]); 
  Six();
  digitalWrite(latchpin1, 0); 
  break;

  case 7:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[0]); 
  Sept();
  digitalWrite(latchpin1, 0); 
  break;

  case 8:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[0]); 
  Huit();
  digitalWrite(latchpin1, 0); 
  break;
  
  case 9:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[0]); 
  Neuf();
  digitalWrite(latchpin1, 0); 
  break;
  }
// adresse le chiffre des Centaines sur l'afficheur du Haut
  switch (VitesseVentC) 
  {
  case 0:
  digitalWrite(latchpin1, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[1]); 
  Zero();
  digitalWrite(latchpin1, 0); 
  break;
  
  case 1: 
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[1]); 
  Un();
  digitalWrite(latchpin1, 0); 
  break;

  case 2:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[1]); 
  Deux();
  digitalWrite(latchpin1, 0); 
  break;
 
  case 3:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[1]); 
  Trois();
  digitalWrite(latchpin1, 0); 
  break;
  
  case 4:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[1]); 
  Quatre();
  digitalWrite(latchpin1, 0); 
  break;
  
  case 5:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[1]); 
  Cinq();
  digitalWrite(latchpin1, 0); 
  break;

  case 6:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[1]); 
  Six();
  digitalWrite(latchpin1, 0); 
  break;

  case 7:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[1]); 
  Sept();
  digitalWrite(latchpin1, 0); 
  break;

  case 8:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[1]); 
  Huit();
  digitalWrite(latchpin1, 0); 
  break;
  
  case 9:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[1]); 
  Neuf();
  digitalWrite(latchpin1, 0); 
  break;
  }
// adresse le chiffre des Dizaines sur l'afficheur du Haut 
  switch (VitesseVentD)
  {
  case 0:
  digitalWrite(latchpin1, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[2]); 
  Zero();
  digitalWrite(latchpin1, 0); 
  break;
  
  case 1: 
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[2]); 
  Un();
  digitalWrite(latchpin1, 0); 
  break;

  case 2:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[2]); 
  Deux();
  digitalWrite(latchpin1, 0); 
  break;
 
  case 3:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[2]); 
  Trois();
  digitalWrite(latchpin1, 0); 
  break;
  
  case 4:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[2]); 
  Quatre();
  digitalWrite(latchpin1, 0); 
  break;
  
  case 5:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[2]); 
  Cinq();
  digitalWrite(latchpin1, 0); 
  break;

  case 6:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[2]); 
  Six();
  digitalWrite(latchpin1, 0); 
  break;

  case 7:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[2]); 
  Sept();
  digitalWrite(latchpin1, 0); 
  break;

  case 8:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[2]); 
  Huit();
  digitalWrite(latchpin1, 0); 
  break;
  
  case 9:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[2]); 
  Neuf();
  digitalWrite(latchpin1, 0); 
  break;
  }
// adresse le chiffre des Unité sur l'afficheur du Haut
  switch (VitesseVentU)
  {
  case 0:
  digitalWrite(latchpin1, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[3]); 
  Zero();
  digitalWrite(latchpin1, 0); 
  break;
  
  case 1: 
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[3]); 
  Un();
  digitalWrite(latchpin1, 0); 
  break;

  case 2:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[3]); 
  Deux();
  digitalWrite(latchpin1, 0); 
  break;
 
  case 3:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[3]); 
  Trois();
  digitalWrite(latchpin1, 0); 
  break;
  
  case 4:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[3]); 
  Quatre();
  digitalWrite(latchpin1, 0); 
  break;
  
  case 5:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[3]); 
  Cinq();
  digitalWrite(latchpin1, 0); 
  break;

  case 6:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[3]); 
  Six();
  digitalWrite(latchpin1, 0); 
  break;

  case 7:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[3]); 
  Sept();
  digitalWrite(latchpin1, 0); 
  break;

  case 8:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[3]); 
  Huit();
  digitalWrite(latchpin1, 0); 
  break;
  
  case 9:   
  digitalWrite(latchpin1, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[3]); 
  Neuf();
  digitalWrite(latchpin1, 0); 
  break;
  }
  
// adresse les Unités de mesures  
  digitalWrite(latchpin1, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[4]); 
  K();
  digitalWrite(latchpin1, 0);            
  
  digitalWrite(latchpin1, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[5]); 
  m();
  digitalWrite(latchpin1, 0); 

  digitalWrite(latchpin1, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[7]); 
  m();
  digitalWrite(latchpin1, 0); 

  digitalWrite(latchpin2, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[8]); 
  p();
  digitalWrite(latchpin2, 0); 

  digitalWrite(latchpin2, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[9]); 
  h();
  digitalWrite(latchpin2, 0); 
  
// adresse le chiffre des Unités sur l'afficheur du Bas
  switch (VitesseEolienneU)
  {
  case 0:
  digitalWrite(latchpin2, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[12]); 
  Zero();
  digitalWrite(latchpin2, 0); 
  break;
  
  case 1: 
  digitalWrite(latchpin2, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[12]); 
  Un();
  digitalWrite(latchpin2, 0); 
  break;

  case 2:   
  digitalWrite(latchpin2, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[12]); 
  Deux();
  digitalWrite(latchpin2, 0); 
  break;
 
  case 3:   
  digitalWrite(latchpin2, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[12]); 
  Trois();
  digitalWrite(latchpin2, 0); 
  break;
  
  case 4:   
  digitalWrite(latchpin2, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[12]); 
  Quatre();
  digitalWrite(latchpin2, 0); 
  break;
  
  case 5:   
  digitalWrite(latchpin2, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[12]); 
  Cinq();
  digitalWrite(latchpin2, 0); 
  break;

  case 6:   
  digitalWrite(latchpin2, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[12]); 
  Six();
  digitalWrite(latchpin2, 0); 
  break;

  case 7:   
  digitalWrite(latchpin2, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[12]); 
  Sept();
  digitalWrite(latchpin2, 0); 
  break;

  case 8:   
  digitalWrite(latchpin2, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[12]); 
  Huit();
  digitalWrite(latchpin2, 0); 
  break;
  
  case 9:   
  digitalWrite(latchpin2, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[12]); 
  Neuf();
  digitalWrite(latchpin2, 0); 
  break;
  }
  
// adresse les Unités de mesures  
  digitalWrite(latchpin2, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[13]); 
  r();
  digitalWrite(latchpin2, 0); 
             
// adresse le chiffre des Centaines sur l'afficheur du Bas 
  switch (VitesseEolienneC)
  {
  case 0:
  digitalWrite(latchpin2, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[14]); 
  Zero();
  digitalWrite(latchpin2, 0); 
  break;
  
  case 1: 
  digitalWrite(latchpin2, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[14]); 
  Un();
  digitalWrite(latchpin2, 0); 
  break;

  case 2:   
  digitalWrite(latchpin2, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[14]); 
  Deux();
  digitalWrite(latchpin2, 0); 
  break;
 
  case 3:   
  digitalWrite(latchpin2, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[14]); 
  Trois();
  digitalWrite(latchpin2, 0); 
  break;
  
  case 4:   
  digitalWrite(latchpin2, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[14]); 
  Quatre();
  digitalWrite(latchpin2, 0); 
  break;
  
  case 5:   
  digitalWrite(latchpin2, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[14]); 
  Cinq();
  digitalWrite(latchpin2, 0); 
  break;

  case 6:   
  digitalWrite(latchpin2, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[14]); 
  Six();
  digitalWrite(latchpin2, 0); 
  break;

  case 7:   
  digitalWrite(latchpin2, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[14]); 
  Sept();
  digitalWrite(latchpin2, 0); 
  break;

  case 8:   
  digitalWrite(latchpin2, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[14]); 
  Huit();
  digitalWrite(latchpin2, 0); 
  break;
  
  case 9:   
  digitalWrite(latchpin2, 1);
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[14]); 
  Neuf();
  digitalWrite(latchpin2, 0); 
  break;
  }
 // delay(300);
}






void Nodata() {
  digitalWrite(latchpin1, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[0]); 
  blank();
  digitalWrite(latchpin1, 0);  
  
  digitalWrite(latchpin1, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[1]); 
  N();
  digitalWrite(latchpin1, 0); 

  digitalWrite(latchpin1, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[2]); 
  o();
  digitalWrite(latchpin1, 0);             
  
  digitalWrite(latchpin1, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[3]); 
  D();
  digitalWrite(latchpin1, 0);            
  
  digitalWrite(latchpin1, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[4]); 
  a();
  digitalWrite(latchpin1, 0); 
  
  digitalWrite(latchpin1, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[5]); 
  t();
  digitalWrite(latchpin1, 0); 

  digitalWrite(latchpin1, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[7]); 
  blank();
  digitalWrite(latchpin1, 0); 
    digitalWrite(latchpin2, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[8]); 
  blank();
  digitalWrite(latchpin2, 0); 

  digitalWrite(latchpin2, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[9]); 
  a();
  digitalWrite(latchpin2, 0); 

  digitalWrite(latchpin2, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[12]); 
  blank();
  digitalWrite(latchpin2, 0); 

  digitalWrite(latchpin2, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[13]); 
  blank();
  digitalWrite(latchpin2, 0);   

  digitalWrite(latchpin2, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[14]); 
  blank();
  digitalWrite(latchpin2, 0); 

    delay(5000);
}


//==== Fonctions Afficheurs ====//

void Zero ()
{
  digitalWrite(Data6, LOW);
  digitalWrite(Data5, HIGH);
  digitalWrite(Data4, HIGH);
  digitalWrite(Data3, LOW);
  digitalWrite(Data2, LOW);
  digitalWrite(Data1, LOW);
  digitalWrite(Data0, LOW);
}
void Un ()
{
  digitalWrite(Data6, LOW);
  digitalWrite(Data5, HIGH);
  digitalWrite(Data4, HIGH);
  digitalWrite(Data3, LOW);
  digitalWrite(Data2, LOW);
  digitalWrite(Data1, LOW);
  digitalWrite(Data0, HIGH);
}
void Deux ()
{
  digitalWrite(Data6, 0);
  digitalWrite(Data5, 1);
  digitalWrite(Data4, 1);
  digitalWrite(Data3, 0);
  digitalWrite(Data2, 0);
  digitalWrite(Data1, 1);
  digitalWrite(Data0, 0);
}
void Trois ()
{
  digitalWrite(Data6, 0);
  digitalWrite(Data5, 1);
  digitalWrite(Data4, 1);
  digitalWrite(Data3, 0);
  digitalWrite(Data2, 0);
  digitalWrite(Data1, 1);
  digitalWrite(Data0, 1);
}
void Quatre ()
{
  digitalWrite(Data6, 0);
  digitalWrite(Data5, 1);
  digitalWrite(Data4, 1);
  digitalWrite(Data3, 0);
  digitalWrite(Data2, 1);
  digitalWrite(Data1, 0);
  digitalWrite(Data0, 0);
}
void Cinq ()
{
  digitalWrite(Data6, 0);
  digitalWrite(Data5, 1);
  digitalWrite(Data4, 1);
  digitalWrite(Data3, 0);
  digitalWrite(Data2, 1);
  digitalWrite(Data1, 0);
  digitalWrite(Data0, 1);
}
void Six ()
{
  digitalWrite(Data6, 0);
  digitalWrite(Data5, 1);
  digitalWrite(Data4, 1);
  digitalWrite(Data3, 0);
  digitalWrite(Data2, 1);
  digitalWrite(Data1, 1);
  digitalWrite(Data0, 0);
}
void Sept ()
{
  digitalWrite(Data6, 0);
  digitalWrite(Data5, 1);
  digitalWrite(Data4, 1);
  digitalWrite(Data3, 0);
  digitalWrite(Data2, 1);
  digitalWrite(Data1, 1);
  digitalWrite(Data0, 1);
}
void Huit ()
{
  digitalWrite(Data6, 0);
  digitalWrite(Data5, 1);
  digitalWrite(Data4, 1);
  digitalWrite(Data3, 1);
  digitalWrite(Data2, 0);
  digitalWrite(Data1, 0);
  digitalWrite(Data0, 0);
}
void Neuf ()
{
  digitalWrite(Data6, 0);
  digitalWrite(Data5, 1);
  digitalWrite(Data4, 1);
  digitalWrite(Data3, 1);
  digitalWrite(Data2, 0);
  digitalWrite(Data1, 0);
  digitalWrite(Data0, 1);
}
void r ()
{
  digitalWrite(Data6, 1);
  digitalWrite(Data5, 1);
  digitalWrite(Data4, 1);
  digitalWrite(Data3, 0);
  digitalWrite(Data2, 0);
  digitalWrite(Data1, 1);
  digitalWrite(Data0, 0);
}
void p ()
{
  digitalWrite(Data6, 1);
  digitalWrite(Data5, 1);
  digitalWrite(Data4, 1);
  digitalWrite(Data3, 0);
  digitalWrite(Data2, 0);
  digitalWrite(Data1, 0);
  digitalWrite(Data0, 0);
}
void m ()
{
  digitalWrite(Data6, 1);
  digitalWrite(Data5, 1);
  digitalWrite(Data4, 0);
  digitalWrite(Data3, 1);
  digitalWrite(Data2, 1);
  digitalWrite(Data1, 0);
  digitalWrite(Data0, 1);
}
void K ()
{
  digitalWrite(Data6, 1);
  digitalWrite(Data5, 0);
  digitalWrite(Data4, 0);
  digitalWrite(Data3, 1);
  digitalWrite(Data2, 0);
  digitalWrite(Data1, 1);
  digitalWrite(Data0, 1);
}
void h ()
{
  digitalWrite(Data6, 1);
  digitalWrite(Data5, 1);
  digitalWrite(Data4, 0);
  digitalWrite(Data3, 1);
  digitalWrite(Data2, 0);
  digitalWrite(Data1, 0);
  digitalWrite(Data0, 0);
}
void slash ()
{
  digitalWrite(Data6, 0);
  digitalWrite(Data5, 1);
  digitalWrite(Data4, 0);
  digitalWrite(Data3, 1);
  digitalWrite(Data2, 1);
  digitalWrite(Data1, 1);
  digitalWrite(Data0, 1);
}
void x ()
{
  digitalWrite(Data6, 1);
  digitalWrite(Data5, 1);
  digitalWrite(Data4, 1);
  digitalWrite(Data3, 1);
  digitalWrite(Data2, 0);
  digitalWrite(Data1, 0);
  digitalWrite(Data0, 0);
}
void N ()
{
  digitalWrite(Data6, 1);
  digitalWrite(Data5, 0);
  digitalWrite(Data4, 0);
  digitalWrite(Data3, 1);
  digitalWrite(Data2, 1);
  digitalWrite(Data1, 1);
  digitalWrite(Data0, 0);
}
void o ()
{
  digitalWrite(Data6, 1);
  digitalWrite(Data5, 1);
  digitalWrite(Data4, 0);
  digitalWrite(Data3, 1);
  digitalWrite(Data2, 1);
  digitalWrite(Data1, 1);
  digitalWrite(Data0, 1);
}
void W ()
{
  digitalWrite(Data6, 1);
  digitalWrite(Data5, 0);
  digitalWrite(Data4, 1);
  digitalWrite(Data3, 0);
  digitalWrite(Data2, 1);
  digitalWrite(Data1, 1);
  digitalWrite(Data0, 1);
}
void i ()
{
  digitalWrite(Data6, 1);
  digitalWrite(Data5, 1);
  digitalWrite(Data4, 0);
  digitalWrite(Data3, 1);
  digitalWrite(Data2, 0);
  digitalWrite(Data1, 0);
  digitalWrite(Data0, 1);
}
void LettreF ()
{
  digitalWrite(Data6, 1);
  digitalWrite(Data5, 0);
  digitalWrite(Data4, 0);
  digitalWrite(Data3, 0);
  digitalWrite(Data2, 1);
  digitalWrite(Data1, 1);
  digitalWrite(Data0, 0);
}
void a ()
{
  digitalWrite(Data6, 1);
  digitalWrite(Data5, 1);
  digitalWrite(Data4, 0);
  digitalWrite(Data3, 0);
  digitalWrite(Data2, 0);
  digitalWrite(Data1, 0);
  digitalWrite(Data0, 1);
}
void D ()
{
  digitalWrite(Data6, 1);
  digitalWrite(Data5, 0);
  digitalWrite(Data4, 0);
  digitalWrite(Data3, 0);
  digitalWrite(Data2, 1);
  digitalWrite(Data1, 0);
  digitalWrite(Data0, 0);
}
void t ()
{
  digitalWrite(Data6, 1);
  digitalWrite(Data5, 1);
  digitalWrite(Data4, 1);
  digitalWrite(Data3, 0);
  digitalWrite(Data2, 1);
  digitalWrite(Data1, 0);
  digitalWrite(Data0, 0);
}
void blank ()
{
  digitalWrite(Data6, 0);
  digitalWrite(Data5, 1);
  digitalWrite(Data4, 0);
  digitalWrite(Data3, 0);
  digitalWrite(Data2, 0);
  digitalWrite(Data1, 0);
  digitalWrite(Data0, 0);
}


void TestAfficheurs() {
          
  digitalWrite(latchpin1, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[0]); 
  Sept();
  digitalWrite(latchpin1, 0);  
  
  digitalWrite(latchpin1, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[1]); 
  Zero();
  digitalWrite(latchpin1, 0); 

  digitalWrite(latchpin1, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[2]); 
  Un();
  digitalWrite(latchpin1, 0);             
  
  digitalWrite(latchpin1, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[3]); 
  Deux();
  digitalWrite(latchpin1, 0);            
  
  digitalWrite(latchpin1, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[4]); 
  Trois();
  digitalWrite(latchpin1, 0); 
  
  digitalWrite(latchpin1, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[5]); 
  Quatre();
  digitalWrite(latchpin1, 0); 

  digitalWrite(latchpin1, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[7]); 
  p();
  digitalWrite(latchpin1, 0); 



  digitalWrite(latchpin2, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[8]); 
  r();
  digitalWrite(latchpin2, 0); 

  digitalWrite(latchpin2, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[9]); 
  Cinq();
  digitalWrite(latchpin2, 0); 

  digitalWrite(latchpin2, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[12]); 
  Huit();
  digitalWrite(latchpin2, 0); 

  digitalWrite(latchpin2, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[13]); 
  Neuf();
  digitalWrite(latchpin2, 0);   

  digitalWrite(latchpin2, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, dataArray[14]); 
  Six();
  digitalWrite(latchpin2, 0); 
  
//  digitalWrite(latchpin2, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
//  shiftOut(datapin, clockpin, LSBFIRST, dataArray[12]); 
//  x();
//  digitalWrite(latchpin2, 0); 
//
//  digitalWrite(latchpin2, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
//  shiftOut(datapin, clockpin, LSBFIRST, dataArray[13]); 
//  x();
//  digitalWrite(latchpin2, 0); 
//
//  digitalWrite(latchpin2, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
//  shiftOut(datapin, clockpin, LSBFIRST, dataArray[14]); 
//  x();
//  digitalWrite(latchpin2, 0); 
//
//  digitalWrite(latchpin2, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
//  shiftOut(datapin, clockpin, LSBFIRST, dataArray[15]); 
//  x();
//  digitalWrite(latchpin2, 0); 
  delay(300);
}
  • Programme pour le NodeMCU de réception :
// Ressources :
//https://forum.arduino.cc/index.php?topic=553743.0
//https://plaisirarduino.fr/moniteur-serie/

#include "ESPinfluxdb.h"    // lib ESP InfluxDB
#include <SoftwareSerial.h> // lib Transmission série
#include <ESP8266WiFi.h>    // lib ESP Wifi
#include <ESP8266WiFiMulti.h>

//################
//# DÉCLARATIONS #
//################
//——— Radio HC-12 ———//
SoftwareSerial HC12(D5, D6);  // HC-12 TX Pin et RX Pin
char acquis_data;
String chaine;
float Voltage=12;
float MiniC=0.08;             // courant minimum mesuré en dessous duquel la valeur est forcée à 0.
float tension_batterie_float;
float Courant_float;
int VitesseVent;
int rpmEolienne;

//——— InfluxDB ———//
const char *INFLUXDB_HOST = "xxx.org";
const uint16_t INFLUXDB_PORT = 8086;
const char *DATABASE = "xxxx";
const char *DB_USER = "xxxx";
const char *DB_PASSWORD = "xxxx";
Influxdb influxdb(INFLUXDB_HOST, INFLUXDB_PORT);  //https://github.com/projetsdiy/grafana-dashboard-influxdb-exp8266-ina219-solar-panel-monitoring/tree/master/solar_panel_monitoring
int compteur = 1;

//——— WiFi ———//
char ssid[] = "xx";
char password[] = "xxxx";
ESP8266WiFiMulti WiFiMulti;

//#########
//# SETUP #
//#########
void setup() {
//  Serial.begin(115200); // Debug
//——— HC12 ———//
  HC12.begin(9600);           // Serial port to HC12
        
//——— WiFi ———//
  WiFiMulti.addAP(ssid, password);  // Connection au réseau WiFi
  while (WiFiMulti.run() != WL_CONNECTED) {
    delay(100);
  }
  Serial.println ("WiFi Connecté"); 
  
//——— InfluxDB ———//
  while (influxdb.opendb(DATABASE, DB_USER, DB_PASSWORD)!=DB_SUCCESS) { // Connexion à la base InfluxDB
    delay(10000);
  }
  Serial.println ("Connexion DataBase OK"); 
}

//#############
//# PROGRAMME #
//#############
void loop() {
  Reception();

  if (compteur > 100) { // envoie la data toutes les 6 secondes (delay 10 x 100 = 1000 ms, et l'opération prend 5 secondes à transférer/écrire en base)
    SendDataToInfluxdbServer();  
    compteur = 1;
  }
  else {
    compteur++;
  }
 delay(10);
} 

//#############
//# FONCTIONS #
//#############
void Reception() {
// surtout pas de delay dans cette boucle, sinon les data reçues sont erronnées.
  while (HC12.available()) {        // If HC-12 has data
    acquis_data = HC12.read();
    chaine = chaine + acquis_data;
    Serial.println (chaine);      // Attention, chaine est donc une String

/* message reçu de la forme 
5 KMH / 60 RPM / 11.435 VOL / -11.371 AMP
pour chaque ligne on fait :*/
    if (acquis_data == 10) {      //détection de fin de ligne : méthodes ascii meilleure avec esp8266
//    if (chaine.endsWith("\n")) {      //détection de fin de ligne : méthodes String
      Serial.println ("fin de ligne");            // debug
//      String phrase = "12.665 VOL / 0.045 AMP";   //debug
      char Ventchar[5];
      char Eolchar[5];
      char tension_batterie[7];   // chaine de 6 caractères pour stocker le texte avant le mot VOL
      char Courant[3];            // chaine de 4 caractères pour stocker le texte avant le mot AMP
// scanf tout en char, puis conversion float :
//      sscanf(chaine.c_str(), "%s KMH / %s RPM / %s VOL / %s AMP", Ventchar, Eolchar, tension_batterie, Courant);  // la chaine à parser est dans une String, avec la méthode c_str()
//      VitesseVent_float = atof(Ventchar),0;               // char convertie en Float, avec 0 décimales
//      rpmEolienne_float = atof(Eolchar),0;                // char convertie en Float, avec 0 décimales
//      tension_batterie_float = atof(tension_batterie),3;  // char convertie en Float, avec 3 décimales
//      Courant_float = atof(Courant),2;                    // char convertie en Float, avec 2 décimales
//      Serial.print("VENT:");
//      Serial.println(VitesseVent_float,0);
//      Serial.print("EOLIENNE:");
//      Serial.println(rpmEolienne_float,0);

// scanf avec int et char, puis conversion float pour les valeurs en char :
      sscanf(chaine.c_str(), "%d KMH / %d RPM / %s VOL / %s AMP", &VitesseVent, &rpmEolienne, tension_batterie, Courant);  // la chaine à parser est dans une String, avec la méthode c_str()
      tension_batterie_float = atof(tension_batterie),3;  // char convertie en Float, avec 3 décimales
      Courant_float = atof(Courant),2;                    // char convertie en Float, avec 2 décimales
      Serial.print("VENT:");
      Serial.println(VitesseVent);
      Serial.print("EOLIENNE:");
      Serial.println(rpmEolienne);

      Serial.print("VOLTS: ");
      Serial.println(tension_batterie_float,3); // float avec 3 décimales
      Serial.print("AMPERES: ");
      Serial.println(Courant_float,2);
      Serial.print("Watt: ");
      Serial.println(Courant_float*Voltage,0); // float avec 0 décimales
      Serial.println(' ');
      
// Affichage LCD courant et Puissance
//      if ( Courant_float < MiniC ){   // remise à zero forcée si valeur mesurée très petite
//        Courant_float = 0;
//      }
//Serial.println (chaine);
      chaine = "";    // vide la String chaine
    }
  }
}

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/

  if ( (tension_batterie_float >= 0) && (tension_batterie_float <= 9) ) {   // si var sup ou égal à 0 et var inf ou égal à 9
//  if ( tension_batterie_float == 0){  // Rustine pour se débarasser des erreurs de décodage de la phrase que je ne parviens pas à résoudre, malgré la détection de fin de ligne en mode ascii
    Serial.println('Erreur détection fin de ligne'); 
  }
  else if (tension_batterie_float >= 18) {
    Serial.println('Erreur détection fin de ligne'); 
  }
  else {
    dbMeasurement rowDATA("Data");
    rowDATA.addField("VitesseVent", VitesseVent);
    rowDATA.addField("RotationEolienne", rpmEolienne);
    rowDATA.addField("tension_batterie", tension_batterie_float);
    rowDATA.addField("Courant", Courant_float);
    Serial.println(influxdb.write(rowDATA) == DB_SUCCESS ? " - rowDATA write success" : " - Writing failed");
    influxdb.write(rowDATA);
  
    // Vide les données - Empty field object.
    rowDATA.empty();
  }
}

Configuration de la Grafana :

  • Concernant cette partie, je vous laisse voir la fin de ce billet, vu que c'est la même chose !

Vous pourriez obtenir ce genre de chose :


L'observateur attentif aura remarqué que la vitesse du vent n'est ici pas logique avec la rotation de l'éolienne… Normal, je faisais des tests en rotation manuelle afin de pouvoir tracer ces graphiques.

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

Ajouter un commentaire

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

Fil des commentaires de ce billet