L'ESP8266, un Arduino avec Wifi pour 2€ ?

Présentation

Il y a encore peu de temps, pour offrir des capacités de connexion Wi-Fi à nos Arduinos, il nous fallait acquérir un shield dédié. Il nous en coûtait quelques dizaines d'euros. Ce tarif prohibitif en a calmé plus d'un.

Mais ça, c'était avant. Courant 2014, un nouveau venu dans le monde des micro-controlleurs a complètement changé la donne. Il s'agit de l'ESP8266. L'ESP8266 est un module Wi-Fi qui peut être utilisée de deux manières :

Cet article est une présentation générale de l'ESP8266. Pour aller plus loin et commencer à en tirer vraiment partie, vous pouvez consultez les autes articles de ce site qui lui sont consacrés, notamment:

Les différentes versions

Il existe plus de 10 versions différentes de l'ESP8266. Toutes ces versions utilisent en réalité le même microcontroleur. Ce qui les différencie c'est le nombre de PINs accessibles, le type d'antenne, ou encore la quantité de mémoire Flash. Nous nous focalisons ici sur 2 des ces modules : l'ESP-01 et l'ESP-12.

Voici les principales différences entre les deux :

 
 
ESP8266 ESP-01

ESP8266 ESP-012
Nombre de GPIO 2 12
Entrée analogique (ADC) Aucune 1
Dimensions 24.75mm x 14.5mm 24mm x 16mm
Prix 1,81€ 2,35€
 

Les caractéristiques communes à toutes les versions :


Notre préférence va nettement à la version ESP-12 en raison du nombre de GPIOs disponibles, ainsi que pour la présence d'une entrée analogique ADC. Par contre il vous faudra jouer du fer à souder avec cette version car les connecteurs ne respectent pas l'espacement standard de 2,54mm. Deux solutions : soit vous gravez votre PCB avec les espacements qui vont bien, soit vous utilisez un adaptateur comme celui là : adaptateur pins ESP8266 ESP-12.

Utilisation

Comme nous l'avons vu en introduction, l'ESP8266 peut s'utiliser de différentes façons. À sa sortie, la puce ne pouvait être utilisée que comme module Wi-Fi "périphérique", associé à autre microcontrôleur. Fin 2014, Espressif (le constructeur à l'origine du module) a mis à disposition de la communauté un SDK, qui a rendu possible l'utilisation de l'ESP8266 comme microcontrolleur totalement autonôme. Intéressons-nous d'abord au premier cas. Nous n'y consacrerons qu'une brêve introduction car ce n'est à notre sens clairement pas ce qui est le plus intéressant à faire avec l'ESP8266. Si vous voulez passer cette étape et apprendre directement à programmer l'ESP8266 sans passer par un Arduino, consultez cet article: Programmer l'ESP8266 avec l'IDE Arduino.

Utilisation comme périphérique d'un autre microcontrôleur

Pour illustrer nos propos, nous allons utiliser un ESP8266 en version ESP-01, et un Arduino Nano. L'Arduino et l'ESP8266 communiqueront par liaison série.

La liste de courses :

Désignation Prix unitaire Quantité Prix

Résistance 10k Ohm

Résistance de 10k Ohm

0.01 €

sur Ebay, ici

1 0.01 €

ESP8266 ESP-01

Module Wi-Fi ESP8266, version ESP-01

1.69 €

sur Ebay, ici

1 1.69 €

Arduino Nano

L'Arduino, version miniature

2.76 €

sur Banggood, ici

1 2.76 €

Platine d'essais

Platine de prototypage, ou breadboard

1.3 €

sur Banggood, ici

1 1.3 €

Résistance 20k Ohm

Résistance 20k Ohm

0.01 €

sur Ebay, ici

1 0.01 €
total 5.77 €

Le cablage

La seule difficultée ici est liée au fait que notre Arduino fonctionne en 5v, alors que l'ESP8266 fonctionne lui en 3.3v. On réalisera les branchements suivants :

Pin Arduino Pin ESP8266 Remarque
3.3v VCC -
GND GND -
D10 RX L'ESP8266 ne doit pas recevoir de 5v sur ses pins.
Nous devons donc ici convertir le signal 5v en 3.3v.
D11 TX L'ESP8266 va envoyer un signal 3.3v à l'Arduino, qui lui est sensé recevoir du 5v.
Dans la pratique il semble que l'Arduino considère le 3.3v comme un niveau haut,
donc cela fonctionne, même si ce n'est pas très propre.
3.3v CH_PD La pin CH_PD doit être au niveau haut pour que le module fonctionne

Pour convertir le signal 5v sortant de la pin TX de l'Arduino en 3.3v, nous allons faire au plus simple en utilisant deux résistances pour créer un diviseur de tension.

 

Diviseur de tension 5v - 3.3v

 

En utilisant une résistance R1 de 10kOhm et une résitance R2 de 20kOhm, nous obtenons :

Vin x R2 / (R1 + R2) = 5 x 20000 / (20000 + 10000) = 3.3v

Voilà ce que ça donne sur une platine d'essais:


Reste à écrire le programme Arduino qui va envoyer des commandes à notre ESP8266.

Les commandes Hayes (ou AT)

Pour communiquer avec l'ESP8266, nous devons utiliser un jeu de commandes Hayes, encore appelées commandes AT. C'est un langage développé à l'origine pour le modem Hayes Smartmodem 300, qui a ensuite été utilisé par presque tous les modems du marché.

Commençons par faire quelques tests grâce au programme suivant:

#include <SoftwareSerial.h>

// On crée une communication série software pour l'ESP8266
SoftwareSerial espSerial(10, 11); // RX, TX

void setup() {
  // On ouvre une communication serie hardware pour les messages destines au moniteur série
  Serial.begin(57600);

  // On ouvre la communication serie software pour l'ESP8266
  espSerial.begin(57600);
  
  Sleep(1000);
  Serial.println("Pret.");
}

void loop() { 
  // si l'ESP8266 a quelque chose a nous dire, on ecrit son message sur le moniteur série
  if (espSerial.available()) {
    Serial.write(espSerial.read());
  }

  // si quelque chose a été saisi dans le moniteur série, on l'envoie à l'ESP8266
  if (Serial.available()) {
    espSerial.write(Serial.read());
  }
}

Avec ce programme, l'Arduino va servir de relai entre le moniteur série de notre IDE et l'ESP8266. Tout ce que nous saisirons dans le moniteur série sera transmis au module Wi-Fi, et toutes les réponses du module Wi-Fi seront affichées dans le moniteur série. Vous noterez qu'on utilise ici 2 liaisons série : une pour la communication moniteur série - Arduino, et une autre pour la communication Arduino - ESP8266. L'Arduino Nano ne disposant que d'une seule interface série hardware, nous utilisons la librairie SoftwareSerial, qui permet de créer des interfaces série en utilisant les GPIOs.

Faisons un premier test. Uploadez le programme, puis ouvrez le moniteur série de l'IDE Arduino. Dans la zone de saisie, entrez la commande suivante:

AT

Vous devriez avoir la réponse suivante :

OK

Cette commande "AT" permet de vérifier que nous arrivons à communiquer avec le module. Essayons autre chose, tappez :

AT+GMR

Vous devriez obtenir quelque chose ressemblant à ça :

00200.9.5(b1)

Ce "AT+GMR" renvoie la version du firmware installé sur le module.

Voici un tableau récapitulatif des principales commandes AT:

Commande Description
AT Ne fait rien, à part renvoyer "OK"
AT+GMR Retourne la version du firmware
AT+RST Redémarre le module
AT+CWMODE Permet de choisir le mode Wi-Fi à utiliser:
  • AT+CWMODE=1: mode station (utiliser ce mode pour se connecter à un réseau Wi-Fi existant)
  • AT+CWMODE=2: mode AP (Access Point: utiliser ce mode pour créer un nouveau réseau Wi-Fi)
  • AT+CWMODE=3: les deux
AT+CWLAP Retourne la liste des réseaux Wi-Fi à portée
AT+CWJAP Connection à un réseau Wi-Fi. Cette commande prend deux paramètres : le SSID du réseau, et le mot de passe.
Par exemple: AT+CWJAP="Livebox-1234","MonMotDePasseWifi"
AT+CIFSR Une fois la module connecté à un réseau, cette commande permet de récupérer son adresse IP

Avec tout ça on est en mesure de se connecter à un réseau Wi-Fi, ou même d'en créer un. L'étape suivante est d'utiliser cette connexion pour envoyer et/ou recevoir des données. Pour ça, on utilisera les commandes suivantes :

Commande Description
AT+CIPSTART Initialise une connexion.
AT+CIPMUX Permet de choisir si on veut pouvoir gérer plusieurs connexions simultanément ou pas:
  • AT+CIPMUX=0: une seule connexion
  • AT+CIPMUX=1: plusieurs connexions
AT+CIPSTART Initialise une connexion. Deux cas, en fonction de ce que vous avez choisi pour AP+CIPMUX:
  • si CIPMUX=0: AT+CIPSTART prend 3 paramètres: le type (TCP ou UDP), l'IP, et le port. Par exemple: AT+CIPSTART="TCP",192.168.0.5,80
  • si CIPMUX=1: AT+CIPSTART a un paramètre suplémentaire qui est le numéro de la connexion à utiliser (entre 0 et 4). On a donc: le numéro de la connexion, le type (TCP ou UDP), l'IP, et le port. Par exemple: AT+CIPSTART=1,"TCP",192.168.0.5,80
AT+CIPSEND Démarre l'envoie de données sur une connexion. Ici aussi, deux cas, en fonction de ce que vous avez choisi pour AP+CIPMUX:
  • si CIPMUX=0: AT+CIPSTART prend un seul paramètre: le nombre de caractères à envoyer. Par exemple: AT+CIPSEND=10
  • si CIPMUX=1: AT+CIPSTART a un paramètre suplémentaire qui est le numéro de la connexion à utiliser (entre 0 et 4). On a donc: le numéro de la connexion, et le nombre de caractères. Par exemple: AT+CIPSEND=1,10
Pour envoyer le message à proprement parler, on écrira sur la liaison série à la suite de cette commande. Par exemple:
AT+CIPSEND=18
GET / HTTP/1.0\r\n\r\n        
AT+CIPCLOSE Ferme une connexion. Si CIPMUX=0, ne prend pas de paramètre. Si CIPMUX=1, prend en paramètre le numéro de connexion à fermer. Par exemple: AP+CIPCLOSE=1

Exemple complet: appeler une URL

#include <SoftwareSerial.h>
  
SoftwareSerial softSerial(10, 11); // RX, TX
String SSID = "Livebox-1234";  // SSID du réseau Wi-Fi
String PASS = "MonMotDePasseWiFi"; // Mot de passe Wi-Fi

void setup() {
  softSerial.begin(115200); // baudrate par défaut de l'ESP8266
  delay(100);
  // on demande à utiliser un baudrate inférieur
  // (notre esp8266 s'est montrer plus stable ainsi)
  softSerial.println("AT+CIOBAUD=9600"); 
  delay(200);
  softSerial.begin(9600);
}

void loop() {
  String temperatureSalon = String(20.12); // dans la vraie vie on utiliserait la valeur retournée par un capteur
  sendValue("MQmGBUiuXg3JNgCk", "temperature-salon", temperatureSalon);
}

  
void sendValue(String token, String metric, String value) {
  String host = "www.fais-le-toi-meme.fr";
  delay(100);
  // on va se connecter à un réseau existant, donc on passe en mode station
  softSerial.println("AT+CWMODE=1");
  delay(1000);
  // on se connecte au réseau
  softSerial.println("AT+CWJAP=\""+SSID+"\",\""+PASS+"\"");
  delay(10000);
  // mode "connexions multiples"
  softSerial.println("AT+CIPMUX=1");
  
  delay(3000);
  // on se connecte à notre serveur en TCP sur le port 80
  softSerial.println("AT+CIPSTART=4,\"TCP\",\""+host+"\",80");
  delay(1000);
  String request = "GET /iot-dashboard/write/"+token+"/"+metric+"/"+value+ " HTTP/1.0\r\n";
  request       += "Host:"+host+"\r\n";
  // on donne la taille de la requête qu'on va envoyer, en ajoutant 2 car
  // println ajouter 2 caractères à la fin "\r" et "\n"
  softSerial.println("AT+CIPSEND=4,"+String(request.length()+2));
  delay(500);
  // on envoie la requete
  softSerial.println(request);
  delay(3000);
  // on ferme la connexion
  softSerial.println("AT+CIPCLOSE=4");
}

Bon. Vous aurez remarqué le nombre important d'appels à la fonction delay(). Ça pique un peu les yeux, mais nous avons remarqué que plus on laisse de temps au module, moins on rencontre d'erreurs. L'utilisation des commandes AT envoyées en série rendent le code assez moche. Vous verez par la suite qu'en flashant le module pour y mettre nos propres programmes, on peut faire les choses de manière bien plus élégante.

Utilisation de l'ESP8266 de façon autonôme

Pour découvrir comment programmer l'ESP8266, consultez cet article : Programmer l'ESP8266 avec l'IDE Arduino. Attention, vous risquez d'utiliser votre Arduino beaucoup moins souvent après avoir découvert ce que l'ont peut faire avec l'ESP8266 ! :).