[WiFiEsp] TIMEOUT: XXX perchè?

Ciao,
sto continuando a smanettare e a esercitarmi con arduino, mi sapete dire come mai con cadenze casuali ricevo l'errore in oggetto? al posto delle 3 x compaiono numeri casuali.

funziona la trasmissione dei dati in remoto ma ogni tanto mi esce quel timeout? a cosa si riferisce?

il codice di prova che sto usando lo trovate in allegato

grazie in anticipo per l'aiuto

provawifiesp.ino (54.6 KB)

Credo che quantomeno dovresti postare anche l'output di quando questa cosa è successa (almeno una volta diciamo), perché dal listato non si riesce a capire quando possa succedere e chi/cosa emetta quel messaggio (che ti compare sulla seriale o sul client??). Ad esempio sicuro che il livello di segnale sia sufficiente e stabile? PErché nel loop ad esempio non vedo codice per effettuare la riconnessione al WiFi in caso di caduta di segnale.

Credo di essere interessato anche io a questo topic, vediamo come prosegue.

eccomi!!!

intanto grazie per la risposta:

ecco quello che mi esce senza richiedere info da remoto:

[WiFiEsp] Initializing ESP module
[WiFiEsp] Initilization successful - 2.0.0
Attempting to connect to WPA SSID: TIM-31791139
[WiFiEsp] Connected to TIM-31791139
You're connected to the network
SSID: TIM-31791139
IP Address: 192.168.1.6

To see this page in action, open a browser to http://192.168.1.6

[WiFiEsp] Server started on port 80

questo è quello che mi dice il monitor seriale quando invia correttamente le info da remoto

[WiFiEsp] New client 0
New client
[WiFiEsp] Disconnecting  0
Client disconnected

questo quando non funziona:

[WiFiEsp] New client 0
New client
[WiFiEsp] TIMEOUT: 355

la connessione è stabile e sono molto vicino al router... sul discorso della riconnessione ci avrei pensato successivamente... pensavo che servisse solo in caso di riavvio accidentale di arduino e non che perdesse connessione in generale...

grazie per l'aiuto

Quel timeout riguarda la connessione tra Arduino e ESP, non quella tra ESP e Access Point. Forse hai un firmware un po' buggato sull'ESP? Prova ad aggiornarlo.

Prova a vedere QUI se quella modifica indicata può esserti di aiuto.
Dicono di sostituire tutte le linee timeout "readUntil(1000" a "readUntil(2000" nel file EspDrv.cpp.

grazie docdoc,

ho fatto la modifica come consigliato:

questo è quello che mi esce al primo tentativo dopo la modifica... ha aggiornato la pagina correttamente ma poi ha dato il solito errore:

[WiFiEsp] New client 0
New client
[WiFiEsp] Disconnecting  0
Client disconnected
[WiFiEsp] New client 0
New client
[WiFiEsp] TIMEOUT: 132
Client disconnected

questo al secondo:

[WiFiEsp] New client 0
New client
[WiFiEsp] Disconnecting  0
Client disconnected
[WiFiEsp] New client 0
New client
[WiFiEsp] TIMEOUT: 264
Client disconnected

questo al terzo:

Client disconnected
[WiFiEsp] New client 0
New client
[WiFiEsp] Disconnecting  0
Client disconnected
[WiFiEsp] New client 0
New client
[WiFiEsp] TIMEOUT: 295
Client disconnected

questo al quarto:

[WiFiEsp] New client 0
New client
[WiFiEsp] TIMEOUT: 354

per riassumere, tre volte su quattro ha aggiornato la pagina, ma il timeout resta e il problema sussiste ma è migliorato

Non so cosa siano quei numeri dopo "TIMEOUT" (magari se si capisse si potrebbe localizzare meglio quale sia la causa) ma per ora se è migliorato prova ad aumentare, da 2000 a diciamo 5000.

Aspetta un attimo!

Ma il tuo programma è ancora quello che hai postato?

No, perché all'inizio leggo:

SoftwareSerial esp8266(11, 12); // RX, TX
SoftwareSerial Serial1(11, 12); // RX, TX

Ossia definisci DUE oggetti SoftwareSerial sugli STESSI pin!!
Non credo proprio che faccia bene, e tra l'altro "esp8266" è un oggetto che non usi nel resto del codice quindi a cosa serve?

Sicuramente questa cosa bene non fa, anche se al massimo viene ignorata non so se invece in realtà non vada a fare confusione nella gestione della seriale, per cui togli quella riga "esp8266" (che tra l'altro è un oggetto che non usi) e vedi se risolve.

docdoc:
Aspetta un attimo!

Ma il tuo programma è ancora quello che hai postato?

No, perché all'inizio leggo:

SoftwareSerial esp8266(11, 12); // RX, TX

SoftwareSerial Serial1(11, 12); // RX, TX



Ossia definisci **DUE** oggetti SoftwareSerial sugli **STESSI pin**!!
Non credo proprio che faccia bene, e tra l'altro "esp8266" è un oggetto che non usi nel resto del codice quindi a cosa serve?

Sicuramente questa cosa bene non fa, anche se al massimo viene ignorata non so se invece in realtà non vada a fare confusione nella gestione della seriale, per cui togli quella riga "esp8266" (che tra l'altro è un oggetto che non usi) e vedi se risolve.

cacchio!!! si errore mio... nel rinominare la SoftwareSerial ho lasciato anche la vecchia..... :frowning:

cmq eliminando la SoftwareSerial in più e aumentando a 5000 ls situazione peggiora...

che noia...

[WiFiEsp] Initializing ESP module
[WiFiEsp] Initilization successful - 2.0.0
Attempting to connect to WPA SSID: TIM-31791139
[WiFiEsp] Connected to TIM-31791139
You're connected to the network
SSID: TIM-31791139
IP Address: 192.168.1.6

To see this page in action, open a browser to http://192.168.1.6

[WiFiEsp] Server started on port 80
Device error!
[WiFiEsp] New client 0
New client
[WiFiEsp] TIMEOUT: 354
Client disconnected
[WiFiEsp] New client 0
New client
[WiFiEsp] TIMEOUT: 354
Client disconnected

sto continuando a provare... anche ripristinando "readUntil(2000" nel file EspDrv.cpp. il problema sussiste...

nessuno si è mai imbattuto in questo problema? grazie

[WiFiEsp] New client 0
New client
[WiFiEsp] TIMEOUT: 329
Client disconnected
[WiFiEsp] New client 0
New client
[WiFiEsp] TIMEOUT: 318
Client disconnected
[WiFiEsp] New client 0
New client
[WiFiEsp] Disconnecting  0
Client disconnected
[WiFiEsp] New client 0
New client
[WiFiEsp] Disconnecting  0
Client disconnected
[WiFiEsp] New client 0
New client
[WiFiEsp] TIMEOUT: 65
Client disconnected
[WiFiEsp] New client 0
New client
[WiFiEsp] TIMEOUT: 355
Client disconnected

Veramente strana questa cosa...
Senti ma potresti mandare sulla seriale i caratteri che ricevi, così magari si vede meglio qualcosa?
Poi tra "New client" e "Client disconnected" hai notato più o meno quanto tempo passa? Ovvero è quasi immediato o effettivamente passa qualche secondo?

Magari oltre ad abilitare la Serial.write(c) metti anche un print di millis e mandaci l'output:

  if (client) {                               // if you get a client,
    Serial.println(F("New client"));             // print a message out the serial port
    Serial.println(millis());
    buf.init();                               // initialize the circular buffer
    while (client.connected()) {              // loop while the client's connected
      if (client.available()) {               // if there's bytes to read from the client,
        char c = client.read();               // read a byte, then
        buf.push(c);                          // push it to the ring buffer
        // printing the stream to the serial monitor will slow down
        // the receiving of data from the ESP filling the serial buffer
        Serial.write(c);
        // you got two newline characters in a row
        // that's the end of the HTTP request, so send a response
        if (buf.endsWith("\r\n\r\n")) {
          sendHttpResponse(client);
          break;
        }
      }
    }
    // close the connection
    client.stop();
    Serial.println(F("Client disconnected"));
    Serial.println(millis());
  }

UPDATE:
oltre alle cose precedenti, intanto ho comunque voluto vedere nella libreria quand'è che compare quel messaggio e cosa significa quel numero.

In EspDrv.cpp il metodo getData è:

...
bool EspDrv::getData(uint8_t connId, uint8_t *data, bool peek, bool* connClose)
{
	if (connId!=_connId)
		return false;


	// see Serial.timedRead

	long _startMillis = millis();
	do
	{
		if (espSerial->available())
		{
			if (peek)
			{
				*data = (char)espSerial->peek();
			}
			else
			{
				*data = (char)espSerial->read();
				_bufPos--;
			}
			//Serial.print((char)*data);

			if (_bufPos == 0)
			{
				// after the data packet a ",CLOSED" string may be received
				// this means that the socket is now closed

				delay(5);

				if (espSerial->available())
				{
					//LOGDEBUG(".2");
					//LOGDEBUG(espSerial->peek());

					// 48 = '0'
					if (espSerial->peek()==48+connId)
					{
						int idx = readUntil(500, ",CLOSED\r\n", false);
						if(idx!=NUMESPTAGS)
						{
							LOGERROR(F("Tag CLOSED not found"));
						}

						LOGDEBUG();
						LOGDEBUG(F("Connection closed"));

						*connClose=true;
					}
				}
			}

			return true;
		}
	} while(millis() - _startMillis < 2000);

    // timed out, reset the buffer
	LOGERROR1(F("TIMEOUT:"), _bufPos);

    _bufPos = 0;
	_connId = 0;
	*data = 0;
	
	return false;
}

Nota la parte alla fine del metodo: mi pare ovvio quindi per prima cosa che i 2 secondi di timeout siano "scolpiti" nel codice, e poi che il numero che compare dopo "TIMEOUT" è quindi il numero di caratteri ancora nel buffer interno mentre la connessione è ancora attiva.
Questo però potrebbe significare che non hai ricevuto/riconosciuto la stringa che consideri come terminatore, e dopo 2 secondi va (giustamente) in TIMEOUT.

A questo punto quindi per prima cosa la mia domanda è: ma quando accade questo, comunque tu la risposta sul client l'hai ricevuta o (come penso) non ha affatto risposto con l'output dei dati?
Se così fosse, dovremmo/dovresti chiederci/chiederti perché ci siano ancora più di 300 byte nel buffer interno quando va in timeout, ovvero perché non ricevi o non "riconosci" la sequenza terminale della request, ossia una riga a vuoto ("\r\n\r\n").

Intanto comunque prova quanto ti ho scritto nel precedente (la scrittura di debug dei millis e dei caratteri ricevuti) e dicci cosa succede. Poi prova ad alzare quel "2000" scolpito nel codice, portalo a 5000, e ripeti la compilazione e test di prima.

EDIT: comunque leggendo la tua lunghissima loop() inizio a temere che dato che fai "tante" cose nel resto del loop(), soprattutto se ci sono vari delay(), quando cicla all'inizio del loop() c'è il rischio che siano già stati ricevuti vari caratteri e quindi saturato il buffer interno del WiFiEsp che quindi non "vede" i caratteri finali "\r\n\r\n" della linea vuota.
Secondo me dovresti cercare di leggere più rapidamente possibile nel tuo buffer circolare ossia mettere dentro ad una funzione almeno la porzione di codice che legge dal client, e richiamarla più spesso all'interno della loop(), mentre lasciare all'inizio solamente il controllo della linea vuota ricevuta.
Oppure per qualche ragione potresti aver ricevuto altri caratteri dopo la linea vuota, per cui "endsWith" dà sempre false.

Fai un po' di esperimenti anche in questo senso, insieme alle cose che ho scritto sopra e facci sapere.

Io ho proposto una settimana fa di aggiornare il firmware dell'ESP, hai provato?

Senti ma potresti mandare sulla seriale i caratteri che ricevi, così magari si vede meglio qualcosa?

non ho capito cosa devo fare...

Poi tra "New client" e "Client disconnected" hai notato più o meno quanto tempo passa? Ovvero è quasi immediato o effettivamente passa qualche secondo?

prova con readUntil(2000"

passano circa 15 secondi per avere il risultato corretto nella pagina del browser.

questa è la risposta nella seriale(chiedendo l'aggiornamento della pagina una sola volta):

[WiFiEsp] New client 0
New client
17714
GET / HTTP/1.1
Host,*/*;q=0.8
Accept-Language: it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0

[WiFiEsp] Disconnecting  0
Client disconnected
32854
[WiFiEsp] New client 0
New client
34385
[WiFiEsp] TIMEOUT: 167

prova con readUntil(5000"

primo tentativo:

[WiFiEsp] New client 0
New client
130235
GET / HTTP/1.1
Host[WiFiEsp] TIMEOUT: 355

secondo

[WiFiEsp] New client 0
New client
195717
GET / HTTP/1.1
Host[WiFiEsp] TIMEOUT: 355

terzo

[WiFiEsp] New client 0
New client
224772
GET / HTTP/1.1
Hostdeflate
DNT: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0

[WiFiEsp] Disconnecting  0
Client disconnected
239972
[WiFiEsp] New client 0
New client
241509
[WiFiEsp] TIMEOUT: 256

A questo punto quindi per prima cosa la mia domanda è: ma quando accade questo, comunque tu la risposta sul client l'hai ricevuta o (come penso) non ha affatto risposto con l'output dei dati?

no, non esce proprio e la pagina del browser carica all'infinito...

Secondo me dovresti cercare di leggere più rapidamente possibile nel tuo buffer circolare ossia mettere dentro ad una funzione almeno la porzione di codice che legge dal client, e richiamarla più spesso all'interno della loop(), mentre lasciare all'inizio solamente il controllo della linea vuota ricevuta.
Oppure per qualche ragione potresti aver ricevuto altri caratteri dopo la linea vuota, per cui "endsWith" dà sempre false.

Fai un po' di esperimenti anche in questo senso, insieme alle cose che ho scritto sopra e facci sapere.

non saprei come fare onestamente...

Io ho proposto una settimana fa di aggiornare il firmware dell'ESP, hai provato?

cacchio mi era sfuggito....scusami... esiste una guida? grazie

simosere:
non ho capito cosa devo fare...

Te l'avevo scritto nel post #11 dove ti ho fatto la modifica alla if(client) per mandare in seriale quello che ricevi ed il valore dei millis(), e stando a quello che hai poi postato mi pare che tu lo abbia fatto, quindi hai capito! :wink:

Dopodiché però leggi anche il mio post #12 dove oltre a descriverti alcuni dettagli della libreria che usi, ti suggerivo di modificare il valore del timeout della libreria, da 2000 ad almeno 5000 e di dire se migliorava, ma non la readUntil, bensì questa riga che trovi in EspDrv.cpp, all'interno della funzione "EspDrv::getData":

} while(millis() - _startMillis < 2000);

Infine mi dici questo:

passano circa 15 secondi per avere il risultato corretto nella pagina del browser.

Questa cosa mi lascia ancora più perplesso, e 15 secondi per una risposta semplice mi sembra tanto, troppo.

Questo mi lascia pensare che, come ti avevo accennato, il tuo chilometrico loop() nel quale ci sono vari delay() possa portare la comunicazione col server ad essere molto lenta e quindi il grosso del problema è, sempre come già detto, che tu non riesca a ricevere la fine request perché il buffer interno dell'Esp si è saturato, e si giunge al timeout.

Non dico di essere certo che una di queste sia la causa, ma sicuramente temo che qualcosa del genere stia accadendo.

Pertanto oltre a quanto suggerito da SukkoPera ossia aggiornare il firmware se riesci, ti consiglierei di fare quello che ti suggerivo nella parte finale (vedi "EDIT"...) del mio post #12 ovvero creare una funzioncina che vada ad accumulare nel tuo buffer i dati ricevuti dalla seriale, e richiamarla in vari punti della loop() soprattutto prima di ogni delay(), e nella parte iniziale del loop() andrai quindi solamente a verificare la presenza della riga vuota ("\r\n\r\n").

Ciao Docdoc, intanto grazie per il tempo che mi stai dedicando.

ho fatto una prova estrema,oltre a modificare quanto da te consigliato:

} while(millis() - _startMillis < 2000);

portando quel 2000 a 5000, ho cancellato completamente il contenuto dell loop e devo dire che su vari tentativi(5o6) non ho mai avuto il problema del timeout... quindi credo proprio che hai centrato il problema... troppo lungo il loop... poi ti chiedo in riferimento ai vari delay che dici che ci sono, tolto quello per il rinnovo del display, ci sono solo alcuni delay che vengono richiamati in alcuni void , ma quindi non sempre interessati nel loop, no? sbaglio?

ovvero creare una funzioncina che vada ad accumulare nel tuo buffer i dati ricevuti dalla seriale, e richiamarla in vari punti della loop() soprattutto prima di ogni delay(), e nella parte iniziale del loop() andrai quindi solamente a verificare la presenza della riga vuota ("\r\n\r\n").

ok grazie per lo spunto, ma non sono in grado di applicare quanto da te consigliato... quindi mi blocco qui... :frowning:

simosere:
portando quel 2000 a 5000, ho cancellato completamente il contenuto dell loop e devo dire che su vari tentativi(5o6) non ho mai avuto il problema del timeout... quindi credo proprio che hai centrato il problema... troppo lungo il loop...

Più che lungo dipende da quanto ci mette ad eseguire un ciclo nel caso peggiore (ossia quanti millisecondi sono in totale sommando i delay?).

Capisco che ora rivedere quel loop così "logorroico" non sia semplice, ma sarebbe utile separare i vari blocchi "if()" delle condizioni in altrettante funzioni, e fare una programmazione più strutturata non solo per avere un loop più leggibile (hai anche svariate inutili righe vuote), ma anche per permetterti di gestire meglio le varie condizioni e quindi verificare dove potresti evitare i delay() ad esempio se i delay() sono per far lampeggiare un led, si può risolvere facilmente gestendolo con millis() (es. l'accensione la fai dove serve, ma lo spegnimento lo gestisci a fine loop dove lo porti LOW se millis()-startMillis >=100)

poi ti chiedo in riferimento ai vari delay che dici che ci sono, tolto quello per il rinnovo del display, ci sono solo alcuni delay che vengono richiamati in alcuni void , ma quindi non sempre interessati nel loop, no? sbaglio?

Se con "alcuni void" intendi "alcune funzioni" ("void" è il tipo di dato restituito, in questo caso void=nessuno, quindi sono "funzioni", non "void"...:wink: ) se queste vengono richiamate dall'interno del loop() o da altre funzioni, a loro volta nel loop() allora si, incidono pure questi delay().

PS: comunque a me pare che quella sequenza interminabile di "if" si possa sostituire con l'implementazione di una macchina a stati finiti, ma questo discorso sarebbe un poco troppo lunghetto, per ora... :wink:

grazie mille per il supporto dato, la situazione ora mi è chiara. :slight_smile:

non saprei nemmeno da dove iniziare per fare quanto mi dici :confused: , ma cercherò nel tempo di capire come ottimizzare il codice e magari snellirlo.

grazie

ciao ragazzi,
dopo un po di pausa da arduino rieccomi con un quesito:

al fine di rendedere più semplice la lettura da remoto compatibilmente al loop estremamente lungo(senza snellirlo quindi), avrebbe utilità andare a salvare i dati letti durante il loop all'interno di un'SD e richiamare dal controllo da remoto i dati salvati sull'SD?

grazie