Cartes de développement ESP8266 et ESP32

Mes derniers joujous, de vrais petits bijoux ces objets connectés. Ils sont similaires à un Arduino, mais pour quelques Euros et de différents vendeurs. Ils possèdent un WiFi intégré et peuvent se programmer avec les mêmes outils que pour l'Arduino.

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

Introduction

Cet article donne un certain nombre d'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.

Comme cet article ne semble pas interessé une foule de lecteur, j'ai décidé de réduire les descriptions en fin d'article, de n'y mettre que le code, voire quelques descriptions.
Ensuite j'ai ai ajouté mon travail personnel, comme d'afficher des températures sur le LED venant de Raspberry Pis. 

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.

En travaillant avec différentes cartes, nous pourrions nous retrouver avec un ensemble de librairies qui pourraient nous créer une sérieuse confusion.
Une méthode est d'effacer le répertoire Documents\Arduino et le contenu du répertoire utilisateur\AppData\Local\Arduino15 avant de faire une nouvelle installation.
Le répertoire Documents\Arduino pourrait aussi contenir des librairies et du matériel que nous aimerions effacer, pour être sûr, par exemple une librairie inséré par erreur. Dans ce cas nous pourrions effacer le répertoire concerné et relancer l'IDE.  

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 (version Windows zip) 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).

Lorsque nous aurons connecté notre ESP32 au PC, avec un câble USB assez long, 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.

J'ai eu moi-même quelques difficultés avec le port COM1 sur mon PC principal. Je n'ai pas vu immédiatement qu'il était connecté à ma souris:

port COM4

Dans l'IDE de l'Arduino, c'est bien le COM4, qu'il faudra spécifié, même si COM1 est aussi visible sous le menu Outils / Port!

Il est possible d'avoir d'autres soucis, comme décrit dans Failed to connect to ESP32: Timed out waiting for packet header.

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 récemment 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 les adresses nécessaires à notre travail, pour l'ESP32 ou autres: 
http://arduino.esp8266.com/stable/package_esp8266com_index.json
https://dl.espressif.com/dl/package_esp32_index.json

J'ai laissé la première référence qui pourrait être utilisée 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 la carte ESP32 Dev Module et une vitesse de 115200 est raisonnable pour le téléchargement des scripts.
C'est essentiel de faire cette étape avant de pouvoir compiler le code, car il est souvent spécifique au type de carte, comme le WiFi.

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:

Le setup() va initialiser la vitesse sur le port série COM utilisé par le câble USB conncté entre le PC rz l'ESP32.

Dans la boucle loop() nous ferons une pause de 500ms avant de continuer d'envoyer notre message qui sera visible sur le moniteur série.
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. à déposer dans un répertoire nommé esp32testdallas.
Nous commencerons par l'examiner avant de le compiler, c'est à dire d'y ajouter les librairies requises. 

#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);

//Avec sensors.requestTemperatures() pour obtenir
//des valeurs sur tous les capteurs du bus oneWire.
Serial.println("Demande de température...");
sensors.requestTemperatures();

Serial.print("Température pour l'index (0): ");
int res = (int)(sensors.getTempCByIndex(0) * 10);
//Calcul avec une décimale
float resf = (float(res))/10;
Serial.println(resf, 1);
}

Les trois include.h doivent être satisfaits. J'y ai déjà inclus le dernier, pas utilisé ici, pour l'écran OLED.
La démarche est toujours le même lorsque qu'on récupère du code pour des composants particuliers, ici le DS18B20.
Il faut chercher ces bibliothèques et les introduire dans l'IDE de l'Arduino.

Nous le faisons avec  le menu Croquis, Inclure une bibliothèque et Gérer les bibliothèques:

Les trois librairies que nous avons besoin sont visibles dans cette image:

  • OneWire by Jim Studt, ...
  • DallasTemperature by MilesBurton, ...
  • ESP8266 and ESP32 Oled Driver for SSD1306 display by Danier Eichhorn, ...

Elles sont faciles à retrouver en indiquant Tout pour le Type, Tout pour le Sujet et par exemple une recherche avec ESP32 OLED.
Il faudra cliquer sur le bouton Installer qui deviendra gris après installation.

Elles devraient être visible dans la liste, si les bibliothèques Arduino ont été régulièrement mise à jour (proposé au démarrage).

Nous avons déjà indiqué précédemment comment effacer une bibliothèque directement dans le répertoire Documents\Arduino  

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

Demande de température...
Température pour l'index (0): 22.1

toutes les 2 secondes. Le second message n'est pas immédiat: le protocole prend un peu de temps, c'est juste visible.
Un simple soufflement de la bouche sur le capteur permet de voir une petite variation. 
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 second sketch avec le DS18B20

Avec le sketch esp32testdallas2.ino, nous calculons ici le maximum et le minimum de la température mesurée en améliorant le sketch précédant:

#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);

float temperatureMinimum = 100;
float temperatureMaximum = -100;

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

//Température sur le bus à une position déterminée
//et avec une seule décimale
float temperature(int pos) {
sensors.requestTemperatures();
int res = (int)(sensors.getTempCByIndex(pos) * 10);
return (float(res))/10;
}

void loop() {
delay(2000);
float newTemperature = temperature(0);

if (newTemperature > temperatureMaximum) {
temperatureMaximum = newTemperature;
}

if (newTemperature < temperatureMinimum) {
temperatureMinimum = newTemperature;
}

Serial.print("Temperature actuelle: ");
Serial.println(newTemperature, 1);
Serial.print("Temperature min et max: ");
Serial.print(temperatureMinimum, 1);
Serial.print(" ");
Serial.println(temperatureMaximum, 1);
}

Le résultat devrait se présenter ainsi:

Temperature actuelle: 21.2
Temperature min et max: 21.0 25.1

Un premier sketch avec l'écran OLED

Le sketch sera nommé esp32testoled.ino.  

Avec le premier sketch du capteur Dallas de température, le DS18B20, nous avons déjà inclus la bibliothèque OLED driver qui nous permettra de compiler le sketch qui suit:

#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();
}

..... 

Il faudrait décrire le code mais une simple lecture devrait suffire.

Le sketch avec l'écran OLED et nos températures

Le sketch sera nommé esp32thermometre.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);

float temperatureMinimum = 100;
float temperatureMaximum = -100;

//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.setFont(ArialMT_Plain_24);
  display.clear();
  display.setColor(WHITE);
  display.display();
  sensors.begin();
}

//Température sur le bus à une position déterminée
//et avec une seule décimale
float temperature(int pos) {
  sensors.requestTemperatures();
  int res = (int)(sensors.getTempCByIndex(pos) * 10);
  return (float(res))/10;
}

int val = 1;
void loop() {
  delay(2000);
  float newTemperature = temperature(0);
  if (newTemperature > temperatureMaximum) {
    temperatureMaximum = newTemperature;
  }
  if (newTemperature < temperatureMinimum) {
    temperatureMinimum = newTemperature;
  }

  display.clear();
  display.drawString(0, 0, String(newTemperature, 1));
  display.drawString(0, 30, String(temperatureMinimum, 1));
  display.drawString(60, 30, String(temperatureMaximum, 1));
  display.display();
}

Jolis résultat:

A faire éventuellement: expliquer un peu mieux.

Se connecter au réseau WiFi

Le sketch suivant que j'ai nommé esp32WiFi.ino sera utilisé pour installer et vérifier la connexion à notre réseau WiFi. Il faudra indiquer le nom de son routeur WiFi (la variable ssid) et le mot de passe (la variable 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.print("Est connecté au réseau avec ");
Serial.println(WiFi.localIP());
}
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 peut-être été déjà exécutée.
Un moyen de voir cette première partie est de garder le terminal actif ou/et de presser le bouton RST sur l'ESP32, à droite du connecteur USB.

La partie du loop() sera ainsi présentée, et chaque seconde:

Est connecté au réseau avec 192.168.1.141
Est connecté au réseau avec 192.168.1.141
.....

L'adresse 192.168.1.141 est attribuée par le routeur.

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).

Un serveur Web simple

J'ai nommé ce sketch esp32WiFi.ino. Il contient évidemment l'initialisation du WiFi que nous avons vu précédemment.
C'est en travail pour l'instant!

#include "WiFi.h"
const char* ssid = "...";
const char* pwd = "...";
WiFiServer server(80);
String header; //requête Web

void setup() {
Serial.begin(9600);
Serial.print("Connexion à ");
Serial.println(ssid);
WiFi.begin(ssid, pwd);
while (WiFi.status() != WL_CONNECTED) {
delay(333);
Serial.print(".");
}

//Montre l'adresse IP et démarre le serveur Web
Serial.println("");
Serial.println("WiFi connecté!");
Serial.println("Adresse IP: ");
Serial.println(WiFi.localIP());
server.begin();
}

int cnt = 1;

void loop() {
WiFiClient unclient = server.available(); //On écoute

if (unclient) { //Un client se connecte
Serial.println("Nouveau client.");
String currentLine = ""; //Données du client
while (unclient.connected()) { //Boucle pendant la connextion
if (unclient.available()) { //Des bytes reçus
char c = unclient.read(); //Un byte
Serial.write(c); //sur le moniteur série
header += c;
if (c == '\n') { //nouvelle ligne
//Si deux lignes vides: fin de requête
if (currentLine.length() == 0) {
//Les headers HTTP commencent toujours avec une réponse de ce type
unclient.println("HTTP/1.1 200 OK");
unclient.println("Content-type:text/html");
unclient.println("Connection: close");
unclient.println();

//Préparation de la page Web en HTML
unclient.println("");

//Heading de la page
unclient.println("ESP32: Serveur Web");
unclient.print("Compteur: ");
unclient.println(cnt);
unclient.println("");
unclient.println("");
//On termine avec une autre ligne vide
unclient.println();
break;
}
else { //Si nouvelle ligne
currentLine = "";
}
}
else if (c != '\r') {
currentLine += c;
}
}
}
//Efface l'header
header = "";

//Ferme la connexion
unclient.stop();
Serial.println("Client déconnecté.");
Serial.println("");
cnt += 1;
}
}

Avant de le compiler et de le télécharger, nous ouvrirons déjà la fenêtre du moniteur série, afin de voir s'afficher l'adresse IP.

L'accès se fait avec http://192.168.1.141/.

Ce script ne marche pas trop bien, la connection se fait 2 fois. Je vais le corriger assez rapidement avec un ...

server.send(200, "text/html", ....

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.

J'ai laissé pour l'instant cette partie, pour passer à l'exercice suivant en août 2019:

 

Récupérer des températures d'autres serveurs Web et les présenter sur le display

A suivre .... le code est fonctionnel sur deux Raspberry Pi.

Comme cet article est en travail, toutes questions ou commentaires pour améliorer cet article sont bienvenus: Cette adresse e-mail est protégée contre les robots spammeurs. Vous devez activer le JavaScript pour la visualiser.

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! 

 

 

 

 

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)!
La cause: Mon livre chez Eyrolles dédié au Raspberry Pi 3 sorti en Janvier 2019, où l'on pourra rencontrer ce même type de platine d'essais avec du logiciel écrit en Python et en Java.

J'ai constaté un grand nombre de lectures de cet article (moins que mon LEGO Mindstorms EV3: ev3dev et Python) et celui-ci, daté juin 2019 et paru dans le magazine Programmez, risque d'être encore plus apprécié: MicroPython, NodeMCU ESP8266 et Thonny.

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

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). après l'installation du gestionnaire (gérer) ESP8266.

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 terminé. Nous le trouvons dans le numéro d'été 2019 du magazine Programmer.
Si vous avez des questions, des remarques ou du code source, vous pouvez me contacter:  Cette adresse e-mail est protégée contre les robots spammeurs. Vous devez activer le JavaScript pour la visualiser..

Résumé

C'est un des gros articles que j'ai écrit 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 de 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.

 

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

 

Article complet: MicroPython pour le NodeMCU (ESP8266) avec Thonny

C'est l'article complet paru dans Programmez, numéro 231, Juillet - Août 2019, mais un peu remanié.

Introduction

La définition dans Wikipedia est parfaite : MicroPython est une implémentation écrite en C du langage Python, adapté au monde des microcontrôleurs. Son site Web officiel se trouve à l'adresse http://micropython.org/, mais https://docs.micropython.org/en/latest/ est plus complet. Thonny est un IDE pour débutant en Python et disponible sous Windows, Mac et Linux. C’est l’outil idéal pour les microcontrôleurs du type ESP8266 ou ESP32 avec un firmware MicroPython que nous allons installer ici pour le premier. Moi-même, sur mes Arduino, ESP8266 et ESP32, je n'ai jamais utilisé le langage de script LUA et toujours développé le logiciel avec l’IDE de l’Arduino.

Étant moi-même un fan et un inséparable de programmation Java, donc de programmation objet, je me suis aussi, avec le temps, familiarisé avec Python, le langage que j'ai utilisé pour vérifier mes composants attachés au GPIO du Raspberry Pi 3. Je cherchais aussi quelque chose de ludique simple, orienté éducation pour les débutants, pour mon NodeMCU, un ESP8266. C'est alors que j''ai découvert le MicroPython.

Je ne mentionnerai pas ici la carte piboard (http://micropython.fr/cartes_micropython/pyboard) déjà rencontrée en novembre 2018 dans Programmez. La piboard possède plus de broches GPIO et analogiques, vient préinstallée avec MicroPython, mais est nettement plus coûteuse. Pour les makers débutants, je recommanderais le NodeMCU avec lequel il est possible de le programmer à la manière Arduino, avec l’IDE de ce dernier, où il y a pléthore d’exemples sur le Web, et avant de passer à l'installation manuelle du firmware MicroPython. Le principe de développement et les outils sont similaires, cependant l'approche ludique de l'apprentissage de Python sur le PC me semble intéressante. De plus une carte PiBoard va bien coûter 10 fois plus cher qu’une solution NodeMCU.

Jouant moi-même depuis longtemps avec l'Arduino, aussi pour vérifier certains capteurs ou composants digitales que je déposais sur mes Raspberry Pi, il était naturel de passer au NodeMCU :

Le modèle présenté et utilisé ici vient du vendeur Ai-Thinker. Si un autre modèle était utilisé, il faudrait consulter le vendeur pour vérifier les différences voire le firmware version en cas de réinstallation.

C'est un Arduino simplifié, aussi meilleur marché, possédant une interface Wi-Fi et utilisant le même outil de développement IDE que celui de l'Arduino donc avec une connexion via un câble USB. Le NodeMCU, en bref, est une carte basée sur le microcontrôleur 8266 avec 10 broches GPIO et une seule analogique (A0).

Lorsqu'on attache au NodeMCU des composants comme des LEDs, des capteurs, voire des relais, l'outil pour les contrôler par logiciel est l'IDE de l'Arduino avec les langages C et C++ (fonctionnalités limitées). Pour les les débutants ou enseignants désirant apprendre les rudiments de la programmation, le langage Python est certainement plus approprié.

Un programmeur expérimenté devra aussi avoir des bases du langage C, évidemment, pour ensuite passer à du plus sérieux comme le C++ et améliorer son CV. Personnellement, je pencherais plus pour Java comme premier langage, mais ce dernier est simplement inapplicable sur un Arduino ou un ESP8266. Le langage Python, avec de nombreuses alternatives d'outils, étant disponible sur des plates-formes comme Windows, Linux ou encore le Raspberry Pi, ce sera un choix judicieux de remplacer le firmware d'un NodeMCU, donc d'un ESP8266, pour supporter et développer du logiciel en MicroPython, c'est à dire en Python 3. J’indiquerai encore que l’installation et l’utilisation du MicroPython sur un ESP32 est similaire.

Préparation de l’installation et utilisation des outils

Les procédures décrites ici sont pour Windows, mais c'est assez équivalent sous Linux puisque l'IDE de l’Arduino, le langage Python et d’autres outils comme Thonny existent aussi sous Linux et MacOS.

Pour pouvoir jouer avec le MicroPython, il faut commencer par remplacer le firmware installé d'usine sur le NodeMCU ESP8266, avant d'utiliser un IDE comme Thonny sur PC.

Le lecteur aura sans doute déjà pianoté avec l'Arduino IDE pour télécharger et tester des sketches. Nous y aurons découvert le COM utilisé ainsi que la dimension de la flash de 4 Moctets (le minimum est de 1 Moctets pour MicroPython, à surveiller, si on utilise d'autres types d’ESP8266).

Lors du branchement du câble USB sur le NodeMCU, il faudra utiliser Gérer dans l'explorateur de fichiers de Windows sous « Ce PC » pour découvrir quelque chose comme :

indiquant que le port COM4 est ici utilisé.
Si le port COM n'est pas identifiable, il faudrait envisager d'installer le driver USB depuis Silicon Lab à l'adresse https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers.

Installation du firmware

Avant de passer à l’installation de MicroPython, il faudra se rendre compte que le firmware original du NodeMCU sera écrasé. Nous ne pourrons donc plus utiliser l’IDE de l’Arduino pour développer des applications avec le firmware original qui sera remplacé par la version MicroPython. Si nous désirons revenir au NodeMCU d’usine, il faudra utiliser par exemple ESP8266Flasher.exe pour Windows 64-bit qui se trouve à l’adresse https://github.com/nodemcu/nodemcu-flasher/tree/master/Win64/Release. C’est un exécutable qui ne nécessite aucune modification dans les options : il suffira d’indiquer le COM qui est facilement identifiable après la connexion avec le câble USB. J’ai fait moi‑même la vérification et ensuite un test à partir de l’IDE de l’Arduino avec un sketch rudimentaire contenant juste un print() et un delay() dans la boucle loop traditionnelle. Pour ceux qui veulent faire cet exercice, ils prendront la dernière version binaire de l’IDE sur https://www.arduino.cc/en/Main/Software et il faudra spécifier l’URL de téléchargement https://github.com/esp8266/Arduino/releases/download/2.3.0/package_esp8266com_index.json dans les préférences et ajouter le bon gestionnaire de carte, NodeMCU 1.0 (ESP-12E Module), sous Outils, Type de carte. Pour un autre vendeur d’ESP8266 (ici c’est Ai‑Thinker), il faudrait considérer l’outil esptool.py avec read_flash pour reprendre le firmware d’origine: il faudra donner les bons paramètres.

Pour les makers utilisant Linux ou un autre type d’ESP8266, il faudra se retourner sur l’outil esptool.py et consulter le site https://nodemcu.readthedocs.io/en/master/flash/. Nous y trouverons la description de la commande avec write_flash.

Le téléchargement du firmware se faisant avec un script Python, ainsi que les outils qui suivront, nous aurons besoin d'installer préalablement le langage Python sur le PC. Moi‑même j'ai eu quelques difficultés avec mes versions de Python 2 et 3, c'est pourquoi je donnerai ici, à chaque fois, le chemin complet de l'installation lors de l'exécution de scripts.

Pour cette installation, je n'ai pas considéré la version de Python qui vient installée avec Thonny, mais la version standard que j’utilisais déjà avec d'autres outils, comme Eclipse sous PyDev, une extension tiers (http://www.pydev.org/ et pour mon article dans Programmez de février 2019 (no.226)) où j'avais besoin d'une installation traditionnelle.

Nous trouverons sur https://www.python.org/downloads/ le fichier d'installation de Python, la version 3, nommé « Windows x86 executable installer » et nous choisirons l'option « Customize installation » avec tous les « Features » pour le positionner par exemple dans le répertoire D:\Python37-32. Il m’est aussi arrivé de devoir faire une réparation (Repair), dans le même répertoire, après avoir remarqué que python.exe ne voulait plus s’exécuter.

Dans un nouveau répertoire D:\Python37-32\esptool-master, nous irons télécharger les outils et les dézipper depuis https://github.com/espressif/esptool (avec le bouton « Clone or Download » suivi de « Download zip ») ainsi que le firmware de MicroPython, esp8266-20190125-v1.10.bin, depuis le site http://micropython.org/download, qui est la version disponible au moment de l’écriture de cet article. Le fichier esptool-master.zip n’a pas de date et attention de bien prendre la version 8266 du firmware et non celle du 32, c’est à dire de la puce ESP-32.

Pour pouvoir communiquer en Python avec le port série de l’USB, il faudra installer le module pySerial. Si nous ne le savons pas, pas de soucis, en se positionnant sur le disque D:, dans mon cas, et dans une console CMD de Windows :

D:
D:\>cd Python37-32
D:\Python37-32>python.exe -m pip install pyserial

qui nous indiquera par exemple :

D:\Python37-32>python.exe -m pip install pyserial
Requirement already satisfied: pyserial in d:\python37-32\lib\site-packages (3.4)

que c’est déjà installé.

Sur certains sites Web, nous pourrions trouver une référence à l’effacement de la flash voir même en tenant pressé le bouton FLASH sur le NodeMCU :

D :
CD D:\Python37-32\esptool-master
D:\Python37-32\python.exe esptool.py --chip esp8266 erase_flash

Cette procédure n’a pas été nécessaire sur mon modèle.

Pour l’écriture du firmware, c’est à dire du fichier esp8266-20190125-v1.10.bin, certains sites indique cette commande :

esptool.py --port COM5 write_flash 0x00000 esp8266-20190125-v1.10.bin
Dans mon cas, pour ma variante de NodeMCU, j’ai utilisé :
esptool.py --port COM5 --baud 115000 write_flash --flash_size=detect -fm dio 0 esp8266-20190125-v1.10.bin

Si notre NodeMCU connecté vient d’être utilisé, il faudra reconnecté le câble USB. J’ai eu un cas, après avoir laissé mes platines de démonstration branchées, de devoir reflasher le firmware en tenant le bouton FLASH pressé durant le transfert.

Donc après avoir identifié le COM4 depuis Windows, utiliser une vitesse raisonnable (115000) voire créer une commande flash.cmd avec une PAUSE en dernier  :

D :
CD D:\Python37-32\esptool-master
D:\Python37-32\esptool-master>D:\Python37-32\python.exe esptool.py --port COM4 --baud 115000 write_flash --flash_size=detect -fm dio 0 esp8266-20190125-v1.10.bin
esptool.py v2.7-dev
Serial port COM4
Connecting....
Detecting chip type... ESP8266
Chip is ESP8266EX
Features: Wi-Fi
MAC: 5c:cf:7f:00:d6:51
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Auto-detected Flash size: 4MB
Flash params set to 0x0240
Compressed 615388 bytes to 399928...
Wrote 615388 bytes (399928 compressed) at 0x00000000 in 35.4 seconds (effective 139.0 kbit/s)...
Hash of data verified.
Leaving...
Hard resetting via RTS pin...

Nous allons à présent indiquer comment vérifier l’installation du firmware.

Vérification de notre NodeMCU avec MicroPython

La première vérification se fera avec PuTTY avant d’utiliser Thonny l’outil IDE pour Python et MicroPython.

Installation de PuTTY et REPL

Il n'est pas essentiel d'utiliser PuTTY pour tester nos premiers scripts. Nous pourrions passer directement à Thonny, l'IDE parfait pour le MicroPython. Pour les bricoleurs comme moi, jouant par exemple avec des Raspberry Pi, un robot Lego EV3 ou d'autres plates-formes à micro-contrôleur, PuTTY devrait déjà être installé sous Windows. PuTTY est une application client SSH et telnet que l'on peut aussi utiliser sur un port série COM.

Une alternative à PuTTY c’est par exemple Tera Term (https://osdn.net/projects/ttssh2/releases/). Si le lecteur le connaît déjà, il peut l’utiliser et sans passer par l’installation de PuTTY. Il ne devra pas oublier de spécifier la vitesse avec le menu Setup / Serial port… et ceci après la connexion sur le COM du NodeMCU ESP8266 déjà branché avec le câble USB.

Nous pourrons télécharger PuTTY depuis le site http://www.putty.org/ et nous choisirons la version 64 bits installable avec l’extension .msi.

La fenêtre de l'application PuTTY nous permettra d'entrer le port série (bouton à cocher « Serial ») et la vitesse de 115200 définie par le firmware :

Il est important d’ajuster le Flow Control à None. Dans cette fenêtre, nous irons sous Category, Connection et Serial pour le modifier.

Pour une prochaine utilisation, et c'est vraiment pratique, nous sauverons la session avec un nom prédéfini, comme par exemple NodeMCU COM4.

Avec le bouton « Open » nous devrions voir cette fenêtre avec l'invite du MicroPython en ligne de commande REPL, c'est à dire >>>.
Elle apparaîtra après l'envoi de la touche Retour sur le clavier et positionné dans la fenêtre de PuTTY :

REPL signifie Read Evaluate Print Loop. Il s'agit du nom donné à l'invite interactive du MicroPython. Utiliser le REPL est de loin le moyen le plus simple de tester du code simple et d’exécuter des commandes.

Nous allons commencer par entrer les deux commandes Python suivantes (un Ctrl-C sur une sélection suivi d'un clic du bouton droite de la souris, permet un copier/coller une sélection d’ailleurs dans la fenêtre de PuTTY) :

import sys
print(sys.platform+ " " + sys.version)

qui seront ainsi interprétés en mode REPL :

>>> import sys
>>> print(sys.platform+ " " + sys.version)
esp8266 3.4.0

La version est bien 3.4.0, celle de notre MicroPython, qui vient d'une réécriture complète de la version 3.4 du langage Python. Pour l’installation et l’utilisation de Thonny qui va suivre, il faudra préalablement fermer la session PuTTY, et ensuite sortir et rebrancher le câble USB.

Installation de Thonny

J'ai choisi l'IDE Thonny sous Windows qui permet le développement d'applications en Python et MicroPython depuis le PC et avec un câble USB connecté à notre NodeMCU.
Une alternative à Thonny, c'est uPyCraft: https://randomnerdtutorials.com/install-upycraft-ide-windows-pc-instructions/. Nous noterons le site https://randomnerdtutorials.com que je conseille au lecteur de suivre régulièrement ou de s'abonner. Rui Santos fait un travail extraordinaire pour de nombreux projets Arduino, ESP8266 ou ESP32. Il a aussi été pour moi une source d'information pour écrire cet article et certains sujets de mon dernier livre dédié au Raspberry Pi 3 avec Python et Java.

Sur le site Web de Thonny, https://thonny.org/, au moment de l'écriture de cet article, j'y ai trouvé la version 3.1.2 (thonny-3.1.2.exe). Comme j'avais déjà installé Thonny, il me demande juste de mettre mon ancienne version à jour sur D:\Thonny (j'utilise le disque D : pour ne pas surcharger mon disque SSD C:).

Nous commencerons par créer un fichier test1.py avec les deux instructions que nous connaissons déjà :

Je l'ai mis ici volontairement dans Notepad++ (https://notepad-plus-plus.org/fr/), car j'adore sa colorisation syntaxique et je l'utilise souvent avant de déposer mes scripts Python sur mes Raspberry Pi, scripts qui ne nécessitent souvent pas de tests sur le PC au travers d’un interpréteur Python à installer.

Ayant créé ce premier script Python, nous pouvons à présent l'ouvrir dans Thonny et l'exécuter avec le bouton fléché circulaire Run, coloré vert (ou F5) :

Le premier message indique que l’interpréteur est celui empaqueté avec Thonny. Nous pourrons l'identifier avec le menu Tools, Options et Interpreter :

Nous passerons rapidement à notre NodeMCU ESP8266, qui est déjà connecté avec un câble USB, un changeant le mode en « generic device » avec le même menu Tools, Options et Interpreter :

Nous remarquons que le COM4 a été assigné par Windows. Comme ci-dessus, nous utiliserons à nouveau le bouton Run coloré vert (ou F5) :

Nous sommes cette fois-ci sur notre NodeMCU ESP8366. Nous avons la même réponse que précédemment en mode REPL sous PuTTY. Magnifique !

Déposer des composants sur notre NodeMCU

Avant de pouvoir programmer nos premiers scripts Python, il nous faut préparer nos plaques de prototypage avec quelques capteurs et composants.

Une LED à 4 branches et un LM35

Une LED à 4 branches, c'est une LED couleur où les trois couleurs RVB peuvent être activées séparément.
Ce sera un excellent sujet pour de premiers exercices en Python.

Nous devons tout d'abord présenter la disposition des pins sur le NodeMCU :

ainsi que le diagramme Fritzing (http://fritzing.org/home/) de notre LED où chaque broche, correspondant à une couleur RGB différente, doit être protégée, pour limiter le courant, par une résistance de 220 Ohm, valeur que nous trouvons dans les kits et correcte pour cette tension de 3.3Volt et ce composant LED :

Nous y avons aussi ajouté un capteur de température LM35 sur l'unique broche analogique du NodeMCU. En plaçant le NodeMCU juste entre deux petites plaques de prototypage, il tiendra bien, et nous aurons d'un côté la partie analogique et de l'autre la digitale. Pour la couleurs des fils de la LED RGB, nous avons utilisé ici sur ce schéma la couleur qui sera activée sur la LED. La broche D0, en haut à droite, va correspondre au GPIO16, c'est à dire à la couleur rouge. J’ai ajouté ces descriptions de couleurs dans les scripts Python qui suivront. Nous mettrons en série trois résistances de 220 Ohm avant chaque broche correspondante à une couleur. La broche la plus longue est celle associée à la terre.

Test de nos deux composants depuis Thonny

Nous commencerons par tester les deux composants depuis Thonny avec deux scripts des plus dépouillés, mais aussi lisibles que possible.

Le plus facile et direct ici est de démarrer Thonny avec le NodeMCU déjà connecté et avec le mode en « generic device » (Menu : Tools, Option, Interpreter) sur le COM déjà détecté.

Dans le fichier test2.py nous déposerons le script Python suivant :

from machine import Pin
from time import sleep

ledblue = Pin(16, Pin.OUT) #bleu
ledgreen = Pin(5, Pin.OUT) #vert
ledred = Pin(4, Pin.OUT) #rouge

ledred.value(0)
ledgreen.value(0)
ledblue.value(0)

while True:
ledgreen.value(not ledgreen.value())
sleep(1.0)

Nous montrons à nouveau l’exécution dans Thonny avec le bouton Run coloré vert (ou F5) :

Ici, il n’y a pas de message dans la partie Shell de Thonny, car aucune instruction print() ne sont présentes dans le script.

Après l’assignation des broches (voir le diagramme ci-dessus, où par exemple la broche D0 correspond au GPIO16 et la couleur bleu) nous déposons 3 valeurs 0 sur chacune. Aucune couleur ne sera donc activée.

Dans la boucle while le not de l’instruction value() est particulier et génial. Chaque seconde, la valeur de la couleur rouge sera inversée. Donc, au premier passage, la LED sera allumée en rouge pour 1 seconde. Avant la boucle while nous pourrions activer la partie bleue et la laisser ainsi, donc avec ledblue.value(1). Lorsque la broche rouge sera inactive, chaque seconde après une seconde, la LED sera bleue, sinon le bleu et le rouge se mélangerons.

En ajoutant le code qui suit qui contient quelques pauses en secondes (sleep(sec)), et avant les trois value(0), et comme ceci :

sleep(1.0)
ledblue.value(0)
sleep(2.0)
ledboard = Pin(2, Pin.OUT)
ledboard.value(0)
sleep(3.0)

nous comprendrons que (nous retirerons et remettrons le câble USB pour s’assurer du bon état des broches au démarrage) :
• la LED couleur sera bleue, car le GPIO16 sera 1 au démarrage par défaut ;
• après une seconde la LED s’éteint, mais une LED bleue sur le NodeMCU s’allume (près du câble USB) (elle est mise en circuit inversé par rapport à D0, le GPIO 16) ;
• après 2 autres secondes, une autre LED bleue sur l’ESP8266, à côté du D0, associée au GPIO02 (D4) s’allume (ledboard.value(0) : valeur inversée comme D0. Par défaut au démarrage le D4 (pas utilisé ici) est à 1 ;
• lorsque le code initial est actif avec la LED clignotant en rouge, les deux LEDs bleues sur la carte resteront allumée.

Il est donc possible d’utiliser les deux LEDS de la carte pour indiquer à l’utilisateur des états d’activité du logiciel. Ce dernier devrait donc éviter d’utiliser D0 et D4 pour des composants intégrés sur les platines de développement.

La manipulation du bouton STOP dans Thonny, pour arrêter l’exécution n’est pas évidente, comme d’ailleurs le Save (Ctrl-S) dans le menu qu’il faut parfois cliquer deux fois pour fonctionner après des corrections de code. Suivant les situations, il faudra parfois retirer le câble et le remettre, voire relancer Thonny. Par contre charger un autre script et l’exécuter sans stopper l’actuel semble bien fonctionner.

Nous pouvons facilement nous imaginer le nombre d’exercice possible en Python, voir avec la librairie PWM (modulation de largeur d’impulsion) comme ici :

from machine import Pin, PWM
import timefrom machine
import Pin from time import sleep

ledblue = Pin(16, Pin.OUT) #bleu
ledgreen = Pin(5, Pin.OUT) #vert
ledred = Pin(4, Pin.OUT) #rouge
ledred.value(0)
ledgreen.value(0)
ledblue.value(0)

pwm = PWM(Pin(4))
for level in range(0, 1023):
time.sleep(.01)
pwm.duty(level)

Le PWM n’est pas disponible sur la broche D0 (GPIO 16) : il faudrait alors faire passer le bleu de la broche D0 à la broche D3 (GPIO 0) par exemple. Cet exemple nous montre notre LED couleur mise au rouge (1013 pour le maximum) qui se fane rapidement jusqu’à s’éteindre (pwm.duty(0)).

Comme pour le script test1.py et les suivants, tous ces scripts ne sont pas téléchargés dans le NodeMCU et il faudra les exécuter à chaque fois. Mais cela permet de les vérifier, d’y ajouter plus de code, d’autres fonctions ou modules, avant une installation pour un démarrage automatique au boot de l’ESP8266, c’est à dire dans le fichier main.py. Nous y viendrons rapidement !

Le script ci-dessus sera vraisemblablement déposé dans un fichier et chargé dans Thonny. Mais un copier/coller dans la fenêtre Shell de ce dernier est tout à fait possible : le code devrait cependant rester simple et une exécution ligne par ligne est recommandée.

Le prochain composant à vérifier, c’est le capteur de température, un LM35.

from machine import ADC
adc = ADC(0) #assigne la broche analogique

def temperature():
value = adc.read()
return value/3.95

celsius_temp = temperature()
print(celsius_temp)

Le def n’est pas vraiment nécessaire, peut-être juste pour montrer au lecteur que l’auteur de cet article sait un petit peu comment écrire une fonction en Python !

Le 3.95 a été défini, après calibration, en déposant un thermomètre à côté de notre platine de prototypage et en vérifiant le résultat. Avec deux doigts sur le LM35, nous pouvons rapidement vérifier que le température augmente ou diminue, mais évidemment pas déterminer si nous sommes fiévreux !

Le 22 degrés est une température juste confortable pour travailler et les chiffres après la virgule pourraient être ignorés, ou mieux, arrondis à une décimal avec la fonction round(celsius_temp, 1). J’ajouterai encore quand déconnectant la platine de démonstration contenant le LM35, j’ai noté une valeur de 2 à la lecture. Un LM35 mal branché pourra aussi être vérifié en le pinçant de deux doigts pour y faire monter la température.

Un script plus sérieux et déposé dans le NodeMCU

Nous allons à présent considérer les aspects suivants :
• intégrer le code des scripts précédents, test2.py et lm35.py pour y faire quelque chose de plus intelligent ;
• ajouter le code nécessaire pour attribuer une adresse IP à notre NodeMCU ;
• y ajouter un serveur Web pour obtenir la température de l’extérieur.

Les trois composants seront vérifiés comme précédemment, et toujours sans télécharger les scripts pour qu’ils soient disponibles au prochain démarrage du NodeMCU.

Trois couleurs différentes suivant la température

Nous présentons le script ControlTemperature.py, que nous préparerons sous Thonny, suivi de quelques explications :

from machine import Pin
from machine import ADC
from time import sleep

ledblue = Pin(16, Pin.OUT) #bleu
ledgreen = Pin(5, Pin.OUT) #vert
ledred = Pin(4, Pin.OUT) #rouge

adc = ADC(0) #LM35 sur l'analogique 0

ledgreen.value(0)
ledblue.value(0)
ledblue.value(1)
sleep(.3)
ledblue.value(0)
ledgreen.value(1)
sleep(.3)
ledgreen.value(0)
ledred.value(1)
sleep(.3)
ledred.value(0)
sleep(1)

while True:
reading = adc.read()
celsius_temp = round(reading/3.95, 1)
print(celsius_temp)

ledgreen.value(0)
ledblue.value(0)
ledred.value(0)

if (celsius_temp) > 24.0:
ledred.value(1)
else:
if (celsius_temp) < 22.0:
ledblue.value(1)
else:
ledgreen.value(1)

sleep(2.0)

Rien de bien sorcier. C’est une composition des scripts précédents avec la lecture de la température. Chaque deux secondes nous coupons la tension GPIO de toutes les broches, pour ne pas mélanger les couleurs, et nous attribuons une couleur dépendante de la température :
• bleu si en dessous 22 degrés ;
• rouge si supérieure à 24 degrés ;
• vert, entre les deux, c’est confortable.

Comme il n’y a ici qu’un seul print(), c’est la seule chose que nous verrons dans le shell de Thonny en l’exécutant, c’est à dire la température en degré Celsius avec une décimale. Nous verrons la LED avec la couleur correcte, couleur qu’il nous est facile de faire passer au rouge avec deux doigts sur le LM35. La mise à jour se fera chaque seconde, c’est suffisant.

Avant de passer au transfert de fichiers MicroPython sur le NodeMCU et en particulier aux boot.py et main.py qui seront exécutés à chaque démarrage, il nous faut revenir un peu au mode REPL et à la configuration Wi-Fi.

Configuration Wi-Fi

Notre application finale, qui aura besoin d’un accès réseau pour transmettre en particulier la température récupérée par un LM35, va nécessiter préalablement la mise en place de sa configuration réseau.
Cette configuration et sa vérification peut très bien être faite du Shell de Thonny voire aussi de PuTTY. Nous noterons ici que le Shell de Thonny permet de copier/coller (Ctrl-C/Ctrl-V) depuis une autre fenêtre Windows et aussi de naviguer sur d’anciennes commandes avec les touches curseur.

import network
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
print('network config:', sta_if.ifconfig())

Il faudra un peu patienter avant de voir la réponse avec l’adresse IP activée (entre temps un 0.0.0.0 serait retourné) :

>>> print('network config:', sta_if.ifconfig())
network config: ('192.168.1.138', '255.255.255.0', '192.168.1.1', '192.168.1.1')

Dans mon cas, j’ai attribué, dans mon routeur Wi-Fi, 192.168.1.138 comme adresse IP statique.

Il serait ensuite possible avec sta_if.active(False) de désactiver l’adresse IP et de, par exemple, nous déplacer dans un autre réseau Wi-Fi ou routeur, en refaisant la même procédure.

Notre application main.py

Thonny nous permet de télécharger des fichiers et des scripts Python sur notre NodeMCU installé avec MicroPython. Ceci se fait avec le menu Device et un des trois sous-menus Upload. Nous commencerons par le premier script décrit ici, le fichier test1.py et ensuite avec main.py et boot.py.

Le main.py est le fichier qui contiendra le code de notre application et qui sera lancé lors de la mise sous tension, s'il existe, et après le script boot.py. Nous déposerons dans ce dernier le code pour initialiser le réseau Wi-Fi.

Nous allons à présent examiner comme accéder le système de fichiers du NodeMCU voire de le modifier. Ayant déposé, avec le menu correspondant de Thonny, le fichier test1.py sur notre NodeMCU, nous pourrons avec le Shell de Python, exécuter les commandes suivantes:

import os
os.listdir()
print(open('test1.py').read())
os.remove('test1.py')
os.listdir()
Typiquement nous devrions retrouver pour la dernière instruction, et plus tard après l'installation des main.py et boot.py qui vont suivre, le résultat de la dernière commande :
>>> os.listdir()
['boot.py', 'main.py']

Précédemment, le read() nous aura montré le contenu de test1.py. La commande remove() effacera le test1.py.

Notre application main.py présentée maintenant est composée des fonctions discutées précédemment:
• test de notre LED ;
• lecture de la température ;
• couleur de la LED en fonction de cette dernière
et nous y ajoutons un serveur Web pour obtenir cette température de l'extérieur.

from machine import Pin
from machine import ADC
from time import sleep
import socket

#import machine
html = """

Temperature

%s


"""

celsius_temp = 10.0

ledblue = Pin(16, Pin.OUT) #bleu
ledgreen = Pin(5, Pin.OUT) #vert
ledred = Pin(4, Pin.OUT) #rouge

adc = ADC(0) #LM35 sur l'analogique 0

ledgreen.value(0)
ledblue.value(0)
ledblue.value(1)
sleep(.3)
ledblue.value(0)
ledgreen.value(1)
sleep(.3)
ledgreen.value(0)
ledred.value(1)
sleep(.3)
ledred.value(0)
sleep(1)

addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
s = socket.socket()
s.bind(addr)
s.listen(1)

while True:
#print('Boucle ')
s.settimeout(2)
try:
conn, addr = s.accept()
except OSError as er:
pass
#print(er.args[0] in (110, 'timed out'))
# 110 is ETIMEDOUT
else:
#print('Client connecté de ', addr)
conn_file = conn.makefile('rwb', 0)
while True:
line = conn_file.readline()
#print('Line ', line)
if not line or line == b'\r\n':
break

response = html % celsius_temp + '\n'
#print('Client receives ', response)
conn.send('HTTP/1.1 200 OK\n')
conn.send('Content-Type: text/html\n')
conn.send('Connection: close\n\n')
conn.sendall(response)
conn.close()
conn.close()

reading = adc.read()
celsius_temp = round(reading/3.95, 1)
#print(celsius_temp)

ledgreen.value(0)
ledblue.value(0)
ledred.value(0)

if (celsius_temp) > 24.0:
ledred.value(1)
else:
if (celsius_temp) < 22.0:
ledblue.value(1)
else:
ledgreen.value(1)

Comme pour les scripts précédents, nous vérifierons le script de la même manière, depuis Thonny, et avant de le télécharger. Un certain nombre de print(), ici en commentaire, nous permettraient de vérifier le bon fonctionnement du script.
La variable html est typique d’une page Web vraiment simple, juste pour nous retourner la température où le %s sera remplacé par la valeur de celsius_temp qui sera de 10.0 degrés au démarrage et immédiatement corrigée après 2 secondes dans la boucle while True. Les deux secondes viennent du s.settimeout(2) sur le socket du port 80 (Web).

Le MicroPython de l’ESP8266 n’ayant pas de support Thread, c’est une manière de faire un peu simpliste, mais suffisante, pour cette application. Une requête http://192.168.1.138/ devra patienter jusqu’à 2 secondes avant de recevoir la dernière température. Au timeout la température sera mise à jour comme la couleur de la LED.

L’adresse IP 0.0.0.0 est une adresse réservée indiquant ce site et ce réseau. Avec 0.0.0.0 nous écouterons sur tous les réseaux d’interface configurés.

L’instruction s.accept() est assez particulière pour les débutants en Python, car elle nous retourne une paire de valeur, conn et adress, un tuple : le premier est la référence d'un nouvel objet de la classe socket(), qui sera la véritable interface de communication entre le client et le serveur, et le second un autre tuple contenant les coordonnées de ce client (son adresse IP et son numéro de port utilisé).

Dès qu’un client sur le port 80 demande un accès, nous lisons toute la requête en ignorant ici les paramètres. Si nous jouons, avec par exemple http://192.168.1.138/temperature, nous recevrons toujours la même réponse envoyée avec les différents conn.send() qui spécifient le protocole et la réponse. Le conn.sendall() est identique à conn.send() mais attend que tout soit envoyé. La send('Connection: close\n\n') est intéressante : elle indiquera que la connexion n’est pas persistante après l’envoi de la réponse : notre température « emballée » dans des balises HTML.

Il y aurait du travail pour implémenter le passage dans une requête Web pour nos deux limites de température, ici fixées à 22 et 24 degrés, pour les intégrer dans le script main.py voire stockées dans un fichier de configuration de l’ESP8266.

Notre script de démarrage boot.py

Nous déposerons le code réseau pour le Wi-Fi dans le fichier Python boot.py :

def do_connect():
sta_if = network.WLAN(network.STA_IF)
if not sta_if.isconnected():
print('connecting to network...')
sta_if.active(True)
sta_if.connect('routeur', 'mot_de_passe')
while not sta_if.isconnected():
pass
print('network config:', sta_if.ifconfig())

do_connect()
Nous le vérifierons tout d’abord avec le shell :
>>> %Run boot.py
network config: ('192.168.1.138', '255.255.255.0', '192.168.1.1', '192.168.1.1')

La fonction do_connect() devra être modifiée en y mettant le nom et le mot de passe du routeur. Comme je le fais pour mes composants IOT, après l’attribution de l’adresse IP, ici ce 192.168.1.138, j’utilise l’accès Web du routeur pour y attribuer le mode statique. Ce sera plus facile pour retrouver ce NodeMCU parmi une pléthore d’objets connectés.

La variable sta_if est utilisée avec la classe WLAN pour obtenir une connexion au routeur et en passant à la fonction connect() le SSID (le nom du réseau, le routeur) et son mot de passe.

Ensuite nous utiliserons le menu Device avec « Upload current script as boot script ». Le menu Device possède deux sous-menus pour visionner nos deux boot.py et main.py. Nous débrancherons et reconnecterons le câble USB pour vérifier l’installation, que la LED change de couleur en la touchant de deux doigts, et que la requête http://192.168.1.138/ nous retourne des valeurs différentes.

En cas de difficultés, nous pourrions toujours remettre quelques print() dans le code, voire utiliser PuTTY. Pour utiliser ce dernier, il faudra rebrancher le câble pour avoir une session correcte dans PuTTY. Un Ctrl-C dans sa console permettrait d’interrompre le script main.py, avec ces conséquences, et de retravailler en mode REPL. Le lecteur comprendra vite que notre Thonny est bien agréable à utiliser.

Enfin un peu de Java

Ma passion et mon attachement restant toujours la programmation Java, je n’ai pas hésité à écrire une petite classe Java pour récupérer la température de cet objet connecté qu’est notre NodeMCU :

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;

public class NodeMcuWebRead {
public static void main(String[] args) throws IOException {
URL url = new URL("http://192.168.1.138");
BufferedReader in = new BufferedReader(
new InputStreamReader(url.openStream()));

String inputLine;
float temperature = (float)0.0;
int lineNb = 0;
while ((inputLine = in.readLine()) != null) {
if (lineNb == 4) {
inputLine = inputLine.replaceAll("\\s+","");
temperature = Float.parseFloat(inputLine);
System.out.println(temperature);
break;
}
lineNb++;
}
in.close();
}
}

Ce code pourra être compilé et déposé sur n’importe quel PC ou système embarqué, comme un Raspberry Pi (avec Java 8), voire un NAS et là où une machine virtuelle Java est disponible et installée.

En utilisant un explorateur Internet à l’adresse http://192.168.1.138/ et en examinant le code source (bouton droite de la souris sous Chrome et Firefox) nous retrouverons notre température sur la 5-ième ligne du code HTML. Nous retirerons les espaces avant une conversion en float.

Nous pourrions par exemple étendre cette mini-classe en une classe lisant régulièrement la température pour :
• enregistrer la température chaque minute dans une table de base de données SQLite, aussi créée avec sa table dans cette même classe ;
• calculer les moyennes horaires et journalières et les déposer dans deux autres tables SQLite ;
• y ajouter d’autres NodeMCU pour des statistiques de températures mesurées à différents endroits de la maison, voire de l’extérieur ;
• développer un Web serveur en Java pour montrer ces informations sous différentes formes ;
• envoyer chaque jour ou semaine un courriel avec ces informations de statistique ;
• créer un système d’alarme pour indiquer un problème de température lié aux limites de température précédemment discutée et en permettant au NodeMCU d’accepter de nouvelles valeurs limites.

C'est parti pour l'apprentissage de Python

Ce n'est pas le but de cet article, mais nous voyons bien que nous avons ici une infrastructure idéale pour l'apprentissage du langage Python.

Nous pourrions commencer par des variables, qui pourraient par exemple représentées l'intensité d'une ou de plusieurs couleurs de la LED. Des tests de conditions suivant la valeur de la température, ou de petits jeux de variations d'intensité ou de couleurs, sont facile à imaginer et à développer sous Thonny.

En fonction des thèmes de l'apprentissage de Python, il serait alors facile de mettre en place une série d'exercices évolutifs, comme par exemple, l'implémentation, qui me semble incontournable, d'une classe Python, LedColor, contenant toutes les fonctionnalités sorties de notre imagination.

Apprendre Java et Python en parallèle

Dès que nous parlons de classe, ici de LedColor, il nous viendrait vite à l’esprit d’écrire aussi une jolie classe en Java, sous Eclipse, pour un Raspberry Pi, avec la même LED, mais un Dallas DS18B20 digital pour remplacer notre LM35 analogique, car le Pi n’a pas d’interface analogique.