I have an arduino and an esp8266 12f (NodeMCU) connected via Serial (SoftSerial on Arduino's side). It works well when sending AT commands directly from computer via a USB-Serial connection, esp8266 answers properly and complies to requests. I use the WifiESP library and have uploaded one of the sample applications (WebServerLed), it works really fine. Since the goal of my project is to trigger relays, I changed the WebServerLed code to update the relays state instead of the LED. That's when I started to have issues.
Here is the code:
#include "WiFiEsp.h"
// Emulate Serial1 on pins 6/7 if not present
#ifndef HAVE_HWSERIAL1
#include "SoftwareSerial.h"
SoftwareSerial Serial1(9, 8); // RX, TX
#endif
char ssid[] = "..."; // your network SSID (name)
char pass[] = "..."; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio's status
int ledStatus = LOW;
int LED = 4;
int relay1Status = HIGH;
int RELAYIN1 = 6;
int relay2Status = HIGH;
int RELAYIN2 = 7;
WiFiEspServer server(80);
// use a ring buffer to increase speed and reduce memory allocation
RingBuffer buf(16);
void setup()
{
pinMode(LED_BUILTIN, OUTPUT); // initialize digital pin LED_BUILTIN as an output.
// Startup sequence
digitalWrite(LED, HIGH);
digitalWrite(RELAYIN1, LOW);
delay(3000);
digitalWrite(RELAYIN1, HIGH);
// Shutdown relays
digitalWrite(RELAYIN1, relay1Status);
digitalWrite(RELAYIN2, relay2Status);
Serial.begin(115200); // initialize serial for debugging
Serial1.begin(9600); // initialize serial for ESP module
WiFi.init(&Serial1); // initialize ESP module
// check for the presence of the shield
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();
// End of startup sequence
digitalWrite(LED, LOW);
}
void loop()
{
WiFiEspClient client = server.available(); // listen for incoming clients
if (client) { // if you get a client,
Serial.println("New client"); // print a message out the serial port
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
// TEST CODE THAT MESSES THE HTTP DEBUG CODE - sorry
if (c != -1) {
Serial.write(c);
} else {
Serial.print("BipBipBipBip");
}
// 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;
}
// Check to see if the client request was "GET /ChangeStatus?relay=1&status=on" or "GET /L":
if (buf.endsWith("GET /r1on")) {
Serial.println("Turn relay 1 on");
relay1Status = LOW;
digitalWrite(RELAYIN1, relay1Status);
} /* ***PART1***
else if (buf.endsWith("GET /r1off")) {
//Serial.println("Turn relay 1 off");
relay1Status = HIGH;
digitalWrite(RELAYIN1, relay1Status);
} */ /* ***PART2***
else if (buf.endsWith("GET /r2on")) {
//Serial.println("Turn relay 2 on");
relay2Status = LOW;
digitalWrite(RELAYIN2, relay2Status);
} else if (buf.endsWith("GET /r2off")) {
//Serial.println("Turn relay 2 off");
relay2Status = HIGH;
digitalWrite(RELAYIN2, relay2Status);
}*/
}
}
// close the connection
client.stop();
Serial.println("Client disconnected");
}
}
void sendHttpResponse(WiFiEspClient client)
{
Serial.print("Sending response");
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println();
// the content of the HTTP response follows the header:
client.print("Relay 1 is ");
client.print(relay1Status);
client.print(" - Relay 2 is ");
client.print(relay2Status);
client.println("<br>");
client.println("<br>");
client.println("Switch relay 1 <a href=\"/r1on\">on</a> or <a href=\"/r1off\">off</a><br>");
client.println("Switch relay 2 <a href=\"/r2on\">on</a> or <a href=\"/r2off\">off</a><br>");
// The HTTP response ends with another blank line:
client.println();
}
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
Serial.println();
Serial.print("To see this page in action, open a browser to http://");
Serial.println(ip);
Serial.println();
}
As is, it works, if I uncomment PART1 in loop(), it sometimes fails and if I also uncomment PART2, it always fails. By failing, I mean the following : I get a "[WiFiEsp] TIMEOUT: xx" and the esp8266 until I reset it (with the button on the board or by temporary bringing to ground the RST pin) After some investigation, it seems getData() fails expecting more data from the ESP through serial and times out after 2seconds. Since I am pretty sure that the uncommented code does not add a 2s delay within the getData execution, I am completely at a loss as to why it fails.
An other interesting point is that I tested this code with an esp01 and with an esp8266 12f and both show the same behavior.
Is there some race condition that I don't understand somewhere ? Do you have any idea of tests I could do to further understand the issue ?
Here is an exemple of Serial Log for an execution of the code:
[WiFiEsp] Initializing ESP module
[WiFiEsp] Initilization successful - 2.0.0
Attempting to connect to WPA SSID: xxx
[WiFiEsp] Connected to xxx
You're connected to the network
SSID: xxx
IP Address: 192.168.0.19
To see this page in action, open a browser to http://192.168.0.19
[WiFiEsp] Server started on port 80
[WiFiEsp] New client 0
New client
GET / HTTP/1.1
Host: 192.168.0.19
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36
Acept tex/htl,aplictio/xhtl+xl,apliatio/xm;q=09,iageavifimae/wep,iageapn,*/*q=08,aplictio/siged-xchnge;=b3q=0.
Acep-Encdin: gzp, eflte
ccet-Lnguae: r-FRfr;=0.,en-S;q0.8,n;q0.7
[WiFiEsp] TIMEOUT: 53
The messed up http log is due to the 5 lines of code that are prefixed by the comment "// TEST CODE THAT MESSES THE HTTP DEBUG CODE", it is not relevant to the problem, the timeout issue is the same if I comment these 5 lines.