ESP01 Contrôle des diodes WS2812 à l’aide de l’IDE Arduino-Part6


Niveau:3

Introduction:

Dans cet article, nous allons mettre en place un minuteur pour l’arrêt programmé de notre bandeau LED. Nous partirons de la version esp8266_webinterface_1.5.2.zip et nous créerons une deuxième page pour la configuration du minuteur et du choix de la couleur.

Ajout du client NTP:

Nous allons utiliser les bibliothèques suivantes:

<TimeLib.h> : https://github.com/PaulStoffregen/Time

<NTPClient.h> : https://github.com/arduino-libraries/NTPClient

et ajout des fonctionnalités wifiUdp.

#include <WiFiUdp.h> //Inclusion bibliothèque pour la gestion de l'User Datagram Protocol
#include <NTPClient.h> //Inclusion bibliothèque gestion serveur NTP
#include <TimeLib.h> //Inclusion bibliothèque gestion des fonctionnalités de chronométrage

Affichage de la date et de l’heure dans le client web:

Dans notre programme:

Nous allons ajouter une variable globale pour stocker la valeur de la date et de l’heure. Cette variable sera transmise au client web pour l’afficher dans la page web.

String DateHeure = "";

La varaible doit être ajouter après l’ensemble des définitions.

Maintenant nous allons initialisé nos bibliothèques avec leurs paramètres.

WiFiUDP ntpUDP;
// You can specify the time server pool and the offset (in seconds, can be
// changed later with setTimeOffset() ). Additionaly you can specify the
// update interval (in milliseconds, can be changed using setUpdateInterval() ).
NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000);

Ajouter l’initialisation après l’initialisation de la bibliothèque du serveur web (ESP8266WebServer server = ESP8266WebServer(HTTP_PORT);)

Dans le sous-programme setup ajouter les lignes suivantes:

server.on("/DateHeure", srv_handle_dateheure);

Au-dessus du démarrage du serveur web (server.begin();).

timeClient.begin();

A la fin du sous-programme setup.

Nous allons créer un sous-programme Date_Heure qui se mettra à jour dans le programme sous-programme loop.

void Date_Heure(){
 String temp="Date: ";
 timeClient.update();
 if (day()<10){
 temp+="0";
 temp+=day();
 }else temp+=day();
 temp+="/";
 if (month()<10){
 temp+="0";
 temp+=month();
 }else temp+=month();
 temp+="/";
 temp+=year();
 temp+=" Heure: ";
 DateHeure =temp+timeClient.getFormattedTime();
 setSyncProvider(getNtpTime);
}

Puis la fonction getNtpTime.

/*-------- NTP code ----------*/
time_t getNtpTime(){
 return (timeClient.getEpochTime()); 
}

Et dans le sous-programme loop,nous ajoutons l’appel à DateHeure.

Date_Heure();

Dans la partie du programme serveur web nous ajoutons l’envois de la chaîne dateheure.

void srv_handle_dateheure() {
 server.send(200,"text/plain", DateHeure);
}

Notre programme est terminé. Nous allons modifier notre client web pour afficher la date et l’heure. Vous pouvez envoyer le programme vers votre ESP.

Dans notre client web:

Dans le fichier index.html, nous ajoutons la ligne ci dessous en dessous du titre.

 <h2 id="dateheure"></h2><br />

Puis nous ajoutons le style H2 dans l’entête.

 h2 {
 color:#454545;
 text-align:center;
 font-size: 100%; 
 }

Dans le fichier main.js, nous ajoutons une fonction qui viendra lire la valeur à intervalle régulier avec le code ci dessous.

function rafraichir() { 
 var date = new Date(),secondes = date.getSeconds(); 
 
 /* Fonction ' SECONDES ' */
 if (secondes <= 9) {
 secondes = '0' + secondes;
 }
 
 ntp();
 }

setInterval(rafraichir, 1000);

function ntp() {
 var xhttp = new XMLHttpRequest();
 xhttp.onreadystatechange = function() {
 if (xhttp.readyState == 4 && xhttp.status == 200) {
 document.getElementById('dateheure').innerHTML = xhttp.responseText;
 }
 };
 xhttp.open('GET', 'DateHeure', true);
 xhttp.send();
}

Maintenant vous pouvez envoyer le client web vers votre ESP.

Fichier et copie d’écran:

Voici le fichier source de ce chapitre: esp8266_webinterface_1.6.0.zip

Création de la page de configuration:

Dans cette partie, nous allons créer un fichier css pour regrouper les styles de nos pages, modifier la page index.html et main.js; puis créer le fichier config.html. J’ai profité de ces modifications pour rationaliser mes pages. Je ne rentrerai pas dans les détails des modifications car cela prendrait un peu de temps, alors je vous mets juste les copies d’écrans et le fichier compressé source.

Voici le fichier source: esp8266_webinterface_1.6.1.zip

Mise en place du minuteur:

Nous utiliserons la version 1.6.1. Notre minuteur aura une valeur comprise en 0 et  600 minutes soit environ 10h.

Modification du programme:

Utilisation de la bibliothèque TimeAlarms:

https://github.com/PaulStoffregen/TimeAlarms

#include <TimeAlarms.h> //Inclusion bibliothèque gestion des fonctionnalités d'alarme et minuterie

Définition de l’adresse de stockage dans l’EEPROM de la valeur du minuteur.

#define ADRESS_MINUTEUR 113 // Adresse mémorisation Marche/Arrêt du bandeau LED 111 (Fin ADRESS_MINUTEUR + 2 mots)113-116

Création de nos variables globales:

String AffMinuteur = ""; // Variable globale de la valeur du minuteur pour client web
int MinuteurStop=0; // Variable globale de la valeur du minuteur 
uint8_t AlarmeMin=0; // Identification de l'alarme minuteur 60 secondes

Dans la partie du sous programme setup nous allons ajouter le code ci dessous:

Serial.print("ID alarme: ");
 AlarmeMin=(Alarm.timerRepeat(1, Timer1S));
 Serial.println(AlarmeMin); // Timer toute les 60 secondes
 Alarm.disable(AlarmeMin);

et avant server.begin:

server.on("/Minuteur", srv_handle_minuteur); // Serveur pour affichage tempo

Dans la partie du sous programme loop nous allons ajouter le code ci dessous:

 Alarm.delay(10);

Nous allons créer le programme de la minuterie dans le sous-programme date_heure:

Le programme ci-dessous permet de gérer l’arrêt et la variable d’affichage du minuteur. Ce programme sera appelé par notre programme.

void Timer1S(){
 if (MinuteurStop==0) {
 ws2812fx.stop();
 Alarm.disable(AlarmeMin);
 MinuteurStop=(EEPROMReadlong(ADRESS_MINUTEUR,4)); // Lecture valeur minuteur dams Mémoire.
 }else {
 --MinuteurStop;
 }

if ((MinuteurStop-60)>0){
 AffMinuteur="Minuteur temps restant: ";
 AffMinuteur+=((MinuteurStop/60)+1);
 AffMinuteur+=" mn";
 }
 else{
 AffMinuteur="Minuteur temps restant: ";
 AffMinuteur+=MinuteurStop;
 AffMinuteur+=" s";
}
}

Dans le sous-programme void srv_handle_set(), nous allons ajouter la transmission de la valeur de la minuterie depuis le client web vers notre programme:

if(server.argName(i) == "ta") { // Valeur de la minuterie 0- 600 mn pour arrêt en minutes
 MinuteurStop=60*((int)strtol(&server.arg(i)[0], NULL, 10));
 EEPROMWritelong(ADRESS_MINUTEUR,MinuteurStop,4); // Sauvegarde valeur minuteur en seconde
 }

Et modifier la commande d’arrêt sur le serveur. Voici la zone du programme à modifier.

 if(server.argName(i) == "p") { // Marche arrêt bandeau LED
 if(server.arg(i)[0] == 'm') {
 Alarm.disable(AlarmeMin);
 ws2812fx.start();
 EEPROM.write(ADRESS_ON_OFF,1); // Sauvegarde LED en marche
 } else if (server.arg(i)[0] == 'a'){
 if (EEPROM.read(ADRESS_ON_OFF)==0) ws2812fx.stop(); // Arrêt du bandeau apres deuxieme appuie sur arrêt 
 Alarm.enable(AlarmeMin);
 EEPROM.write(ADRESS_ON_OFF,0); // Sauvegarde LED à l'arrêt
 }
 EEPROM.commit();
 }

Ajout de l’affichage de la valeur du minuteur pour le client web:

void srv_handle_minuteur() {
 server.send(200,"text/plain", AffMinuteur);
}

Modification du client web:

Ajouter la ligne ci-desoous au fichier de configuration config.html pour envoyer la valeur du minuteur.

 <h2>Valeur du Timer d'arrêt <input type="number" id="timer" name="ValTimer" min="0" max="600"step="1" value="0" onchange="submitVal('ta',(this.value))"> minutes</h2>

Dans le fichier index.html, ajouter la ligne ci dessous pour afficher la minuterie.

 <h2 id="minuterie"> </h2>

Dans le fichier main.js, modifier le programme comme ci-dessous:

Ajouter la fonction minuterie.

function minuterie() {
 var xhttp = new XMLHttpRequest();
 xhttp.onreadystatechange = function() {
 if (xhttp.readyState == 4 && xhttp.status == 200) {
 document.getElementById('minuterie').innerHTML = xhttp.responseText;
 }
 };
 xhttp.open('GET', 'Minuteur', true);
 xhttp.send();
}

Et modifier le rafraîchissement en fonction de la page web afficher.

function rafraichir() { 
 ntp();
 var NomDuFichier = CheminComplet.substring(CheminComplet.lastIndexOf( "/" )+1 );
 if ((NomDuFichier =="index.html") | (NomDuFichier =="")){
 minuterie();
 }
}

Voici le fichier source :esp8266_webinterface_1.6.2.zip

Utilisation de la version 1.6.2:

La configuration du nombre de LED, du Wifi et du réseau se fait par le bais de l’interface série. Taper led pour la configuration du nombre de LED et wifi pour les paramètres Wifi/réseau.

Dans l’interface web, vous pouvez configurer le minuteur,les  couleurs, luminosité, et vitesse de votre bandeau. L’ensemble des paramètres sont mémorisés dans la mémoire EEPROM.

Si vous appuyer une fois sur arrêt, le minuteur se met en marche, au deuxième appuie le bandeau s’arrêt. L’état marche/arrêt est mémorisé dans EEPROM.

Ajout d’un redémarrage en cas de perte réseau:

Télécharger la bibliothèque https://github.com/dancol90/ESP8266Ping

Modifier le fichier ESP8266Ping.h en changeant les valeurs byte count = 5 en byte count = 1.

 bool ping(IPAddress dest, byte count = 1);
 bool ping(const char* host, byte count = 1);

Dans le programme, nous allons créer le sous programme RAZ qui arrêtera le wifi avant de faire un restart.

// Raz esp8266
void raz(){
 delay(500);
 WiFi.mode(WIFI_OFF); // Arrêt du WIFI
 ESP.restart(); // Redémarrage
}

Remplacer ESP.reset par raz() dans notre programme.

Ajouter la définition suivante:

#define WIFI_RESET 5 // Reset du WIFI toute les xxxx minutes Valeur Max 255mn. Vauleur multiple de WIFI_TIMEOUT

Et la variable:

uint8_t ReseauOut=0; // Variable Compteur Nombre de de perte du wifi

Et ajouter les lignes ci-dessous en lieu et place dans le sous-programme loop:

if(now - last_wifi_check_time > WIFI_TIMEOUT) {
 Serial.print("Vérification du WiFi... ");
 if(WiFi.status() != WL_CONNECTED) {
 Serial.println("Erreur de connexion WIFI ...");
 Serial.println("Taper wifi pour modifier les paramètres du WIFI");
 if (ReseauOut>WIFI_RESET) raz(); 
 ReseauOut++; 
 } else {
 Serial.println("OK");
 Serial.printf("Etat du Wifi %d\n",WiFi.isConnected());
 Serial.printf("Hostname est %s\n",WiFi.hostname().c_str());
 Serial.print("Addresse IP : "); Serial.println(WiFi.localIP());
 Serial.print("Passerelle IP: "); Serial.println(WiFi.gatewayIP());
 Serial.print("Masque sous réseau: "); Serial.println(WiFi.subnetMask());
 Serial.print("Adresse IP DNS: "); Serial.println(WiFi.dnsIP());
 if(Ping.ping(WiFi.gatewayIP())) {
 Serial.println("Ping Passerelle OK :)");
 ReseauOut=0;
 } else {
 Serial.println("Ping Passerelle erreur :(");
 if (ReseauOut>WIFI_RESET) raz();
 ReseauOut++;
 }
 }
 last_wifi_check_time = now;
  }

Voici le fichier source: esp8266_webinterface_1.6.3.zip