Configurer la carte NodeMCU v3 en tant que point d'accès WiFi

Dans un article précédent, Guillaume explique comment prendre en main la carte NodeMCU et la configurer comme serveur web connecté en wifi: A la découverte du NodeMCU / ESP8266.

Cela fonctionne très bien, mais cela nécessite de connecter la carte NodeMCU à un réseau WiFi, puis d'identifier l'adresse IP de cette carte car elle peut varier (DHCP), se connecter à partir d'un smartphone sur le même réseau wifi et enfin se connecter par un navigateur web à cette adresse IP. Le système est donc dépendant d'un réseau wifi externe et de son allocation d'adresse IP.

Ce que je vous propose est une variante qui consiste à configurer le nodeMCU comme point d'accès Wifi. Ainsi, on peut se connecter à partir d'un smartphone à ce point d'accès et accéder via le navigateur web à une page de commande. Le système est donc autonome.

Comme d'habitude on va commencer avec une led pour démontrer les concepts. L'objectif de cette exemple est de configurer la carte NodeMCU comme point d'accès WiFi, de s'y connecter à partir d'un smartphone, et via le navigateur web, d'accéder à une page qui permet d'allumer et éteindre une diode. Evidemment, l'exemple peut être adapté, par exemple pour commander à distance un véhicule ou un robot.

On commence donc par un montage simple d'une led connectée à la borne D1 de la carte NodeMCU.

img_0669.jpg

Le principe est le suivant:
La carte NodeMCU va être configurée en point d'accès WiFi, sur lequel va se connecter un smartphone.
La carte NodeMCU affiche sur l'adresse “192.168.4.1” une page Web avec 2 boutons “On” et “Off”.
Lorsque l'on clique sur le bouton “On”, cela appelle une autre page “192.168.4.1/on”.
La carte NodeMCU écoute les requêtes sur cette page “192.168.4.1/on”, et lorsqu'elle en détecte une, allume la led.
—Note: Comme vous l'avez compris, on obtient le même résultat (la led s'allume) en affichant la page “192.168.4.1/on” au lieu de cliquer sur le bouton “On”.
Lorsque l'on clique sur le bouton “Off”, cela appelle une autre page “192.168.4.1/off”.
La carte NodeMCU écoute les requêtes sur cette page “192.168.4.1/off”, et lorsqu'elle en détecte une, éteins la led.

Le code Arduino est dans la section suivante. Commencez par le télécharger, le compiler et le téléverser vers votre carte NodeMCU. Branchez ensuite votre carte NodeMCU à une source d'alimentation.

Sur votre smartphone, connectez vous au réseau APTEST, saisissez le mote de passe, et dans un navigateur web, enrez l'URL 192.168.4.1.

Et en cliquant sur le bouton On, la led s'allume.

img_0668_1.jpg


J'utilise Arduino IDE pour programmer la carte NodeMCU. Je considère que vous avez lu les articles de Guillaume pour savoir charger un programme Arduino sur la carte NodeMCU.

On commence par les librairies et variables globales.
Le point d'accès que nous allons configurer s'appelle ci-dessous APTEST et a comme mot de passe 12345678. Bien sûr vous pouvez changer cela.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>

// Se connecter au réseau WiFi APTEST avec le mot de pase 12345678
// Puis aller sur http://192.168.4.1 dans un navigateur web
const char *ssid = "APTEST";
const char *password = "12345678";
WiFiServer server(80);

Gestion de la led, sur broche D1 de la carte NodeMCU, avec 2 fonctions pour allumer et éteindre.

const byte LED_PIN = 5; // Branchement NodeMCU D1 --> Led --> Ground
// Allume la led
void led_on(){
Serial.println("Led on");
digitalWrite(LED_PIN, HIGH);
}
// Eteins la led
void led_off(){
Serial.println("Led off");
digitalWrite(LED_PIN, LOW);
}

Fonction d'affichage de la page d'accueil.
Pas facile à lire car code HTML + javascript au milieu du code Arduino. Mais prenez votre temps, ce n'est pas si compliqué. Si on commence par le bas, on voit 2 boutons dans une table HTML qui appellent les fonctions correspondantes en javascript, pour envoyer des requêtes HTTP.
Pensez à relire le paragraphe qui décrit le principe de fonctionnement.

// Affichage de la page d'accueil
// Code javascript pour appeler les fonctions on et off
// Tableau html pour les 2 boutons
// Bouton "On"  (html) --> appelle fonction "on()"  (javascript) --> envoie requete "192.168.4.1/on"
// Bouton "Off" (html) --> appelle fonction "off()" (javascript) --> envoie requete "192.168.4.1/off"
String homepage() {
  String s;
  s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html><body>\r\n";
  s +="<script language='javascript' type='text/javascript'>\r\n";
  s +="<!--\r\n";
  s +="function on()  { var xhr = new XMLHttpRequest(); xhr.open('GET', '/on',  true); xhr.send();}\r\n";
  s +="function off() { var xhr = new XMLHttpRequest(); xhr.open('GET', '/off', true); xhr.send();}\r\n";
  s +="//-->\r\n";
  s +="</script>\r\n";
  s +="<table align='center' style='cursor: pointer;'><tr>\r\n";
  s +="<td height='100' width='100' bgcolor='#f45942' align='center'><font size='20'><div onclick='off();'>Off</div></font></td>\r\n";
  s +="<td height='100' width='100' bgcolor='#41f492' align='center'><font size='20'><div onclick='on();'>On </div></font></td>\r\n";
  s += "</tr></table></body></html>\r\n";
  return s;
}

Une fonction utile pour trouver une chaîne de caractère au sein d'une autre.

boolean matchcommand(String req,String command){
  if (req.indexOf(command) != -1){
    return true;
  } else {
    return false;
  }
}

Et maintenant que fonctions et variables sont définies, on passe à la fonction setup().
Configuration de la broche D1, et du point d'accès.

void setup() {
  delay(1000);
  Serial.begin(115200);

  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);

  Serial.println();
  Serial.println("Configuring access point...");
  WiFi.mode(WIFI_AP);
  WiFi.softAP(ssid, password);

  IPAddress myIP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(myIP);
  server.begin();
  Serial.println("HTTP server started");

}

Et enfin, on termine par la fonction loop().
Le code es commenté et se lit bien.

void loop() {

  // Vérifie si client se connecte
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
  // Attends que le client envoie des données
  Serial.println("new client");
  while(!client.available()){
    delay(1);
  }

  // Affiche la page d'accueil 192.168.4.1
  client.print(homepage());

  // Lit la premiere ligne de la requete
  String req = client.readStringUntil('\r');
  Serial.println(req);
  client.flush();
  if (matchcommand(req,"off")){
    // requête 192.168.4.1/off --> éteins led
    led_off();
  }
  else if (matchcommand(req,"on")){
    // requête 192.168.4.1/on --> allume led
    led_on();
  }
      else {
  Serial.println("invalid request");
  client.stop();
  return;
  }
  client.flush();
}

et voilà le code est fini !