Reputation: 890
I am struggling to get ESP8266 connected to an Arduino Uno working reliably as a webserver. The firmware of my ESP8266 is 1.1.1 - I don't have the option (or knowledge) to update it at the moment. Below is my code. It works, barely, if I serve a small string. However, it usually closes the connection or just loads forever (crashes?) if I try to load the page from the browser three or four times. Ultimately I need to serve a webpage with json embedded in it that will load a second page served by the esp8266, a json file. I have a working demo of that but it crashes after a few retrievals. I understand that my html page is too long for strings so have been attempting to shift across to PROGMEM, initially testing with just a short string. I am storing and retrieving that correctly (I think, at least I can Serial.print
it) but as soon as I try to write it to the ESP8266 I get a never ending load in my browser.
Where am I going wrong here? Is it the string/PROGMEM that is causing the issues or is there something else I'm missing in the AT commands (like some sort of ping to keep the connection open)?
//load softserial library
#include <SoftwareSerial.h>
#include <avr/pgmspace.h>
//set a boolean constant variable to true
//#define DEBUG true
const boolean DEBUG = true;
//RX (pin 2) goes to TX on esp8266, TX (pin 3) goes to RX on esp8266
SoftwareSerial esp8266(2, 3);
//input from the photoresistor
//int photoresistorpin = 0;
//create a PROGMEM variable
//String WEBPAGE = "hello";
static const char PROGMEM WEBPAGE[] = {"hello"};
/*
static const char WEBPAGE[] PROGMEM = R"rawliteral(
<html>
<head>
<meta name="viewport" content="width=device-width, minimumscale=1, maximum-scale=1, initial-scale=1">
</head>
<h1>Light:</h1><div id="light"></div>
<script>
function loadDoc()
{
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200)
{
var obj = JSON.parse(this.responseText);
document.getElementById('light').innerHTML = obj.data[0].datavalue;
}
};
xhttp.open('GET', 'data.json', true); xhttp.send();
}
var timedEvent = setInterval(function() { loadDoc(); }, 5000);
</script>
</body>
</html>
)rawliteral";
*/
//const int WEBPAGE_len = sizeof(WEBPAGE)/sizeof(WEBPAGE[0]);
void setup()
{
//open the serial port
Serial.begin(115200);
//print setup started in the serial monitor
Serial.println("Setup started");
//start esp8266 module (note: your esp's baud rate might be different)
esp8266.begin(115200);
//reset esp8266 module
senddata("AT+RST\r\n", 2000, DEBUG);
//set esp8266 as access point mode
//1 = Station mode (client)
//2 = Access point mode (host)
//3 = Access point mode + Station mode
senddata("AT+CWMODE=2\r\n", 1000, DEBUG);
//get ip address for esp8266
senddata("AT+CIFSR\r\n", 2000, DEBUG);
//configure esp8266 for multiple connections
senddata("AT+CIPMUX=1\r\n", 1000, DEBUG);
//turn on esp8266 server on port 80
senddata("AT+CIPSERVER=1,80\r\n", 1000, DEBUG);
//setup completed
Serial.println("Setup done");
}
void loop()
{
//take a reading from the photoresistor
//int lightval = analogRead(photoresistorpin);
int lightval = random(1000);
//to test
//Serial.println(lightval);
//is the esp8266 sending a message
if (esp8266.available())
{
//if received data from esp8266
if (esp8266.find("+IPD,"))
{
//subtract 48 because the read() function returns the ASCII decimal
//value and 0 (the first decimal number) starts at 48
int connectionid = esp8266.read() - 48;
//Serial.println("");
//Serial.println("*****");
//Serial.print("string = ");
//read the url sent by the client, look for the variable (/)
String msg;
esp8266.find("/");
delay(100);
msg = esp8266.readStringUntil(' ');
String pathrequested = msg.substring(0);
Serial.println("*****");
Serial.println(pathrequested);
Serial.println("*****");
//create a senddata string to send the webpage to the esp8266
String cipsend = "AT+CIPSEND=" + String(connectionid) + ",";
//cipsend += WEBPAGE.length();
cipsend += strlen_P(WEBPAGE);
cipsend += "\r\n";
Serial.println(cipsend);
char buffer[1000];
strcpy_P(buffer, WEBPAGE);
Serial.println(buffer);
//senddata(cipsend, 500, DEBUG);
//senddata(WEBPAGE, 500, DEBUG);
senddata(buffer, 500, DEBUG);
//create a string closecommand with the connection id and send it
String closecommand = "AT+CIPCLOSE=" + String(connectionid) + "\r\n";
senddata(closecommand, 500, DEBUG);
//increment the count
//count++;
}
}
}
void senddata(String command, const int timeout, boolean debug)
{
//send the received command to the esp8266
esp8266.print(command);
//set int variable to the number of millisends since Arduino began
long int time = millis();
//while the time and the timeout is less than the number of millisends since Arduino began
while((time + timeout) > millis())
{
//while the esp8266 is sending messages
while(esp8266.available())
{
//display output in the serial window
Serial.write(esp8266.read());
}
}
}
Upvotes: 1
Views: 504
Reputation: 2989
Assuming that "get a never ending load in my browser" means no display in the browser - check the following:
1. Get rid of String amd String constructors (+=) in your code and replace it with a fixed char array for the building of messages. Read more: https://hackingmajenkoblog.wordpress.com/2016/02/04/the-evils-of-arduino-strings/
2. My experience with the AT interface was - more than 9600 baud is not reliable and this is not sufficient for doing what you want.
3. If your Esp module has min 512kb (most likely up to 4Mb) host your code there and use the UNO only as sigmal receiver/sender from the attached hardware/ sensors. Save yourself a lot of trouble and problems - most of the examples with AT com are not really working and more of a pain in the ***. I ditched the AT interface within 2 days and never in the last 4 years missed anything.
By flashing code to the Esp module you also have full control and visibility on whats going on due to the debug possiblitie AND you can even host html/css/js on the File system there (LittleFS / SPIFFS)
Upvotes: 1