Arduino + ESP8266 : connexion Wifi

Introduction

La carte Arduino peut être connectée à un module de connexion Wifi (nommé ESP8266) pour lequel une configuration est nécessaire.

Voici la façon dont j’ai pu envoyer un simple HTTP GET depuis la carte Arduino avec ce module.

Dans certains tutoriels qu’on peut trouver sur le Net, il est mentionné la mise à jour du firmware, par l’intermédiaire d’une autre carte électronique. Cet article part du module sorti de son emballage, sans faire cette mise à jour.

 

Le module ESP8266

Ce module est un regroupement de multiples composants, sous forme de mini-carte électronique, avec 8 broches de connexion.
Il mesure 2.5 cm x 1.5 cm et coûte 7.33 € sur Amazon.

Il permet de se connecter à un point d’accès Wifi pour communiquer en mode client/serveur (être client ou être serveur) mais il peut aussi être défini en tant que point d’accès Wifi.

Branchements

Il faut brancher le composant avec la carte Arduino, de manière précise, sur le 3.3v.

 

Détail des branchements :

L’article http://www.labradoc.com/i/follower/p/notes-esp8266 détaille les branchements. En voici un rappel (en Français) :

  • RX vers le port TX de la carte Arduino
  • VCC vers le port 3.3v de la carte Arduino
  • GPIO 0 non branché
  • RESET non branché
  • CH_PD vers le port 3.3v de la carte Arduino
  • GPIO 2 non branché
  • TX vers le port RX de la carte Arduino
  • GND vers le port GND de la carte Arduino

Si vous avez branché RX et TX correctement, une LED bleue sur le module ESP8266 émet un bref flash lors de la mise sous tension. Si elle ne s’allume pas, c’est que le branchement n’est peut-être pas bon…

Quelques conseils :

  • Branchez tout et à la fin, le fil qui va vers 3.3v. Vous saurez si tout est opérationnel ou non avec cette LED bleue.
  • Il ne faut rien brancher avec le port 5v de la carte Arduino. En cas d’erreur, le module grillera. Je vous conseille donc de brancher un fil sur ce port 5v et de laisser non branché à l’autre bout du fil (par exemple, faire un nœud pas trop serré).

 

Comment donner des ordres au module ESP8266 ?

L’article http://www.labradoc.com/i/follower/p/notes-esp8266 détaille les commandes à passer par l’interface de programmation d’Arduino. Pour résumé, une série de commandes doivent être passées pour :

  • Initialiser le module ESP8266
  • Se mettre en mode client Wifi (et pas en mode point d’accès)
  • (en option) Rechercher les points d’accès disponibles (et afficher leur SSID)
  • (en option) Se définir une adresse IP
  • Se connecter sur un point d’accès (avec SSID et mot de passe)
  • Se mettre en mode « Connexions multiples » (pour faire plusieurs appels HTTP)
  • (en option) Afficher son adresse IP
  • (en option) Faire un PING sur un serveur
  • Faire un HTTP GET
  • Fermer la connexion (et préparer le prochain appel HTTP)

Ces commandes sont à transmettre par le port Série de la carte Arduino.

 

Code pour faire les appels HTTP GET

Avec Adruino, 2 fonctions sont préparées pour que l’utilisateur écrive son code à l’intérieur, avec 2 objectifs :

  • setup() : cette fonction est lancée une seule fois au démarrage de la carte Arduino
  • loop() : après la fonction « setup() », cette fonction est lancée autant de fois que la carte Arduino est allumée

Une partie d’initialisation est faire avant ces 2 fonctions

#include <SoftwareSerial.h>

String ssid = "NETGEAR";
String key = "pA$$W0Rd";

SoftwareSerial esp8266(1, 0); // RX, TX
bool done = false;

Seule la bibliothèque SoftwareSerial est nécessaire.

La variable « done » sera utilisée de manière globale.

 

Code de la fonction setup()

 void setup() {
  // put your setup code here, to run once:

  esp8266.begin(115200);
  delay(500);
  esp8266.println("AT+RST");

  /**
   * Initialisation
   */
  delay(1000);
  esp8266.println("AT");
  done = esp8266.find("OK");
  if(!done){
    delay(1000);
    done = esp8266.find("OK");
  }

  /**
   * Se mettre en mode CLIENT
   */
  esp8266.println("AT+CWMODE=1");
  done = esp8266.find("OK");
  if(!done){
    delay(1000);
    done = esp8266.find("OK");
  }

  /**
   * Affecter son adresse IP manuellement
   */
   /*
  delay(1000);
  esp8266.println("AT+CIPSTA=\"192.168.1.200\",\"192.168.92.254\",\"255.255.255.0\"");
  done = esp8266.find("OK");
  while(!done){
    delay(1000);
    done = esp8266.find("OK");
  }*/

  /**
   * Rechercher les points d'accès WIFI
   */
   /*
  delay(1000);
  esp8266.println("AT+CWLAP");
  done = esp8266.find("OK");
  while(!done){
    delay(1000);
    done = esp8266.find("OK");
    delay(3000);
    break;
  }*/

  /**
   * Se connecter au point d'accès Wifi défini dans la variable "ssid"
   */
  esp8266.println("AT+CWJAP=\""+ssid+"\",\""+key+"\"");
  done = esp8266.find("OK");
  while(!done){
    delay(1000);
    done = esp8266.find("OK");
  }

  /**
   * Se mettre en mode connexions multiples
   */
  esp8266.println("AT+CIPMUX=1");
  done = esp8266.find("OK");
  if(!done){
    delay(1000);
    done = esp8266.find("OK");
  }

  /**
   * afficher son adresse IP
   */
  esp8266.println("AT+CIFSR");
  done = esp8266.find("STAIP");
  if(!done){
    delay(1000);
    done = esp8266.find("OK");
  }

  /**
   * faire un ping sur un server
   */
   /*
  delay(1000);
  esp8266.println("AT+PING=\"192.168.1.100\"");
  done = false;
  if(!done){
    delay(1000);
    done = esp8266.find("OK");
  }*/

}

Il est nécessaire de mettre des temps d’attente (moins une seconde maxi) pour que le module se mette dans un état convenable, qu’il communique avec le point d’accès Wifi. Sinon, vous aurez des messages du genre « busy p… » ou « busy s… », qui peuvent être bloquant ou non.

Ajustez ces temps selon vos résultats.

 

Code de la fonction loop()

void loop() {
  int maxLoops = 5;

  /**
   * Faire un HTTP GET
   */
  String cmd = "AT+CIPSTART=4,\"TCP\",\"192.168.1.100\",80";
  esp8266.println(cmd);
  delay(500);
  done = esp8266.find("OK");
  int currentLoop = 0;
  while(!done){
    delay(500);
    done = esp8266.find("OK");
    if(currentLoop >= maxLoops){
      break;
    }
    currentLoop++;
  }

  String url = "/lda/index.php/data/createdatajson/append?datflval=1.55&thing=FIRST";
  String cmdGET = "GET " + url + " HTTP/1.1\r\n"+
    "Host: 192.168.1.100\r\nUser-Agent: ESP8266_HTTP_Client\r\nConnection: close\r\n\r\n";
  esp8266.print("AT+CIPSEND=4,");
  esp8266.println(cmdGET.length());
  delay(1000);
  done = esp8266.find(">");
  currentLoop = 0;
  while(!done){
    delay(500);
    done = esp8266.find(">");
    if(currentLoop >= maxLoops){
      break;
    }
    currentLoop++;
  }
  esp8266.println(cmdGET+"\r\n\r\n");
  delay(1000);

  esp8266.println("AT+CIPSTATUS");
  delay(1000);

  // Close all connections
  esp8266.println("AT+CIPCLOSE=5");
  delay(1000);

  // restart from zero
  esp8266.println("AT");

  // 4 secondes déjà passées
  delay(20000);

}

 

Je désire faire l’appel à l’URL « http://192.168.1.100:80/lda/index.php/data/createdatajson/append?datflval=1.55&thing=FIRST » en GET. Tous les paramètres de cette requête sont après le caractère « ? ».

J’ai un serveur HTTP qui est capable de lire cette requête et de stocker la valeur « 1.55″ pour un objet « FIRST » dans une base de données.

Ce code se découpe en plusieurs parties :

  1. Se connecter au serveur 192.168.1.100, en mode TCP, sur le port 80 : « AT+CIPSTART=… ». Il faut attendre que le moduleESP8266 réponde « OK » pour continuer.
  2. Appeler l’URL en GET : « AT+CIPSEND=… ». Il faut absolument ajouter dans l’entête de cette requête le « Host: xxx », sinon le serveur répond « Error HTTP 400 : BAD REQUEST ». Pour être propre, je rajoute « User-Agent » et « Connection ». Les « \r\n » sont importants. A la fin, il faut les mettre en double : « \r\n\r\n ». Sinon, le serveur attend des données.
  3. (En option) Demander le statut de la connexion : « AT+CIPSTATUS ». elle doit être fermée (le serveur a pris la requête est il a fermé la connexion)
  4. S’assurer que toutes les connexions sont bien fermées : « AT+CIPCLOSE=5″ (le chiffre 5 signifie ‘toutes les connexions’)
  5. Réinitialiser le module ESP8266 : « AT ». Lors de la prochaine connexion au serveur (étape 1 de la boucle), la connexion Wifi sera conservée.
  6. Attendre 20 secondes pour le prochain envoi de données

Ici aussi, les délais d’attente entre les commandes sont importants. Ils peuvent être personnalisés selon votre besoin, mais ils ne pourront pas être mis à 0.

 

Envoi vers la carte Arduino

Les ports TX et RX sont utilisés lors du transfert du programme vers la carte Arduino. si vous laisser le 3.3v branché, Il faudra débrancher les TX et RX pour que le transfert se fasse correctement. Je réitère donc mon conseil de débrancher le 3.3v lors du transfert.

 

Résultat sur le serveur

Les données sont toutes récupérées, à intervalle régulier (toutes les 24 secondes) :

 

Trace laissée par le module

Dans la console « Moniteur série », voici les infos affichées par le module. On y trouve les commandes passées et les réponses du module.

Ai-Thinker Technology Co.,Ltd.

ready
AT

OK
AT+CWMODE=1

OK
AT+CWJAP="NETGEAR","pA$$W0Rd"

WIFI CONNECTED
WIFI GOT IP

OK
AT+CIPMUX=1

OK
AT+CIFSR

+CIFSR:STAIP,"192.168.1.200"
+CIFSR:STAMAC,"5c:cf:7f:10:d6:ab"

OK
AT+CIPSTART=4,"TCP","192.168.1.100",80

4,CONNECT

OK
AT+CIPSEND=4,157

OK
> 

busy s...

Recv 157 bytes

SEND OK

+IPD,4,728:HTTP/1.1 200 OK
Date: Sat, 16 Jan 2016 17:32:03 GMT
Server: Apache/2.4.12 (Ubuntu)
Set-Cookie: ci_session=a%3A5%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%227c75547487eb7803fa0afe75dead178d%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A13%3A%22192.168.1.200%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A19%3A%22ESP8266_HTTP_Client%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1452965523%3Bs%3A9%3A%22user_data%22%3Bs%3A0%3A%22%22%3B%7Deb938672b48c15066e92aef755ab6250; expires=Sat, 16-Jan-2016 19:32:03 GMT; Max-Age=7200; path=/
Access-Control-Allow-Origin: *
Vary: Accept-Encoding
Content-Length: 81
Connection: close
Content-Type: text/html; charset=UTF-8

{"datiddat":41,"datflval":"1.55","datdhacq":"2016-01-16 18:32:03","datidthn":"1"}4,CLOSED
AT+CIPSTATUS

STATUS:4

OK
AT+CIPCLOSE=5

OK
AT

OK
AT+CIPSTART=4,"TCP","192.168.1.100",80

4,CONNECT

OK
AT+CIPSEND=4,157

OK
> 

busy s...

Recv 157 bytes

SEND OK

+IPD,4,728:HTTP/1.1 200 OK
Date: Sat, 16 Jan 2016 17:32:27 GMT
Server: Apache/2.4.12 (Ubuntu)
Set-Cookie: ci_session=a%3A5%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%220a10f1ca33ba3316e6acfee18ba76b2f%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A13%3A%22192.168.1.200%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A19%3A%22ESP8266_HTTP_Client%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1452965547%3Bs%3A9%3A%22user_data%22%3Bs%3A0%3A%22%22%3B%7Db946991f8b9d1ef88d0667330b515767; expires=Sat, 16-Jan-2016 19:32:27 GMT; Max-Age=7200; path=/
Access-Control-Allow-Origin: *
Vary: Accept-Encoding
Content-Length: 81
Connection: close
Content-Type: text/html; charset=UTF-8

{"datiddat":42,"datflval":"1.55","datdhacq":"2016-01-16 18:32:27","datidthn":"1"}4,CLOSED
AT+CIPSTATUS

STATUS:4

OK
AT+CIPCLOSE=5

OK
AT

OK
...

 

Annexe

Toutes les commandes et la doc technique (en anglais) de ce module ESP8266 : https://nurdspace.nl/ESP8266

Code complet : téléchargez

 

14 réflexions au sujet de « Arduino + ESP8266 : connexion Wifi »

  1. Bonjour
    Sympa votre article
    A mon sens il faudrait rajouter un adaptation sur la sortie TX de l’arduino qui est à 5V et l’entrée RX de l’ESP8622 qui lui doit être à 3V3 . un simple pont de résistance devrait faire l’affaire et donc faire durer la vie de notre gentil module ESP.

  2. Bonjour,
    merci pour l’article, bien fait et complet !
    J ai toutefois un petit problème (je ne suis pas encore expert en code arduino!), je n’ai rien d’affiché dans le moniteur série. Si je remplace esp8266.begin(9600) par Serial.begin et Serial.println c’est ok. Mais je ne sais pas comment écrire done = esp8266.find(« OK »); pour m’afficher le ok.

    Je souhaite juste appeler une URL du type : » /json.htm?type=command&param=switchlight&idx=60&switchcmd=On »
    sans passer de valeur comment puis je simplifier le code.

    Merci beaucoup pour votre aide

    • Bonjour,
      En effet, moi aussi j’ai du mal à récupérer le ‘OK’. Je pense que cela peut venir du ESP8266. J’ai testé plusieurs matériels, alimentés par différentes sources, mais pour le moment, sans succès.

      Dans la fonction loop(), il y a ce code :
      String url = "/lda/index.php/data/createdatajson/append?datflval=1.55&thing=FIRST";

      J’appelle une page du serveur avec des paramètres « en dur ». Tu peux donc tout à fait passer par ma méthode pour faire tes appels.
      Si tu es sûr que tes commandes à l’ESP8266 sont bons, tu peux te passer des tests « esp8266.find(« OK »); ».

      Bonne continuation.

    • Hello,
      Je n’ai pas essayé toutes ces cartes. Par contre, j’ai beaucoup de mal à installer un firmware sur un ESP8266. Pour le moment, j’ai abandonné. Je te conseille donc de te tourner vers une carte Arduino qui a déjà le wifi et non utiliser un module wifi externe. Tu perdras de la place dans ton projet final (ces cartes Arduino sont plus grosses que les mini-cartes Arduino), mais tu gagneras du temps…

      Bye.

  3. Bonjour,

    C’est un article très intéressant.
    Je suis à l’aise dans la partie électronique.
    Par contre, pour le serveur…
    Pouvez-vous me donner le code de la page serveur ?
    Merci d’avance.
    Salutations

    • Bonjour,
      En fait, la partie serveur est composée de plusieurs pages pour personnaliser les données : capteurs, catégorie de données, groupes de capteurs

      Je te conseille de lire ce petit article, sur le mode de fonctionnement : Données d’un capteur vers un serveur Web. C’est une vraie application Web PHP avec le framework CodeIgniter.

      Si tu désires le code complet, il faudra me contacter par mail : julien.coron@gmail.com

      Bye,
      Julien

  4. Pas mal d’explications qui m’ont permis de faire fonctionner l’esp8266 en WebServer…

    J’essaie maintenant de faire un serveur client : je veux INSERER la température dans ma database WAMP à partir de la page add_th.php? (j’arrive à le faire à la main )
    Avec le code ci-dessous, j’ai toujours le même message= HTTP/ 1.1 403 Forbiden
    Que dois-je faire ? est-ce au niveau WAMP APACHE ou proxy??? que je ne peux pas rentrer ? pourquoi ?

    Merci

    René

    /* DHTClient – ESP8266 client with a DHT sensor as an input http://homecircuits.eu/blog/esp8266-temperature-iot-logger/
    */
    #include
    #include

    #include
    #define DHTTYPE DHT11 //or DHT11
    #define DHTPIN 2

    const char* ssid = « Livebox….. »;
    const char* password = « ………………… »;

    WiFiClient client;
    byte server[] = {
    192, 168, 1, 19 }; // http server – PUT HERE YOUR SERVER IP as bytes
    String serverStr = « 192.168.1.19″; // http server – PUT HERE YOUR SERVER IP as string

    // Initialize DHT sensor – adafruit note
    // NOTE: For working with a faster than ATmega328p 16 MHz Arduino chip, like an ESP8266,
    // you need to increase the threshold for cycle counts considered a 1 or 0.
    // You can do this by passing a 3rd parameter for this threshold. It’s a bit
    // of fiddling to find the right value, but in general the faster the CPU the
    // higher the value. The default for a 16mhz AVR is a value of 6. For an
    // Arduino Due that runs at 84mhz a value of 30 works.
    // This is for the ESP8266 processor on ESP-01
    DHT dht(DHTPIN, DHTTYPE, 15); // 11 works fine for ESP8266

    float humidity, temperature; // Values read from sensor
    String webString = «  »; // String to display
    // Generally, you should use « unsigned long » for variables that hold time
    unsigned long previousMillis = 0; // will store last temp was read
    const long interval = 2000; // interval at which to read sensor

    // Required for LIGHT_SLEEP_T delay mode
    extern « C » {
    #include « user_interface.h »
    }

    void setup(void)
    {
    // You can open the Arduino IDE Serial Monitor window to see what the code is doing
    Serial.begin(115200); // Serial connection from ESP-01 via 3.3v console cable
    Serial.println(« \n\r \n\rWorking to connect »);
    for (uint8_t t = 4; t > 0; t–) {
    Serial.print(« [SETUP] WAIT « );
    Serial.println(t);
    delay(1000);
    }

    dht.begin(); // initialize temperature sensor
    Serial.println(« \n\r \n\rDHT done »);
    gettemperature();
    Serial.println(String(temperature));

    delay(2);
    }

    void loop(void)
    {
    delay(2);
    gettemperature();

    // Connect to WiFi network
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    Serial.print(« \n\r \n\rWorking to connect »);

    // Wait for connection
    while (WiFi.status() != WL_CONNECTED) {
    delay(200);
    Serial.print(« . »);
    }
    Serial.println(«  »);
    Serial.println(« DHT Weather Reading Client »);
    Serial.print(« Connected to « );
    Serial.println(ssid);
    Serial.print(« IP address: « );
    Serial.println(WiFi.localIP());

    Serial.println(ESP.getChipId()) ;
    Serial.println(« Client started »);

    if (client.connect(server, 80)) { // http server is running on default port 80
    Serial.println(« connected »);
    client.print(« GET /MonSite/arduino/add_th.php?temp= »); // PUT HERE YOUR SERVER URL e.g. from http://192.168.1.11/SensorWriteToFile.php?temp=10.5&hum=58

    client.print(String(temperature));
    client.print(« &hum= »);
    client.print(String(humidity));
    client.println( » HTTP/1.1″);
    client.print(« Host: « ); // http server is running on port 80, so no port is specified
    client.println(serverStr);
    client.println(« User-Agent: herge »); // PUT HERE YOUR USER-AGENT that can be used in your php program or Apache configuration
    client.println(); // empty line for apache server

    //Wait up to 10 seconds for server to respond then read response
    int i = 0;
    while ((!client.available()) && (i = interval) {
    // save the last time you read the sensor
    previousMillis = currentMillis;

    // Reading temperature for humidity takes about 250 milliseconds!
    // Sensor readings may also be up to 2 seconds ‘old’ (it’s a very slow sensor)
    humidity = dht.readHumidity(); // Read humidity (percent)
    //temperature = dht.readTemperature(true); // Read temperature as Fahrenheit
    temperature = dht.readTemperature(); // Read temperature as *C
    // Check if any reads failed and exit early (to try again).
    if (isnan(humidity) || isnan(temperature)) {
    Serial.println(« Failed to read from DHT sensor! »);
    return;
    }
    }
    }

    • Bonjour,
      il faut tout d’abord que tu puisses valider ton URL sur ton serveur, avec un navigateur ou avec Postman (un outil qui envoie des requêtes HTTP). Si ta requête est correctement formatée, elle pourra insérer une ligne dans ta base de données. Je te conseille de consulter les traces « access.log » de ton serveur APACHE, pour t’assurer que l’appel est correctement interprété.

      Si cette étape est franchie avec succès, mais que tu as toujours un refus de la part de ton serveur, il faut que tu t’assures que l’entête HTTP envoyée par ton ESP8266 est bien celle attendue par ton serveur Web. Pour ma part, j’ai dû ajouter cette entête HTTP :

      "GET " + url + " HTTP/1.1\r\n"+ "Host: 192.168.1.100\r\nUser-Agent: ESP8266_HTTP_Client\r\nConnection: close\r\n\r\n";

      En espérant t’avoir débloqué,
      Bon courage pour la suite.

      Julien

  5. bonjour
    Je viens de tomber sur ton post que je trouve vraiment bien construit ;)

    Je suis en train de me gratter la tête pour construire un programme utilisant un arduino uno et un esp8266-01
    Le projet est de piloter une rampe d’eclairage ( cette partie c’est bon !), je voudrais pouvoir mettre des variables à jour de mon programme
    exemple:
    j’ai declaré :
    int h_debut_eclairage_1 =17
    int mn_debut_eclairage_1 =0
    int h_debut_eclairage_2 =17
    int mn_debut_eclairage_2 =30
    int h_debut_eclairage_3 =19
    int mn_debut_eclairage_3 =0
    int h_debut_eclairage_4 =19
    int mn_debut_eclairage_4 =30

    const int debut_Eclairage [4]= { h_debut_eclairage_1 *60 + mn_debut_eclairage_1, h_debut_eclairage_2*60 + mn_debut_eclairage_2 , h_debut_eclairage_3*60 + mn_debut_eclairage_3, h_debut_eclairage_4*60 + mn_debut_eclairage_4 };

    Mon but serais via des requêtes de pouvoir modifier les variables :
    int h_debut_eclairage_1
    int mn_debut_eclairage_1
    int h_debut_eclairage_2
    int mn_debut_eclairage_2
    int h_debut_eclairage_3
    int mn_debut_eclairage_3
    int h_debut_eclairage_4
    int mn_debut_eclairage_4

    aurais tu une idée pour m’aider?

    • Bonjour,

      La solution la plus simple pour moi, serait de faire des requêtes à un serveur web (toutes les 10 secondes par exemple, dans le « loop » de l’arduino) pour lire les valeurs et changer ces variables. Tu peux faire un simple serveur web en PHP, sur un hébergement ou chez toi. Une URL sur ce serveur te permettrai de récupérer les valeurs, que tu pourrai modifier par une jolie interface graphique, en HTML CSS JS.

      Merci d’avoir lu mon post.

      Bye,
      Julien

  6. bonjour
    j’ai en ma possession un arduino uno et un module wifi esp8266
    je ne maitrise pas les programmation serveur , stp je voudrais que vous aidiez a piloter un systeme de de plusieurs leds sur internet grâce a un arduino uno et un module wifi esp8266

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

*

Vous pouvez utiliser ces balises et attributs HTML : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>