ESP8266 et ESP32

Mes derniers joujous, de vrais petits bijoux, de vrais objets connectés pour quelques Euros et de différents vendeurs.

En travail.
Les sketches fonctionnent déjà, mais doivent être adaptés pour être présentables.
A vérifier: mention du capteur analogique LM35 et du langage MicroPython.

------------------

Introduction

Cet article donne toutes les instructions, sous Windows 10, pour un débutant qui n'a jamais programmé avec un ESP32, voir un ESP8266 ou même un Arduino classique.

Ayant déjà utilisé un capteur de température 1-Wire DS18B20 de Dallas, au chapitre 18 de mon livre chez Eyrolles, Programmer en Java pour le Raspberry Pi 3, qui touche aussi au langage Python pour tester les composants déposés sur des platines d'essais, il m'est venu à l'idée d'y ajouter, en plus, un petit écran OLED. Ce dernier permettra de visualiser la température ambiante avec aussi, le minimum et le maximum mesurés.

Comme c'est mon premier exercice sérieux sur un ESP32, j'ai pensé que je pourrais partager ici mes expériences, car il y a beaucoup de petits détails et combines. Du maker tout craché et beaucoup de choses à maîtriser pour un débutant qui ne voudrait sans doute pas perdre trop de temps à se casser la tête. L'ESP32 est le succésseur de l'ESP8266. Il ne le remplace pas forcément, car le second par exemple est souvent meilleur marché. Moi-même j'avais commencé avec l'ESP8266 avant de passer avec le MicroPython plus tard (voir ci-dessous). 

Il y a évidemment plein de références sur le Web. Mon intention n'est pas de faire mieux que les autres, mais avec une approche que j'espère un peu plus ludique 

Le matériel

Le Dallas DS18B20, c'est le plus simple. Nous le trouvons partout.

Pour l'ESP32 et l'écran OLED, c'est un peu différent, il y a beaucoup de modèles et de vendeurs. Ce n'est pas du tout comme un Raspberry Pi 3 Model A+ ou un Raspberry Pi 7″ Touch Screen, où il y a juste UN modèle.

Préparation avec l'IDE de l'Arduino

Avant de commencer par écrire un sketch par composants, nous allons décrire l'installation des librairies nécessaires pour les deux cas qui finiront en fin d'article dans une application unique.

Depuis que j'ai commencé avec l'Arduino, il y a de nombreuses années, j'ai toujours repris la dernière version de l'IDE de l'Arduino, et créé un répertoire avec sa version.

Cet IDE se trouve sur le site https://www.arduino.cc/en/main/software. Nous n'utiliserons pas la version Web, mais la version 1.8.9 que nous installerons dans un répertoire comme par exemple D:\arduino-1.8.9.
J'ai aussi pris l'habitude d'utiliser un répertoire de travail, par exemple D:\arduinoDataJb où je dépose mes sketches et dans un sous répertoire D:\arduinoData\esp32 pour mon ESP32 décrit ici.   

L'IDE de l'Arduino permet d'écrire des sketches pour des Arduino classiques, mais aussi pour des ESP8266 ou des ESP32. C'est le firmware installé d'origine qui le permet. Si nous désirions utiliser un autre langage comme le MicroPython par exemple, il faudrait installé le firmware approprié (voir mon article MicroPython, NodeMCU ESP8266 et Thonny).

Losque nous aurons connecté notre ESP32, l'IDE devrait nous indiquer quel port est utilisé. En cas de doute, nous pourrons utiliser, sous Windows 10, l'explorateur, sur Ce PC, et le menu Gérer, Gestionnaire de périphérique et Ports (COM et LPT). Si aucun COM n'est visible ce peut être un problème de driver USB ou de module dans l'IDE de l'Arduino.

Avant de passer à la référence du modèle d'ESP32 utilisé, nous allons montrer et utiliser un premier script de test: espprintest.ino. Ce script devrait fonctionner pour tous les modèles d'Arduino et d'ESP. Il est important de commencer par la vérification de l'interface entre l'IDE et le micro-controlleur via un câble USB. Le script espprintest.ino doit être déposé dans un répertoire espprintest, c'est une nécessité pour l'IDE de l'Arduino:

void setup() {
Serial.begin(9600); //Communication série
}

void loop() {
delay(500);
Serial.println("Print chaque demi-seconde");
}

Pour le débutant en programmation Arduino, le site https://www.arduino.cc/reference/en/ devrait suffire. Ce dernier possède de nombreux exemples.
Le menu Fichier / Ouvert est pratique pour recharger un ancien script. Si arduino.exe est lancé sans fichier, il risque de nous montrer un nouveau sketch vide avec les entrées habituelles setup() et loop().  

Avec le menu Fichier / Préférence, nous découvrirons une ensemble de paramètres comme l'URL de gestionnaire de cartes supplémentaires où nous cliquerons sur le petit icône disquette afin d'introduire ces 3 adresses nécessaires à notre travail, pour l'ESP32, l'écran OLED et le capteur de température Dallas: 

http://arduino.esp8266.com/stable/package_esp8266com_index.json
https://dl.espressif.com/dl/package_esp32_index.json
http://www.adafruit.com/category/63_98

J'ai laissé la première référence qui pourrait être utilisé pour des ESP8266.

Après avoir indiqué ces trois adresses, il faudra redémarrer l'IDE. Il est bien pratique d'avoir un raccourci au binaire arduino.exe sur le bureau !. 

Nous irons à présent dans le menu Outils, sous Type de cartes et Gestionnaire de cartes afin d'y ajouter le module pour l'ESP32:


Ensuite, à nouveau dans le menu Outils, sous Type de cartes:

Nous indiquerons ls type ESP32 Dev Module et une vitesse de 115200 est raisonnable pour le téléchargement des scripts.

Nous utiliserons les deux boutons Vérifier (V) et Téléverser (->) dans la barre supérieure du menu de l'IDE, afin de déposer le script dans notre ESP32:



La vérification se fera avec le menu Outils, Moniteur série:

Le message apparaîtra chaque demi-seconde. Il faudra s'assurer que la vitesse sur le barre horizontale en bas est correcte, c'est à dire 9600 baud. Cette dernière correspond Serial.begin(9600) du sketch.

Cette article-ci utilise deux composants, un DS18B20 et un écran OLED. Nous allons commencer par écrire un sketch par composant afin de les vérifier.

Mon modèle d'ESP32

 Il y a une pléthore de modèles d'ESP32. Sur le site The Internet of Things with ESP32 nous trouverons pratiquement tous les modèles existants au moment de l'écriture de cet article. J'ai choisi le NodeMCU-32S d'AI-Thinker. La définition des broches est similaire à ESP-WROOM-32 d'Espressif que nous avons aussi vérifié avec les composants décrits ci-dessous.

Ce schéma repris d'AI-Thinker nous montre les broches de cet ESP32:

 

Un premier sketch avec le DS18B20

J'ai nommé le sketch suivant esp32testdallas.ino.

#include <OneWire.h>
#include <DallasTemperature.h>
#include "SSD1306Wire.h"

//Le fil data sur la broche P15
#define ONE_WIRE_BUS 15

//oneWire instance pour la communication
OneWire oneWire(ONE_WIRE_BUS);
//La réference du capteur de température Dallas
DallasTemperature sensors(&oneWire);

void setup() {
Serial.begin(9600); //Communication série
sensors.begin();
}

void loop() {
delay(2000);
// call sensors.requestTemperatures() to issue a global temperature
// request to all devices on the bus
Serial.println("Demande de température...");
sensors.requestTemperatures();
Serial.print("Temperature pour l'index 0): ");
Serial.println(sensors.getTempCByIndex(0));
}

En l'exécutant, nous devrions obtenir quelque chose comme:

Demande de température...
Temperature pour l'index 0): 21.81

toutes les 2 secondes. Le second message n'est pas immédiat: le protocole prend un peu de temps, c'est juste visible.
Pour vérifier le cas d'erreur, il suffit de retirer le fil de la broche P15, pour obtenir une valeur de -127.0. Celle-ci pourrait être testée par le logiciel pour indiquer une erreur.

 

 

 

Un autre avec l'écran OLED

....

#include "SSD1306Wire.h"
//Initialisation de l'OLED display avec la librairie Wire
SSD1306Wire display(0x3c, 21, 18); //SDA et SCK

void setup() {
Serial.begin(9600); //Communication série
display.init();

//display.flipScreenVertically();
display.setFont(ArialMT_Plain_24);
display.clear();
display.setColor(WHITE);
display.display();
}

int val = 1;
void loop() {
delay(2000);
Serial.print("Print chaque deux secondes: ");
Serial.println(val);
val += 1;

display.clear();
display.drawString(0, 0, "Salut chef!");
display.drawString(0, 30, String(val));
display.display();
}

..... 

Se connecter au réseau WiFi

Le sketch suivant sera utilisé pour installer et vérifier la connexion à notre réseau WiFi. Il faudra indiquer le nom du routeur WiFi (la variable ssid) et son mot de passe (la varaible pwd). 

#include "WiFi.h"
const char* ssid = "...";
const char* pwd = "...";

void setup() {
Serial.begin(9600);
Serial.println("Configuration du WiFi");
WiFi.begin(ssid, pwd);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("Connexion au WiFi..");
}

Serial.println("Connecté au réseau WiFi");
}

void loop() {
delay(1000);

if (WiFi.status() == WL_CONNECTED) {
Serial.println("Est connecté au réseau");
}
else {
Serial.println("N'est pas connecté au réseau");
}
}

Nous ferons la vérification avec l'IDE et le menu Outils, Moniteur série. Sans messages dans la boucle loop() nous ne pourions savoir si la configuration s'est faite correctement, puisque la partie setup() aura déjà été exécutée.
Il est tout à fait possible de consulter la liste des appareils connectés dans notre routeur, avec un interface Web, pour y vérifier qu'une adresse IP a bien été allouée voire la définir comme adresse IP fixe (statique). 

L'application complète

Le sketch final sera composé du code pour récupérer la température, la montrer sur l'écran OLED avec le maximum et le minimum, ainsi qu'un accès avec un serveur Web.

Et oui, je continue avec l'ESP8266, qui est passionnant, après une grosse année 2018 passée à l'écriture de mon livre sur le Raspberry Pi 3 et le langage Java.

NodeMCU 600 314

L'idée de cet article m'est venue en jouant avec le firmware MicroPython sur le NodeMCU ESP8266 pour un article pour le magazine Programmez.

Nous devrons consulter l'article MicroPython, NodeMCU ESP8266 et Thonny pour plus de détails et en particulier l'installation de l'outil Python esptool.py.

Cet article utilise un exécutable Windows et que se passe-t-il si le programmeur veut absolument travailler sous Linux ou utiliser un ESP8266 d'un autre vendeur.

Nous allons décrire ici comment utiliser le script Python esptool.py pour lire le firmware original ou actuel et le réécrire ou récupérer plus tard.
Le NodeMCU ESP8266 pourrait avoir un croquis Arduino déjà installé et nous verrons que cette procédure est en fait un backup!

Je n'ai pas encore décrit en détails les commandes et les différents paramètres.
Cela devrait suffire pour une première version.
Les deux sites suivants peuvent être consultés:

https://projetsdiy.fr/esp-easy-flasher-firmware-esptool-py-esp8266/

https://projetsdiy.fr/esptool-update-firmware-nodemcu-esp8266-osx/

Lorsqu'on reçoit son ESP8266, on se précipite naturellement sur son Arduino IDE et on branche le câble USB.
Le premier croquis Arduino devrait être quelque chose comme:

void setup() {
Serial.begin(9600); //Communication série
}

void loop() {
delay(1000);
Serial.println("Print chaque seconde");
}

Lorsque nous aurons testé et vérifié notre nouveau joujou avec ce croquis, pourquoi ne pas faire une sauvegarde.

L'outil pour faire ce travail de sauvegarde, c'est à dire la lecture du firmware :

esptool.py --port COM5 --baud 115000 read_flash 0 0x400000 fwNodeMCU8266std.bin 

La récupération se fera avec:

esptool.py --port COM5 --baud 115000 write_flash 0x00000 fwNodeMCU8266std.bin
esptool.py flash_id

La récupération nous montrera que le croquis sera aussi récupéré! Cool! 

 

 

 

 

Décembre 2018 - Mai 2019:

Malgré une mise à jour en janvier 2018, je n'ai pas eu le temps de vérifier à nouveau cet article. 
Il faudra donc prendre son contenu AS IS (comme il est)!

------------------------------------

Généralités

Dès que j'ai commencé à mettre un ou deux composants autour de ce ESP8266, il m'est venu cette idée de plateforme.

Au lieu de penser à une application bien spécifique, comme par exemple celle d'allumer une lampe au passage d'une personne, celle de faire clignoter la LED si l’humidité est trop haute ou trop basse, ou encore celle d'enclencher un radiateur électrique si la température est trop basse, pourquoi ne pas implémenter du code pour en faire un objet connecté beaucoup plus général.

L'ESP8266 ayant une interface Wifi et donc la possibilité de dialoguer avec l'extérieur au moyen d'un Web serveur, pourquoi ne pas laisser le contrôle et la logique à l'extérieur.
Une application sur un PC, un Smartphone, un Raspberry Pi, ou mieux encore sur un serveur NAS ouvert, pourrait implémenter du code pour, par exemple, vérifier une température, en faire des statistiques, voir générer une alarme ou envoyer un Email (un peu trop compliqué pour un ESP8266).

Commençons par la présentation des éléments:

  1. L'ESP8266, ici un NodeMCU ( Wikipedia ) qui s'alimente avec un cable USB standard 
  2. Un capteur température humidité DHT11
  3. Un relais 220V
  4. Un détecteur de mouvement
  5. Une LED

L'idée est aussi de mettre tous ces composants, ou une partie seulement, dans une jolie petite boîte!
Il manque quelques câblage, ici, comme la partie 220V du relais ou des fils de prolongation de la LED. 


Mise en route

La première chose est de connecter son NodeMCU sur son PC et de mettre en place l'outil de développement.
Le premier exercice sera de vérifier l'intégration de la LED pour pouvoir la faire clignoter.

Afin de vérifier cette partie, j'ai refait une installation complète du logiciel lors de l'écriture de ce document!
Certaine librairie (par exemple pour le DHT11) nécessite une installation particulière. 

Le document en anglais de Benn Thomsen va nous aider à configure l'IDE (logiciel de développement) de l'Arduino pour l'utiliser avec l'ESP8266.
Ma première difficulté sur mon PC a été la reconnaissance du module connecté à l'USB. J'ai dû installer le driver USB

On trouvera une description plus détaillée ici, mais les point essentiels sont: l’installation du logiciel Arduino (j'ai pris la version 1.8.1 et sans installeur) et sous Préférence dans IDE (arduino.exe), après son démarrage, il faudra s'assurer d'entrer l'Url de gestion des ESP8266: http://arduino.esp8266.com/stable/package_esp8266com_index.json.

Pour pouvoir se connecter au NodeMCU, il faudra spécifier dans l'IDE, sous Outil / Type de carte: NodeMCU 1.0 (ESP 12E Module).

On utilisera ici un DHT11 et il faudra y intégrer les librairies d'Adafruit associées.
Comme j'installe en général mes outils sur un disque séparé, on trouvera ces librairies dans le sous-répertoire D:\arduino-1.8.1\libraries sous par exemple Adafruit_Sensor et DHT_sensor.
Ne pas mettre de - dans le nom (contenus dans https://github.com/adafruit/DHT-sensor-library et https://github.com/adafruit/Adafruit_Sensor.
Dès qu'on a créer ces deux répertoires avec leur fichier, il faudra redémarrer l'IDE si actif (pour moi D:\arduino-1.8.1\arduino.exe). 

Si c'est vraiment trop compliqué, il faudra reprendre les bases sans nécessairement faire l'achat d'un Arduino, quoique!  >>>>>  Ici un très bon site de référence et très général 


Premier test avec la LED

Ce fichier de test en anglais est disponible dans l'IDE de l'Arduino sous Fichier/Exemples/ESP8266/Blink
Où cela se complique, c'est d'identifier la location de Blink.ino (le fichier de données de l'arduino.exe): C:\Users\jb\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0. Cet exemple est installé lors de l'intégration de l'ESP8266 dans l'IDE expliqué ci-dessus.

Si on veut le modifier, il est conseillé de créer son propre répertoire de fichiers .ino, par exemple sous D:\arduinoDataXx avec des sous répertoires bien nommés. 

/*
 ESP8266 Blink by Simon Peter
 Blink the blue LED on the ESP-01 module
 This example code is in the public domain

 The blue LED on the ESP-01 module is connected to GPIO1 
 (which is also the TXD pin; so we cannot use Serial.print() at the same time)

 Note that this sketch uses LED_BUILTIN to find the pin with the internal LED
*/
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);     // Initialize the LED_BUILTIN pin as an output
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED_BUILTIN, LOW);   // Turn the LED on (Note that LOW is the voltage level
                                    // but actually the LED is on; this is because 
                                    // it is active low on the ESP-01)
  delay(1000);                      // Wait for a second
  digitalWrite(LED_BUILTIN, HIGH);  // Turn the LED off by making the voltage HIGH
  delay(2000);                      // Wait for two seconds (to demonstrate the active low LED)
} 


Les scripts Arduino sont assez facile à comprendre avec la partie setup() pour l'initialisation et celle de loop() pour la boucle infinie.

LED_BUILTIN est une constante Arduino correspondant au GPIO 1, une petite LED bleu sur le circuit lui-même.

Dès qu'on a chargé ce fichier on pourra le compiler et le télécharger avec une connexion établie avec un câble USB (qui alimentera aussi le NodeMCU.

Je n'ai pas trop détaillé ici ces divers aspects, il y en a plein sur Internet, comme en français sur https://zestedesavoir.com/tutoriels/686/arduino-premiers-pas-en-informatique-embarquee/742_decouverte-de-larduino/3416_le-logiciel/#3-10784_approche-et-utilisation-du-logiciel.

On pourra modifier le code, voir connecter une grosse LED rouge (5) comme sur l'image en début d'article.
Il ne faudra pas oublier de mettre une résistance de 1K au moins entre la LED et la terre pour ne pas risquer de griller la LED voir la carte elle-même.
La LED est une diode! Il faudra donc la montée dans le bon sens, donc éventuellement la retourner si elle ne s'allume pas quand elle le devrait.

En consultant https://iotbytes.wordpress.com/nodemcu-pinout/ on trouvera que le GPIO5 correspondant au pin D1 du NodeMCU, où j'ai connecté ma grosse LED.

On utilisera donc ce code à intégrer:

const int ledPin   = 5;    //D1 grosse LED rouge (code avant setup()) 

pinMode(ledPin, OUTPUT); //Dans setup()

digitalWrite(ledPin, ...); //A modifier

Serial.println("Début de loop()"); //Dans la boucle pour vérifier l'interface Console


Dans le menu Outil / Moniteur on pourra initialisé une console pour vérifier le déroulement du programme lors d'adaptation de code.


Notre plateforme complète 

Mon code n'étant pas encore terminé, je dépose quand même ici l'état actuel début Janvier 2017.

Il est tout à fait fonctionnel, mais nécessitera encore des adaptations. Comme je dois encore développer un application client pour dialoguer avec le serveur Web de cette plateforme, bien des changements seront nécessaire. 

#include <ESP8266WiFi.h>

#include "DHT.h"

#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

#define DHTTYPE DHT11

const char* ssid     = ".....";      //Router name
const char* password = ".....";      //Router password 

//The time we give the sensor to calibrate (10-60 secs according to the datasheet)
int calibrationTime = 10;        

boolean isHigh = false;

const int relayPin = 2;    //D4 relay
const int DHTPin   = 0;    //D3 humidity / temperature sensor
const int pirPin   = 4;    //D2 mvt sensor
const int ledPin   = 5;    //D1 big LED

const int led = 13;  //It seems we cannot remove it

String texttosend = "Hi";
int nbofmoves   = 0;
int ledactive   = 1;
int relayactive = 0;

const  int   asize = 10;    //array size
static float myTemps[asize];
static float myHumids[asize];
static int   pos = 0;

static char celsiusData[7];
static char humidityData[7];

int loop1  = 0;
int count1 = 0;
int count2 = 0;

ESP8266WebServer server(80);

//Init DHT sensor.
DHT dht(DHTPin, DHTTYPE);

void handleRoot() {
  digitalWrite(led, 1);

  texttosend = "Nb of mouvements: ";
  texttosend += nbofmoves;
  
  server.send(200, "text/plain", texttosend);
  digitalWrite(led, 0);
}

void handleNotFound(){
  digitalWrite(led, 1);
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET)?"GET":"POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i=0; i<server.args(); i++){
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
  digitalWrite(led, 0);
}

void setup(void){
  Serial.begin(115200);
  Serial.println("Setup started");
  
  pinMode(relayPin, OUTPUT); 
  digitalWrite(relayPin, HIGH);
  
  pinMode(pirPin, INPUT);
  digitalWrite(pirPin, LOW);
  
  pinMode(ledPin, OUTPUT);
  
  WiFi.begin(ssid, password);

  //Config static IP
  IPAddress ip(192, 168, 1, 70);
  IPAddress gateway(192, 168, 1, 1);
  IPAddress subnet(255, 255, 255, 0);  
  WiFi.config(ip, gateway, subnet);
  
  Serial.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  if (MDNS.begin("esp8266")) {
    Serial.println("MDNS responder started");
  }

  server.on("/", handleRoot);

  server.on("/inline", [](){
    server.send(200, "text/plain", "This works as well");
  });

  server.on("/temperature", [](){
    String separator = " - ";
    String both = celsiusData + separator + humidityData; 
    server.send(200, "text/plain", both);
  });

  server.on("/relayon", [](){
    server.send(200, "text/plain", "Relay on");
    digitalWrite(relayPin, HIGH);
  });

  server.on("/relayoff", [](){
    server.send(200, "text/plain", "Relay off");
    digitalWrite(relayPin, LOW);
  });

  server.on("/relayactive", [](){
    server.send(200, "text/plain", "Relay active");
    relayactive = 1;
  });

  server.on("/relaynotactive", [](){
    server.send(200, "text/plain", "Relay not active");
    relayactive = 0;
  });

  server.on("/ledon", [](){
    server.send(200, "text/plain", "Led on");
    ledactive = 1;
  });
  
  server.on("/ledoff", [](){
    server.send(200, "text/plain", "Led off");
    ledactive = 0;
  });

  server.onNotFound(handleNotFound);

  server.begin();
  Serial.println("HTTP server started");

  //give the sensor some time to calibrate
  Serial.print("Calibrating sensor (");
  Serial.print(calibrationTime);
  Serial.print(" secs) ");
  for (int i = 0; i < calibrationTime * 2; i++){
     Serial.print(".");
     delay(500);
  }
  Serial.println(" calibrating done");
  Serial.println("THE SENSOR IS ACTIVE");

  strcpy(celsiusData, "0");
  strcpy(humidityData, "0");
              
  delay(1000);    
  blink(4);
  delay(1000);
}

void blink(int nbtimes) {
  if (ledactive == 1) {
    for (int i = 0; i < nbtimes; i++) {
      digitalWrite(ledPin, HIGH);
      delay(110);
      digitalWrite(ledPin, LOW);
      delay(110);
    }
  }
}

void sort(float a[], int size) {
    for (int i=0; i<(size-1); i++) {
        for (int o=0; o<(size-(i+1)); o++) {
                if(a[o] > a[o+1]) {
                    int t = a[o];
                    a[o] = a[o+1];
                    a[o+1] = t;
                }
        }
    }
}

void computeData(float oneTemp, float oneHumid, int nbignored) {
  myTemps[pos]  = oneTemp;
  myHumids[pos] = oneHumid;
  pos += 1;

  if (pos == asize) {
    //showAll();
      
    sort(myTemps, asize);
    sort(myHumids, asize);

    //Serial.println("Sorted done and restart from 0");

    //showAll();

    float total1 = 0;
    float total2 = 0;
    for (int i = nbignored; i < (asize - nbignored); i++) {
      total1 += myTemps[i];
      total2 += myHumids[i];
    }

    total1 = total1 / (asize - (2*nbignored));
    total2 = total2 / (asize - (2*nbignored));
    
    dtostrf(total1, 6, 1, celsiusData);               
    dtostrf(total2, 6, 1, humidityData);

    String result = "Average: ";
    String separator = " - ";
    String both = separator + celsiusData + separator + humidityData; 
    //Serial.print(result);
    //Serial.println(both);

    for (int i = 0; i < asize; i++) {
      myTemps[i]  = 0;
      myHumids[i] = 0;
    }
    pos = 0;
  }
}

void showAll() {
  for (int i = 0; i < asize; i++) {
    Serial.print(myTemps[i]);
    Serial.print(" ");
  }
  Serial.println("");

  for (int i = 0; i < asize; i++) {
    Serial.print(myHumids[i]);
    Serial.print(" ");
  }
  Serial.println("");
}


void loop(void){
  server.handleClient();

  if (digitalRead(pirPin) == HIGH) {
    if (isHigh == false) {
       if (ledactive == 1) {
         digitalWrite(ledPin, HIGH);   //the led visualizes the sensors output pin state
       }
       Serial.print("Motion detected !!!   ");
       isHigh = true;
       nbofmoves += 1;

       if (relayactive == 1) {
         digitalWrite(relayPin, HIGH);
       }
       
       blink(3);      
       delay(500); 
     }
    }

    if (digitalRead(pirPin) == LOW) {     
      if (isHigh == true) {  
        if (ledactive == 1) {
          digitalWrite(ledPin, LOW);   //the led visualizes the sensors output pin state
        }
        
        Serial.println("End of motion detected !!!");
        isHigh = false;

        if (relayactive == 1) {
          digitalWrite(relayPin, LOW);
        }
         
        blink(1);      
        delay(500);
      }
    }

    loop1 += 1;
    if (loop1 == 100000){
      loop1 = 0;
      
      //Sensor readings may also be up to 2 seconds (slow sensor)
      float h = dht.readHumidity();

      //Read temperature as Celsius (default)
      float t = dht.readTemperature();

      //Check if any reads failed
      if (isnan(h) || isnan(t)) {
        //Serial.println("isnan() failed to read from DHT sensor!");
        count2 += 1;
        h = 0;       
      }
      else {
        if (h == 0) {  //Failure: no humidity
          //Serial.println("Humidity 0 from DHT sensor!");
          count2 += 1;  
        }
        else {
          // Computes values in Celsius and Humidity
          float hic = dht.computeHeatIndex(t, h, false); 
                
          //dtostrf(hic, 6, 2, celsiusData);               
          //dtostrf(h, 6, 2, humidityData);
          count1 += 1;

          String separator = " - ";
          String both = separator + celsiusData + separator + humidityData; 
          //Serial.print(count1);
          //Serial.print(" ");
          //Serial.print(count2);
          //Serial.println(both);

          computeData(hic, h, 2);
       }
    }
  }
}

Le code n'a pas trop de documentation. Ce n'est pas trop mon habitude mais j'étais trop impatient de voir ma plateforme fonctionnée.

Le senseur est délicat: j'ignore les valeurs extrêmes. 
Le code aussi: il faut systématiquement sauver le fichier avec un autre nom ou nouvelle version. Une petite correction malveillante peu entraîner un désastre. L'IDE et le compilateur ne sont pas trop à la hauteur. Une simple variable non initialisée peut entraîner une catastrophe.  

En activant une console avant la recompilation, on pourra voir les messages correspondant à ce code pendant le démarrage et après avoir passer trois fois devant le senseur de mouvements: 

Connected to vdl-84353
IP address: 192.168.1.70
MDNS responder started
HTTP server started
Calibrating sensor (10 secs) .................... calibrating done
THE SENSOR IS ACTIVE
Motion detected !!!   End of motion detected !!!
Motion detected !!!   End of motion detected !!!
Motion detected !!!   End of motion detected !!!

Le code actuel compte le nombre de passage devant notre senseur de mouvement, et fait clignoter la LED 3 fois à chaque passage.

Nous voyons que l'adresse IP 192.168.1.70 est utilisée et qu'un accès à http://192.168.1.70 (code server.on("/", handleRoot);) nous retournera ceci 

Nb of mouvements: 3

Pour vérifier le code server.on("/temperature", [](){ on utilisera doc http://192.168.1.70/temperature

  21.1 -   33.7

C'est à dire la température en Celsius et l'humidité un peu basse (besoin de calibration quoique il fait un froid de canard dehors, -5).

J'accepte volontiers toutes questions ou commentaires pour améliorer cette partie pas encore terminée: Cette adresse e-mail est protégée contre les robots spammeurs. Vous devez activer le JavaScript pour la visualiser.

Cet article est en travail. Il devrait paraître dans le numéro de cet été 2019 du magazine Programmer.
Si un lecteur aimerait la version PDF en travail, il suffit de me contacter:  Cette adresse e-mail est protégée contre les robots spammeurs. Vous devez activer le JavaScript pour la visualiser..

C'est le premier article que j'a écrit, et qui sort un peu du contexte, après la sortie de mon dernier livre sur Java, Python et le Raspberry Pi 3, paru chez Eyrolles en Janvier 2019, mais le style est similaire avec beaucoup d'outils, de petits exemples et des schémas Fritzing.

Le NodeMCU ESP8266 a été choisi à cause de son prix modique. L'idée ensuite sera de passer sur l'ESP32, aussi en MicroPython.
Un Arduino standard n'a pas de Wi-Fi, au contraire des ESP8266 et ESP32, et le MicroPython est la solution idéale pour les makers désirant se familiariser avec le langage Python qui semble devenir, pour l'éducation, le langage officiel de programmation en France.

Nous y trouverons:

  • l'installation du firmware MicroPython pour remplacer la version originale avec laquelle nous pouvons développer des applications avec l'IDE de l'Arduino;
  • installation des outils comme PuTTY et Thonny;
  • utilisation de l'IDE Thonny pour programmer en Python sur un PC ou en MicroPython sur l'ESP8266;
  • schéma Fritzing pour une LED couleur à 4 branches et un LM35, un capteur de température;

    LM35 LEDCOL NODEMCU bb joomla

  • test de ces deux composants en MicroPython depuis le PC en mode REPL;
  • installation des scripts Python sur le NodeMCU avec le réseau Wifi et un serveur Web pour recevoir la température;
  • de nombreux trucs et astuces comme un application Java (PC ou Raspberry Pi) pour lire cette température ou encore comment remettre le firmware original de l'ESP8266.