Ciao a tutti,
ho un problema con uno sketch, sono partito da questo sketch (Arduino AJAX Web Server for Reading a Switch Automatically.). Ho fatto delle modifiche allo sketch perchè nel mio caso non ho un modulo ethernet ma ho un modulo esp8266.8sketch modificato: [#include <SPI.h>#include <DHT.h>#include <WiFiEsp.h>#include <SoftwareSeri - Pastebin.com](https://sketch modificato) ). Il problema è che la pagina web mi ritorna sempre "Switch state: Not requested...". qualcuno può aiutarmi a capire dov'è l'errore?
in fondo allo sketch è presente questo void:
void GetSwitchState(WiFiEspClient cl)
{ Serial.println("test"); // ma non stampa nulla
if (digitalRead(7)) {
cl.println("Switch state: ON");
}else {
cl.println("Switch state: OFF");
}
}
Buongiorno e benvenuto nella sezione Italiana del forum,
cortesemente, come prima cosa, leggi attentamente il REGOLAMENTO di detta sezione, (... e, per evitare future possibili discussioni/incomprensioni, prestando molta attenzione al punto 15), dopo di che, come da suddetto regolamento (punto 16.7), fai la tua presentazione NELL'APPOSITA DISCUSSIONE spiegando bene quali esperienze hai in elettronica e programmazione, affinché noi possiamo conoscere la tua esperienza ed esprimerci con termini adeguati.
Grazie,
Guglielmo
P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposita discussione, nel rispetto del succitato regolamento nessuno ti risponderà (eventuali risposte o tuoi ulteriori post, verrebbero temporaneamente nascosti), quindi ti consiglio di farla al più presto.
Per facilitare chi ti deve aiutare, il codice è sempre meglio copiarlo ed incollarlo interamente qui (mi raccomando, seleziona la parte di codice e premi l'icona <code/> nella barra degli strumenti per contrassegnarla come codice) anche perché, messo su siti esterni, oggi c'è, domani non c'è più e la discussione perde di senso
Guglielmo
questo mostrato di seguito è il mio codice:
#include <SPI.h>
#include <DHT.h>
#include <WiFiEsp.h>
#include <SoftwareSerial.h>
#ifndef HAVE_HWSERIAL1
#include "SoftwareSerial.h"
SoftwareSerial Serial1(2, 3); // RX, TX
#define DHTPIN 9
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
char ssid[] = "xxx"; // your network SSID (name)
char pass[] = "yyyy"; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio's status
int reqCount = 0; // number of requests received
WiFiEspServer server(80); // create a server at port 80
String HTTP_req; // stores the HTTP request
#endif
void setup()
{//dht.begin();
// initialize serial for debugging
Serial.begin(115200);
// initialize serial for ESP module
Serial1.begin(9600);
// initialize ESP module
WiFi.init(&Serial1);
pinMode(7, INPUT_PULLUP);
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue
while (true);
}
// attempt to connect to WiFi network
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network
status = WiFi.begin(ssid, pass);
}
Serial.println("You're connected to the network");
printWifiStatus();
// start the web server on port 80
server.begin();
}
void loop()
{
WiFiEspClient client = server.available(); // try to get client
if (client) { // got client?Serial.println(server.available());
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) { // client data available to read
char c = client.read(); // read 1 byte (character) from client
HTTP_req += c; // save the HTTP request 1 char at a time
// last line of client request is blank and ends with \n
// respond to client only after last line received
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: keep-alive");
client.println("");
// AJAX request for switch state
if (HTTP_req.indexOf("ajax_switch") > -1) {
// read switch state and send appropriate paragraph text
}
else { // HTTP request for web page GetSwitchState(client);
// send web page - contains JavaScript with AJAX calls
client.println("<!DOCTYPE html>");
client.println("<html>");
client.println("<head>");
client.println("<title>Arduino Web Page</title>");
client.println("<script>");
client.println("function GetSwitchState() {");
client.println("nocache = \"&nocache=\"\ + Math.random() * 1000000;");
client.println("var request = new XMLHttpRequest();");
client.println("request.onreadystatechange = function() {");
client.println("if (this.readyState == 4) {");
client.println("if (this.status == 200) {");
client.println("if (this.responseText != null) {");
client.println("document.getElementById(\"switch_txt\")\.innerHTML = this.responseText;");
client.println("}}}}");
client.println("request.open(\"GET\", \"ajax_switch\" + nocache, true);");
client.println("request.send();");
client.println("setTimeout('GetSwitchState()', 1000);");
client.println("}");
client.println("</script>");
client.println("</head>");
client.println("<body onload=\"GetSwitchState()\">");
client.println("<h1>Arduino AJAX Switch Status</h1>");
client.println("<p id=\"switch_txt\">Switch state: Not requested...</p>");
client.println("<button type='button' onclick='GetSwitchState()'>Get Switch State</button>");
client.println("</body>");
client.println("</html>");
}
// display received HTTP request on serial port
Serial.print(HTTP_req);
HTTP_req = ""; // finished with request, empty string
break;
}
// every line of text received from the client ends with \r\n
if (c == '\n') {
// last character on line of received text
// starting new line with next character read
currentLineIsBlank = true;
}
else if (c != '\r') {
// a text character was received from client
currentLineIsBlank = false;
}
} // end if (client.available())
} // end while (client.connected())
delay(1); // give the web browser time to receive the data
client.stop(); // close the connection
} // end if (client)
}
void printWifiStatus()
{
// print the SSID of the network you're attached to
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print where to go in the browser
}
// send the state of the switch to the web browser
void GetSwitchState(WiFiEspClient cl)
{ Serial.println("prova");
if (digitalRead(7)) {
cl.println("Switch state: ON");
}else {
cl.println("Switch state: OFF");
}
}
il mio sospetto è che la funzione GetSwitchState, non venga eseguita infatti inserendo un Serial.println("prova");
non viene stampato nulla, potrebbe essere qui il problema?
Il tuo problema sta tutto nell'html che invii al client che non è correttamente formattato e quindi la pagina non fa quello che deve: ci sono infatti alcuni caratteri che non ci dovrebbero essere dove hai dovuto inserire gli escape per le virgolette
Il consiglio è di scrivere la parte HTML + Javascript usando il delimitatore "Raw String Literal" perché in questo modo non ci si deve preoccupare ei caratteri di escape \" \n \r
etc etc ed errori di questo genere sono subito evidenti.
static const char homepage[] PROGMEM = R"EOF(
<!DOCTYPE html>
<html>
<head>
<title>Arduino Web Page</title>
<script>
function GetSwitchState() {
nocache = "&nocache=" + Math.random() * 1000000;
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (this.readyState == 4) {
if (this.status == 200) {
if (this.responseText != null) {
document.getElementById("switch_txt").innerHTML = this.responseText;
}
}
}
}
request.open("GET", "ajax_switch" + nocache, true);
request.send();
setTimeout('GetSwitchState()', 1000);
}
</script>
</head>
<body onload="GetSwitchState()">
<h1>Arduino AJAX Switch Status</h1>
<p id="switch_txt">Switch state: Not requested...</p>
<button type='button' onclick='GetSwitchState()'>Get Switch State</button>
</body>
</html>
)EOF";
E quindi quando devi rispondere al client ti basterà inviare l'array in un colpo solo:
client.println(homepage);
Un ultimo appunto invece per lo script Javascript che non è proprio il massimo secondo me...
L'argomento nocache passato insieme alla richiesta GET, è del tutto inutile con un webserver di questo tipo che non implementa nessun meccanismo di caching e crea solo confusione e diventa possibile fonte di errore (cosa che infatti è successa).
All'interno della funzione GetSwitchState()
imposti un timer che chiama in modo ricorsivo la stessa funzione GetSwitchState()
dopo un secondo.
Se premi il pulsante visualizzato chiami di nuovo questa stessa funzione che imposta un altro timer, se lo premi ancora il meccanismo si ripete e cosi via fino a rendere instabile la pagina aumentando a dismisura le richieste inviate al server che prima o poi smetterà di rispondere: secondo me era meglio usare un setInterval()
al posto di un setTimeout()
(fuori dalla funzione ovviamente)
grazie mille davvero, stasera farò delle prove seguendo i tuoi consigli.
ammetto di non essere riuscito con il tuo suggerimento se non stampando con un ciclo for l'array homepage (se non erro è un array, alla fine dopo vari tentativi mi sono accorto che in realtà lo sketch funziona, il "problema" è che da quando clicco ci mette 20 secondi ad aggiornare lo stato.
P.S. ho usato setInterval() come mi hai suggerito ed ho tolto il pulsante in modo che aggiornasse da solo lo stato e funziona! con i suoi tempi ma funziona
Riposto lo sketch:
#include <SPI.h>
#include <DHT.h>
#include <WiFiEsp.h>
#include <SoftwareSerial.h>
#ifndef HAVE_HWSERIAL1
//#include "SoftwareSerial.h"
SoftwareSerial Serial1(2, 3); // RX, TX
#define DHTPIN 9
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
char ssid[] = "EIR-487p24"; // your network SSID (name)
char pass[] = "AnnaMirkoLeila"; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio's status
int reqCount = 0; // number of requests received
WiFiEspServer server(80); // create a server at port 80
String HTTP_req; // stores the HTTP request
#endif
void setup()
{//dht.begin();
// initialize serial for debugging
Serial.begin(115200);
// initialize serial for ESP module
Serial1.begin(9600);
// initialize ESP module
WiFi.init(&Serial1);
//pinMode(7, INPUT_PULLUP);
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue
while (true);
}
// attempt to connect to WiFi network
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network
status = WiFi.begin(ssid, pass);
}
Serial.println("You're connected to the network");
printWifiStatus();
// start the web server on port 80
server.begin();
}
void loop()
{
WiFiEspClient client = server.available(); // try to get client
//Serial.println(AJAX_request(client));delay(1000);
if (client) { // got client?Serial.println(server.available());
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
// client data available to read
char c = client.read(); // read 1 byte (character) from client
HTTP_req += c; // save the HTTP request 1 char at a time
// last line of client request is blank and ends with \n
// respond to client only after last line received
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: keep-alive");
client.println("");
// AJAX request for switch state
if (HTTP_req.indexOf("ajax_switch") > -1) {
// read switch state and send appropriate paragraph text
GetSwitchState(client);
}
else { // HTTP request for web page GetSwitchState(client);
// send web page - contains JavaScript with AJAX calls
client.println(F("<!DOCTYPE HTML>"));
client.println(F("<html>"));
client.println(F("<head>"));
client.println(F("<title>esp8266</title>"));
client.println(F("<script>"));
client.println(F("var request = new XMLHttpRequest();"));
//client.println(F("console.log(request.onreadystatechange());"));
client.println(F("function GetSwitchState(){nocache = '&nocache='+ Math.random() * 1000000;"));
client.println(F("var request = new XMLHttpRequest();"));
//client.println(F("console.log(request.responseText);"));
client.println(F("request.onreadystatechange = function(){"));
client.println(F("if(this.readyState == 4){"));
client.println(F("if(this.status == 200){"));
client.println(F("if(this.responseText != null){"));
client.println(F("document.getElementById('switch_txt').innerHTML = this.responseText;}}}}"));
client.println(F("request.open(\"GET\", \"ajax_switch\", true);"));
client.println(F("request.send(null);}"));
client.println(F("</script>"));
client.println(F("</head>"));
client.println(F("<body><h1>esp8266</h1>"));
client.println("<p id=\"switch_txt\">Switch state: Not requested...</p>");
client.println("<button type=\"button\"\onclick=\"GetSwitchState()\">Get Switch State</button>");
client.println("</body>");
client.println("</html>");
client.println();
}
// display received HTTP request on serial port
Serial.print(HTTP_req);
HTTP_req = ""; // finished with request, empty string
break;
}
// every line of text received from the client ends with \r\n
if (c == '\n') {
// last character on line of received text
// starting new line with next character read
currentLineIsBlank = true;
}
else if (c != '\r') {
// a text character was received from client
currentLineIsBlank = false;
}
} // end if (client.available())
} // end while (client.connected())
delay(1); // give the web browser time to receive the data
client.stop(); // close the connection
}// end if (client)
}
void printWifiStatus()
{
// print the SSID of the network you're attached to
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print where to go in the browser
}
// send the state of the switch to the web browser
void GetSwitchState(WiFiEspClient client)
{
if (digitalRead(7)) {
client.println("Switch state: ON");
}else {
client.println("Switch state: OFF");
}
}
In effetti il mio suggerimento era incompleto... mea culpa.
Quando si passa un'array ad una funzione è sempre necessario indicare la dimensione ("array to pointer decay") ed infatti il metodo corretto da usare in questo caso è questo
client.println(homepage, sizeof(homepage));
Per quanto riguarda la lentezza del sistema è sicuramente dovuta al fatto che stai usando un esp8266 come modulo e per giunta con un baudrate di soli 9600 bps.
Già il firmware AT castra un bel po' le prestazioni del micro, se ci aggiungi anche una velocità di comunicazione cosi bassa, non mi stupisce la lentezza che riscontri.
Il mio consiglio in questi casi è di evitare di usare "il modulo WiFi" attaccato ad un Uno o quel che è, ma di programmare direttamente una dev-board basata su ESP8266 o meglio ancora su ESP32.
Perfetto proverò lo stesso con l'array che mi hai consigliato, visto che sarebbe molto più comoda la scrittura del codice.
Si effettivamente sarebbe più comodo e performante caricare il tutto direttamente su un espe32 o esp8266 ma attualmente ho solo questo hardware e a dirla tutta ho scelto questa strada per cercare di, imparare qualcosa in più.
Grazie ancora.
In questo caso temo che dovrai convivere con la lentezza del sistema a meno che tu non voglia provare ad aggiornare il firmware AT del modulo esp8266 cosa che a quel punto ti permette di usare la molto più performante libreria WiFiEspAT
ho provato a smanettare un po' con i firmware ma credo di aver peggiorato la situazione, la connessione è ancora più instabile, ho provato a caricare il 2.2.1.0 e il 2.2.0.0 (tramite software esp8266 flash) ma con questi FW i comandi AT smettono di funzionare (o forse sbaglio io procedura non ), scavando nel web ho trovato questo firmware (AiThinker_ESP8266_DIO_8M_8M_20160615_V1.5.4.bin) il quale mi permette di utilizzare i comandi AT, quel "2016" nel nome mi fa pensare che non sia l'ultimissima versione. Dove posso trovare una versione più recente?
Quando feci i miei test del caso, ricordo che il firmware con cui ottenevo risultati migliori era la versione 1.7.
La libreria in questione, con ESP8266 non supporta le versioni > 2.0.0 perché non può lavorare in "passive mode".
Note to 2.0.0 versions: ESP8266 version can't be used with this library. It doesn't support passive receive mode. In ESP32 AT 2.0.0 version UDP doesn't work in passive receive mode.
Il firmware v1.7 l'ho recuperato direttamente dal sito Espressif, però ho visto che adesso lo hanno rimosso, mannaggia a loro!
Da questo link puoi recuperare la versione 1.7.5
Io proverei anche il firmware ESP_ATMod che suggeriscono nel readme (si flasha come se fosse un normale sketch).
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.