Mise en oeuvre du module NodeMCU Lolin ESP8266

L’objectif est de mettre en oeuvre le module NodeMCU Lolin ESP 8266.

L’ESP8266

L’ESP8266 est un circuit intégré à microcontrôleur (32-bit RISC CPU Tensilica Xtensa LX106 à 80 MHz) avec connexion WiFi développé par le fabricant chinois Espressif.

L’ESP8266 peut se programmer de plusieurs façons :

Remarques : il existe aussi des possibilités avec Javascript et Python.

Le module NodeMCU Lolin ESP8266

Site : www.az-delivery.de

Le module est une LoLin du fabricant WeMos.

Documentations NodeMCU :

Détection matérielle

Sous GNU/Linux :

$ dmesg
...
[1134900.516184] usb 3-9.2: new full-speed USB device number 41 using xhci_hcd
[1134900.533375] usb 3-9.2: New USB device found, idVendor=1a86, idProduct=7523
[1134900.533377] usb 3-9.2: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[1134900.533379] usb 3-9.2: Product: USB2.0-Serial
[1134901.596435] usbcore: registered new interface driver usbserial
[1134901.596448] usbcore: registered new interface driver usbserial_generic
[1134901.596457] usbserial: USB Serial support registered for generic
[1134901.599420] usbcore: registered new interface driver ch341
[1134901.599432] usbserial: USB Serial support registered for ch341-uart
[1134901.599443] ch341 3-9.2:1.0: ch341-uart converter detected
[1134901.600386] usb 3-9.2: ch341-uart converter now attached to ttyUSB0

$ lsusb
...
Bus 003 Device 041: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adapter

$ python esptool.py --port /dev/ttyUSB0 flash_id
esptool.py v2.3-dev
Connecting....
Detecting chip type... ESP8266
Chip is ESP8266EX
Uploading stub...
Running stub...
Stub running...
Manufacturer: 5e
Device: 4016
Detected flash size: 4MB
Hard resetting...

Ce module utilise une puce CH340G pour la communication USB.

Remarque : Il est possible de relier un adaptateur USB/TTL sur les broches VIN (5V min), GND, TX0 (Blanc) et RX0 (Vert).

Flasher le module

Pour flasher le firmware, il faut installer esptool :

$ git clone https://github.com/themadinventor/esptool.git

$ cd esptool
$ python setup.py install
$ esptool.py --port /dev/ttyUSB0 write_flash --flash_mode qio --flash_size 4MB 0x00000 [firmware].bin

// ou :
$ python esptool.py --port /dev/ttyUSB0 write_flash --flash_mode qio --flash_size 4MB 0x00000 [firmware].bin

Firmware :

Commandes AT

A la livraison, le module est livré avec un firmware qui supporte les commandes AT.

Lien : ESP8266_AT_Command.pdf

Avec cutecom (115200) :

ready

AT+GMR
AT version:1.1.0.0(May 11 2016 18:09:56)
SDK version:1.5.4(baaeaebb)
compile time:May 20 2016 15:08:19


AT+CIPSTAMAC?
+CIPSTAMAC:"ec:fa:bc:14:40:8d"


AT+CIPSTA?
+CIPSTA:ip:"0.0.0.0"
+CIPSTA:gateway:"0.0.0.0"
+CIPSTA:netmask:"0.0.0.0"


AT+CWMODE=3


AT+CWMODE?
+CWMODE:3


AT+CWLAP
+CWLAP:(0,"orange",-90,"06:19:70:4c:a6:65",1,-16,0)
+CWLAP:(4,"Beauregard",-29,"2c:39:96:21:d3:62",11,11,0)
+CWLAP:(0,"orange",-30,"1e:39:96:21:d3:62",11,11,0)


AT+CWJAP="Beauregard","password"
WIFI CONNECTED
WIFI GOT IP


AT+CIPSTA?
+CIPSTA:ip:"192.168.52.27"
+CIPSTA:gateway:"192.168.52.1"
+CIPSTA:netmask:"255.255.255.0"


AT+CIFSR
+CIFSR:APIP,"192.168.4.1"
+CIFSR:APMAC,"ee:fa:bc:14:40:8d"
+CIFSR:STAIP,"192.168.52.27"
+CIFSR:STAMAC,"ec:fa:bc:14:40:8d"


AT+CWQAP
WIFI DISCONNECT

Voir aussi :

  • AT+CWSAP : Configuration du mode softAP
  • AT+CWDHCP : Active ou désactive DHCP
  • AT+ CIPAP : Configuration de l’adresse IP en mode softAP

Exemple de communication :

  1. Client TCP

Préparation du module :

AT+CWMODE=3
AT+CWJAP="Beauregard","password"
AT+CIPSTA?
+CIPSTA:ip:"192.168.52.27"
+CIPSTA:gateway:"192.168.52.1"
+CIPSTA:netmask:"255.255.255.0"

Démarrer avec netcat un serveur TCP sur le port 5000 sur une machine GNU/Linux :

$ nc -l -p 5000

Ouvrir une connexion TCP à partir du module et envoyer des données (CRLF à la fin) :

AT+CIPMUX=0
AT+CIPSTART="TCP","192.168.52.2",5000
AT+CIPSEND=4
>ok

Remarques :

  • Si le module reçoit des données, on aura une trame AT +IPD,n:xxxxxxxxxx avec n pour le nombre d’octets reçus et xxxxxxxxxx les données.
  • La commande AT+CIPSTART peut aussi être utilisée pour le protocole UDP.

Fermer la communication :

AT+CIPCLOSE
  1. Serveur TCP

Il faut activer les connexions multiples :

  • 0 : single connection
  • 1 : multiple connection
AT+CIPMUX=1

Puis démarrer un serveur sur le port 5001 pour le module :

AT+CIPSERVER=1,5001

Utiliser un client netcat pour vous connecter au serveur :

$ nc 192.168.52.27 5001
blabla...

Et on peut aussi envoyer des données (CRLF à la fin) :

AT+CIPSEND=0,4
> ok
  1. UART-WiFi passthrough

Le module ESP8266 peut fonctionner en UART-WiFi passthrough. Ce mode ne peut être activé que lorsque l’ESP8266 fonctionne en tant que client TCP ou en UDP. On configure ce mode avec la commande AT+CIPMODE.

Lien : esp8266_at_command_examples_en.pdf

Lua

L’ESP8266 peut aussi se programmer avec des scripts Lua avec le firmware NodeMCU.

Avec cutecom (115200) :

NodeMCU 0.9.6 build 20150704  powered by Lua 5.1.4
lua: cannot open init.lua
>
> led1 = 4
> gpio.mode( led1, gpio.OUTPUT )
> gpio.write( led1, gpio.LOW)
> gpio.write( led1, gpio.HIGH )

Arduino

L’ESP8266 peut aussi se programmer en C++ avec l’IDE Arduino (Linux).

Aller dans Fichier -> Préférences :

Puis dans Outils -> Type de cartes -> Gestionnaire de cartes, il faut installer la carte ESP8266 :

On termine par sélectionner la carte :

Il existe de nombreux exemples fournis avec l’ESP8266.

  1. Test WiFi :
#include "ESP8266WiFi.h"

void setup() 
{
  Serial.begin(115200);  
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(2000);
}

void loop() {

  int n = WiFi.scanNetworks();

  if (n > 0)
  {
    for (int i = 0; i < n; ++i)
    {
      Serial.print(i + 1);
      Serial.print(": ");
      Serial.print(WiFi.SSID(i));
      Serial.print(" (");
      Serial.print(WiFi.RSSI(i));
      Serial.print(")");
      Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE)?" ":"*");
      delay(10);
    }
  }
  Serial.println("");

  delay(5000);
}
  1. Serveur Web :

Code source : WebServeur.zip

#include "Serveur.h"

Serveur serveur; //serveur(80);

void setup() 
{
  Serial.begin(115200);
  serveur.demarrer();
}

void loop() 
{
  serveur.traiterRequete();
}

Avec une classe Serveur :

#ifndef SERVEUR_H
#define SERVEUR_H

#include <ESP8266WiFi.h>
#include <WiFiServer.h>

static const char* ssid = "Beauregard";
static const char* password = "password";

class Serveur : public WiFiServer
{
  private:
    int ledPin2; // Led bleue
    int etatLed;
    
    void demarrerWiFi();
    void demarrerServeur();
    void envoyerPageAccueil(WiFiClient &client);
  
  public:
    Serveur(uint16_t port=80);
    virtual ~Serveur() {}
    
    void demarrer();
    void traiterRequete();
};

#endif
#include "Serveur.h"

Serveur::Serveur(uint16_t port/*=80*/) : WiFiServer(port)
{
  ledPin2 = 02; // Led bleue  
  pinMode(ledPin2, OUTPUT);
  etatLed = LOW;
  digitalWrite(ledPin2, etatLed);
}

void Serveur::demarrer()
{
  demarrerWiFi();
  demarrerServeur();
}

void Serveur::traiterRequete()
{
  WiFiClient client = available();
  if (!client) 
  {
    return;
  }
  
  Serial.print("Requête client ");
  while(!client.available())
  {
    delay(1);
  }
  Serial.println(client.remoteIP());  
  
  //String requete = client.readStringUntil('\r');  
  //Serial.println(requete);
  //client.flush();

  String requete;
  while(client.available())
  {
    String ligne = client.readStringUntil('\r');
    Serial.print(ligne);
    requete += ligne;
  }
  client.flush();

  if(requete.indexOf("GET") != -1)
  {
    envoyerPageAccueil(client);    
  }
  else if(requete.indexOf("POST") != -1)
  {
      if(requete.indexOf("led") != -1)
      {          
        if(requete.indexOf("led=0") != -1)
        {
          etatLed = HIGH;
          digitalWrite(ledPin2, etatLed);  
        }
        else if(requete.indexOf("led=1") != -1)
        {
          etatLed = LOW;
          digitalWrite(ledPin2, etatLed);
        }
        envoyerPageAccueil(client);    
      }
  }
  else 
  {
    Serial.println("Requête invalide !");
    client.stop();
    return;
  }
  
  Serial.println("");
}

void Serveur::demarrerWiFi()
{
  Serial.println("");
  Serial.println("");
  Serial.print("Connexion au réseau WiFi ");
  Serial.println(ssid);
  
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Adresse IP du serveur : ");
  Serial.println(WiFi.localIP());  
}

void Serveur::demarrerServeur()
{  
  begin();
  Serial.println("Démarrage du serveur Web");
  Serial.println("");
}

void Serveur::envoyerPageAccueil(WiFiClient &client)
{  
  String reponse = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nPragma: no-cache\r\n\r\n<!DOCTYPE HTML>\r\n";
  reponse += "<html>\n";
  reponse += "<head>\n";
  reponse += "<title>Serveur ESP8266</title>\n";
  reponse += "</head>\n";
  reponse += "<body>\n";
  reponse += "<h1>Bienvenue sur le serveur ESP8266 WiFi !</h1>\n";
  reponse += "<p>\n";
  reponse += "<form method=\"POST\">\n";  
  if (etatLed == LOW) 
  {
    reponse += "<p><input type=\"radio\" id=\"led\" name=\"led\" value=\"0\" />LED off\n";
    reponse += "<br /><input type=\"radio\" id=\"led\" name=\"led\" value=\"1\" checked />LED on</p>";
    
  } 
  else 
  {
    reponse += "<p><input type=\"radio\" id=\"led\" name=\"led\" value=\"0\" checked>LED off</input>\n";
    reponse += "<br /><input type=\"radio\" id=\"led\" name=\"led\" value=\"1\">LED on</input></p>";
  }
  reponse += "<p><input type=\"submit\" /></p>\n";
  reponse += "</form>\n";
  reponse += "</p>\n";
  reponse += "</body>\n";
  reponse += "</html>\n";

  client.flush();
  client.print(reponse);
  //delay(1);  
}

On obtient :

  • Côté serveur web :
  • Côté client web :
Connexion au réseau WiFi Beauregard
.
Adresse IP du serveur : 192.168.52.8
Démarrage du serveur Web

Requête client 192.168.52.2
GET / HTTP/1.1
Host: 192.168.52.8
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1


Requête client 192.168.52.2
POST / HTTP/1.1
Host: 192.168.52.8
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://192.168.52.8/
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 5

led=0

Requête client 192.168.52.2
POST / HTTP/1.1
Host: 192.168.52.8
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://192.168.52.8/
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 5

led=1

Tutoriels

Retour au sommaire