Bonjour,
J'ai réalisé un projet basé sur un Arduino Wifi : commande de 2 moteurs cc via une requête http envoyée à partir d'un smartphone.
Exemple : http://192.168.0.33/arduino/digital/R1/ >> R1 étant la commande a éxécuter. cette commande est envoyée via I2C à un second Arduino qui gère les moteurs et autres périphériques.
La carte Arduino Wifi étant obsolète et de plus difficile à trouver, je souhaiterais la remplacer par une Sparkfun ESP8266 et utiliser cette dernière de la même manière que l'Arduino Wifi.
J'ai testé ESP8266_Shield_Demo.h voir code ci-dessous.
Le module répond à une requête mais quelle est la syntaxe de la requête à envoyer afin qu'il reçoive le paramètre R1 ?
Merci pour vos suggestions.
#include <SoftwareSerial.h>
#include <SparkFunESP8266WiFi.h>
const char mySSID[] = "";
const char myPSK[] = "";
ESP8266Server server = ESP8266Server(80);
void setup()
{
Serial.begin(9600);
initializeESP8266();
connectESP8266();
displayConnectInfo();
serverSetup();
}
void loop()
{
serverDemo();
}
void initializeESP8266()
{
int test = esp8266.begin();
if (test != true)
{
Serial.println(F("Error talking to ESP8266."));
errorLoop(test);
}
Serial.println(F("ESP8266 Shield Present"));
}
void connectESP8266()
{
int retVal = esp8266.getMode();
if (retVal != ESP8266_MODE_STA)
{ // If it's not in station mode.
retVal = esp8266.setMode(ESP8266_MODE_STA);
if (retVal < 0)
{
Serial.println(F("Error setting mode."));
errorLoop(retVal);
}
}
Serial.println(F("Mode set to station"));
retVal = esp8266.status();
if (retVal <= 0)
{
Serial.print(F("Connecting to "));
Serial.println(mySSID);
retVal = esp8266.connect(mySSID, myPSK);
if (retVal < 0)
{
Serial.println(F("Error connecting"));
errorLoop(retVal);
}
}
}
void displayConnectInfo()
{
char connectedSSID[24];
memset(connectedSSID, 0, 24);
// esp8266.getAP() can be used to check which AP the
// ESP8266 is connected to. It returns an error code.
// The connected AP is returned by reference as a parameter.
int retVal = esp8266.getAP(connectedSSID);
if (retVal > 0)
{
Serial.print(F("Connected to: "));
Serial.println(connectedSSID);
}
IPAddress myIP = esp8266.localIP();
Serial.print(F("My IP: ")); Serial.println(myIP);
}
void serverSetup()
{
server.begin();
Serial.print(F("Server started! Go to "));
Serial.println(esp8266.localIP());
Serial.println();
}
void serverDemo()
{
ESP8266Client client = server.available(500);
if (client)
{
Serial.println(F("Client Connected!"));
boolean currentLineIsBlank = true;// an http request ends with a blank line
while (client.connected())
{
if (client.available())
{
char c = client.read();
Serial.println(c);
if (c == '\n' && currentLineIsBlank)
{
Serial.println(F("Sending HTML page"));
// send a standard http response header:
String htmlBody;
client.print("test");
break;
}
if (c == '\n')
{
currentLineIsBlank = true; // you're starting a new line
}
else if (c != '\r')
{
currentLineIsBlank = false; // you've gotten a character on the current line
}
}
}
delay(1); // give the web browser time to receive the data
client.stop(); // close the connection:
Serial.println(F("Client disconnected"));
}
}
void errorLoop(int error)
{
Serial.print(F("Error: ")); Serial.println(error);
Serial.println(F("Looping forever."));
for (;;)
;
}
Merci pour les liens intéressants.
Je comprends plus ou moins le principe.
Je me suis basé sur les exemples fournis avec la carte Sparkfun ESP8266 mais je n'arrive pas à récupérer le paramètre de la requête : exemple http://192.168.0.27/?param1
je n'arrive pas à récupérer la chaîne param1.
Merci pour vos suggestions
void serverDemo()
{
ESP8266Client client = server.available(500);
if (client)
{
Serial.println(F("Client Connected!"));
boolean currentLineIsBlank = true;// an http request ends with a blank line
while (client.connected())
{ if (client.available())
{
char c = client.read();
>>> readString += c;
if (c == '\n' && currentLineIsBlank)
{
Serial.println("Before readString");
Serial.println(readString); // devrait contenir le paramètre à récupérer
Serial.println(F("Sending HTML page"));
String htmlBody; // send a standard http response header:
break;
}
if (c == '\n')
{
currentLineIsBlank = true; // you're starting a new line
Serial.println(readString); // devrait contenir le paramètre à récupérer
}
else if (c != '\r')
{
currentLineIsBlank = false; // you've gotten a character on the current line
}
}
}
delay(1); // give the web browser time to receive the data
client.stop(); // close the connection:
Serial.println(F("Client disconnected"));
}
}
ESP8266Client client = server.available();
if (client) {
// Read the first line of the request
String req = "";
req = client.readStringUntil('\r');
Serial.print("Client request: [");
Serial.print(req);
Serial.println("]");
}
void serverDemo()
{
ESP8266Client client = server.available(500);
if (client)
{
String req = "";
req = client.readStringUntil('\r');
Serial.print("Client request: [");
Serial.print(req);
Serial.println("]");
Serial.println(F("Client Connected!"));
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected())
{
if (client.available())
{
char c = client.read();
if (c == '\n' && currentLineIsBlank)
{
Serial.println(F("Sending HTML page"));
// send a standard http response header:
client.print(htmlHeader);
String htmlBody;
// output the value of each analog input pin
for (int a = 0; a < 6; a++)
{
htmlBody += "A";
htmlBody += String(a);
htmlBody += ": ";
htmlBody += String(analogRead(a));
htmlBody += "
\n";
}
htmlBody += "</html>\n";
client.print(htmlBody);
break;
}
if (c == '\n')
{
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r')
{
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println(F("Client disconnected"));
}
}
#include <SoftwareSerial.h>
#include <SparkFunESP8266WiFi.h>
const char mySSID[] = "";
const char myPSK[] = "";
ESP8266Server server = ESP8266Server(80);
const char destServer[] = "example.com";
const String htmlHeader = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"Connection: close\r\n\r\n"
"<!DOCTYPE HTML>\r\n"
"<html>\r\n";
const String httpRequest = "GET / HTTP/1.1\n"
"Host: example.com\n"
"Connection: close\n\n";
void setup()
{
Serial.begin(9600);
initializeESP8266();
connectESP8266();
displayConnectInfo();
// clientDemo();
serverSetup();
}
void loop()
{
serverDemo();
}
void initializeESP8266()
{
int test = esp8266.begin();
if (test != true)
{
Serial.println(F("Error talking to ESP8266."));
errorLoop(test);
}
Serial.println(F("ESP8266 Shield Present"));
}
void connectESP8266()
{
// The ESP8266 can be set to one of three modes:
// 1 - ESP8266_MODE_STA - Station only
// 2 - ESP8266_MODE_AP - Access point only
// 3 - ESP8266_MODE_STAAP - Station/AP combo
// Use esp8266.getMode() to check which mode it's in:
int retVal = esp8266.getMode();
if (retVal != ESP8266_MODE_STA)
{ // If it's not in station mode.
// Use esp8266.setMode([mode]) to set it to a specified mode.
retVal = esp8266.setMode(ESP8266_MODE_STA);
if (retVal < 0)
{
Serial.println(F("Error setting mode."));
errorLoop(retVal);
}
}
Serial.println(F("Mode set to station"));
retVal = esp8266.status();
if (retVal <= 0)
{
Serial.print(F("Connecting to "));
Serial.println(mySSID);
// esp8266.connect([ssid], [psk]) connects the ESP8266
// to a network.
// On success the connect function returns a value >0
// On fail, the function will either return:
// -1: TIMEOUT - The library has a set 30s timeout
// -3: FAIL - Couldn't connect to network.
retVal = esp8266.connect(mySSID, myPSK);
if (retVal < 0)
{
Serial.println(F("Error connecting"));
errorLoop(retVal);
}
}
}
void displayConnectInfo()
{
char connectedSSID[24];
memset(connectedSSID, 0, 24);
int retVal = esp8266.getAP(connectedSSID);
if (retVal > 0)
{
Serial.print(F("Connected to: "));
Serial.println(connectedSSID);
}
IPAddress myIP = esp8266.localIP();
Serial.print(F("My IP: ")); Serial.println(myIP);
}
void clientDemo()
{
ESP8266Client client;
int retVal = client.connect(destServer, 80);
if (retVal <= 0)
{
Serial.println(F("Failed to connect to server."));
return;
}
client.print(httpRequest);
while (client.available())
Serial.write(client.read()); // read() gets the FIFO char
if (client.connected())
client.stop(); // stop() closes a TCP connection.
}
void serverSetup()
{
server.begin();
Serial.print(F("Server started! Go to "));
Serial.println(esp8266.localIP());
Serial.println();
}
void serverDemo()
{
ESP8266Client client = server.available(500);
if (client)
{
String req = "";
req = client.readStringUntil('\r');
Serial.print("Client request: [");
Serial.print(req);
Serial.println("]");
Serial.println(F("Client Connected!"));
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected())
{
if (client.available())
{
char c = client.read();
if (c == '\n' && currentLineIsBlank)
{
Serial.println(F("Sending HTML page"));
client.print(htmlHeader);// send a standard http response header:
String htmlBody;
// output the value of each analog input pin
for (int a = 0; a < 6; a++)
{
htmlBody += "A";
htmlBody += String(a);
htmlBody += ": ";
htmlBody += String(analogRead(a));
htmlBody += "
\n";
}
htmlBody += "</html>\n";
client.print(htmlBody);
break;
}
if (c == '\n')
{
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r')
{
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println(F("Client disconnected"));
}
}
void errorLoop(int error)
{
Serial.print(F("Error: ")); Serial.println(error);
Serial.println(F("Looping forever."));
for (;;)
;
}
Je vais te renvoyer vers une autre bibliothèque qui fait tout le travail pour toi.
D'abord, il faudrait que tu testes si ce tuto fonctionne avec ton Sparkfun ESP8266, moi je n'en ai pas donc je ne peux pas être sûr à 100%.
Le tuto te permet d'allumer ou éteindre une LED via un serveur web. Il est tout simple.
Si ça fonctionne, tu peux commencer à regarder la bibliothèque qu'il utilise : ESP8266WebServer.
Elle a au moins 2 avantages :
La méthode 'on' permet de repérer automatiquement le début d'une commande. Par exemple, tu peux choisir de commander un moteur en avant ou en arrière. Tu ferais ça comme ça par exemple http://tonIP/moteur&direction=1 --> on va chercher 'moteur' et appeler une fonction que tu vas écrire s'il trouve ce mot clé. Pas besoin de le faire toi-même c'est automatique. Dès qu'il reçoit un truc qui commence par http://tonIP/moteur il appellera la fonction que tu lui indiques, ici handleMoteur() : server.on("/moteur", handleMoteur); Tu peux en faire une autre pour un capteur de température, une bande de LEDs, etc.
D'autres méthodes existent pour chercher les arguments. Par exemple hasArg("direction") permet de vérifier si l'argument 'direction' est présent dans ta commande. C'est un booléen, s'il renvoie true, tu peux utiliser arg("direction") pour obtenir directement la valeur associée.
arg renvoie un String : pour le transformer en int ou en float, il faut utiliser les méthodes de la classe String (toInt(), toFloat(),...). Tout ceci sera dans la fonction que tu as indiqué plus haut (handleMoteur dans mon cas qui va traiter le cas du moteur).
C'est ce que j'ai fait à plusieurs reprises : effacer la bibliothèque et la réinstaller.
La compilation donne ce message :
C:\Program Files (x86)\Arduino\libraries\ESPWebServer-master\src/ESP8266WebServer.h:27:22: fatal error: functional: No such file or directory
compilation terminated.
Utilisation de la bibliothèque ESP8266WiFi prise dans le dossier : C:\Program Files (x86)\Arduino\libraries\ESP8266WiFi (legacy)
Utilisation de la bibliothèque ESPWebServer-master version 1.0 dans le dossier: C:\Program Files (x86)\Arduino\libraries\ESPWebServer-master
exit status 1
Erreur de compilation pour la carte Arduino/Genuino Uno
Alors que le fichier ESP8266WebServer.h existe bien à cet endroit.
Bonjour
Merci pour ta suggestion.
Effectivement il s'agit d'un shield que je place sur un Arduino Uno.
Et je pensais qu'il était donc normal de choisir la carte Arduino Uno.
Mais non apparemment il faut sélectionner Sparkfun ESP8266 Thing
La compilation est réalisée correctement. Mais ce ne serait pas amusant s'il n'y avait pas encore un autre problème lors du téléchargement : le message d'erreur suivant apparaît :
File "C:/Users/Utilisateur/AppData/Local/Arduino15/packages/esp8266/hardware/esp8266/2.5.2/tools/esptool\esptool.py", line 468, in connect
raise FatalError('Failed to connect to %s: %s' % (self.CHIP_NAME, last_error))
esptool.FatalError: Failed to connect to ESP8266: Invalid head of packet (0x00)
J'ai essayé en sélectionnant d'autres cartes : mais c'est pareil.
Merci pour votre temps.
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
ESP8266WebServer server(80);
int ledPin = 16;
bool ledState = LOW;
void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(115200);
WiFi.begin("VOO-020245","UTJQDCRE"); //Connect to the WiFi network
while(WiFi.status()!= WL_CONNECTED){ //Wait for connection
delay(500);
Serial.println("Waiting to connect…");
}
Serial.print("IP address: ");
Serial.println(WiFi.localIP()); //Print the local IP
server.on("/on", turnOn); //Associate the handler function to the path
server.on("/off", turnOff);
server.on("/toggle", toggle);
server.begin(); //Start the server
Serial.println("Server listening");
}
void loop() {
server.handleClient();
}
void turnOn(){
ledState = HIGH;
digitalWrite(ledPin, ledState);
server.send(200, "text/plain", "LED on");
}
void turnOff(){
ledState = LOW;
digitalWrite(ledPin, ledState);
server.send(200, "text/plain", "LED off");
}
void toggle(){
ledState = !ledState;
digitalWrite(ledPin, ledState);
server.send(200, "text/plain", "LED toggled");
}
Je vais ressortir le fameux théorème de Lesept : "Si tu as une erreur, il est fort probable que quelqu'un d'autre l'a eue avant toi et a posé la question sur un forum".
Donc, partant de là, tu peux chercher sur Google : "Failed to connect to %s: %s' % (self.CHIP_NAME, last_error)" et voir s'il y a des réponses...
Sur le Github d'espressif, on trouve ce genre d'erreur : une solution proposée est de revenir à une version plus ancienne de l'esptool (ne me demande pas comment, je ne sais pas, cherche...), une autre est de changer la vitesse d'upload (115200 bauds lieu de 921600), une autre de lancer la compilation + upload avec l'esp non branché et de la brancher seulement lorsque le transfert est initié...
Lis ces messages et teste les solutions, il y en a peut-être une qui fonctionnera pour toi.
Je ne m'imaginais pas passer autant d'heures pour "simplement" récupérer des paramètres d'une requête http. Je l'ai fait sans problème avec un Arduino Wifi (qui n'est plus en vente).
Je n'ai peut-être pas choisi la bonne solution.... Si vous avez un avis là-dessus n'hésitez pas à me le communiquer.
Mon objectif est d'envoyer une requête du genre http://192.168.0.35/p02 et de récupérer le paramètre p02
Concernant le shield : SparkFun WiFi Shield - ESP8266
Si j'ai bien compris, vous avez un Uno et un shield Wifi à base d'ESP8266. Entre les 2, des commandes AT.
Il y a des exemples d'utilisation de cette architecture sur le site, mais c'est une solution m....ique.
Tous ceux qui l'ont un jour essayé (dont moi) ont abandonné.
Passez tout sur une carte à ESP8266 (Nodemcu, Wemos D1 mini, etc.)
C'est beaucoup plus simple, beaucoup plus performant.... et beaucoup moins cher !