I am working with a Raspberry Pi4 and the ESP8266. I am using a generic example of toggling a LED, but running into an issue
It seems there are issues with the compiling of
const char MAIN_page[] PROGMEM = R"=====(
when running on Windows vs MAC, but there is no mention of Linux
below is the code and below that is the result from the serial print
IT seems to tell me I called the webpage, but doesn't print the message to the serial printline. same results if I remove that.
Any help is appreciated.
*
* ESP8266 NodeMCU LED Control over WiFi Demo
*
* https://circuits4you.com
*/
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
//ESP Web Server Library to host a web page
#include <ESP8266WebServer.h>
//---------------------------------------------------------------
//Our HTML webpage contents in program memory
const char MAIN_page[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
<body>
<center>
<h1>WiFi LED on off demo: 1</h1>
Click to turn <a href="ledOn">LED ON</a>
Click to turn <a href="ledOff">LED OFF</a>
<hr>
</center>
</body>
</html>
)=====";
//---------------------------------------------------------------
//On board LED Connected to GPIO2
#define LED D1
//SSID and Password of your WiFi router
const char* ssid = "SSID";
const char* password = "PWD";
//Declare a global object variable from the ESP8266WebServer class.
ESP8266WebServer server(80); //Server on port 80
//===============================================================
// This routine is executed when you open its IP in browser
//===============================================================
void handleRoot() {
Serial.println("You called root page");
String s = MAIN_page; //Read HTML contents
Serial.println(s);
server.send(200, "text/html", s); //Send web page
}
It looks like the crash happened in one of these two lines:
String s = MAIN_page; //Read HTML contents
Serial.println(s);
Does the ESP8266 compiler keep track of which strings are in PROGMEM and which aren't? The AVR compiler certainly doesn't. On the AVR processors it it up to the programmer to keep track of which things are in PROGMEM and call the special PROGMEM version of functions. Does the code work if you take the PROGMEM keyword off your character array? If so, you need to find a way to populate a String from a character array in PROGMEM. You may have to do that byte by byte. Of course there is no reason to put a string in PROGMEM if you are just going to copy it into RAM anyway.
I am not sure if it does or not. I am not good with these chips and figured the exapmles worked. The code came from the guy using a 8266 chip so i assumed it works. Ill dig in when i get home. Also from 6v6gts recommendation on the debugging link the recommendation is to use progmem.
Don’t use const char * with literals. Instead, use const char[] PROGMEM. This is particularly true if you intend to, e.g.: embed html strings.
I actually have had a similar example running where the declaration of the page is declared the same way (but in a separate header file) and it worked fine for me, the pleasure of doing it like this is that you can write 'straight' html-code, without having to worry about the " in there, which does make it a lot more readable. In the end it does go into a String ad actually on an ESP that is fine (for sure if declared locally within the callback just to create a webpage to be send. Disadvantage is that the Webpage now is static and can not display variables from within the code and/or user input, So in the end usually this method is not the final choice. Still i am also a little puzzled by why it is not working for you, mind you there are a few things missing from your sketch (or the part that you posted) which might hold some clues to that. On second thought, what happens when you comment out this line :Serial.println(s);i have a vague recollection of me trying the same thing and the size of s is a bit more than what the println (part of the stream class ? ) can hold.
You have also got the send_P() method of the ESP8266WebServer class. You can directly use a progmem construct and don't need the intermediate String (unless you need to edit the html before sending it) :
Ok, I got the stack trace done, and the results are as follows
Decoding stack results
0x402066b7: String::changeBuffer(unsigned int) at /home/pi/.arduino15/packages/esp8266/hardware/esp8266/2.4.2/cores/esp8266/WString.cpp line 156
0x401007c6: malloc at /home/pi/.arduino15/packages/esp8266/hardware/esp8266/2.4.2/cores/esp8266/umm_malloc/umm_malloc.c line 1676
0x40204e15: ESP8266WebServer::_parseArguments(String) at /home/pi/.arduino15/packages/esp8266/hardware/esp8266/2.4.2/libraries/ESP8266WebServer/src/Parsing.cpp line 283
0x40204c14: ESP8266WebServer::RequestArgument::RequestArgument() at /home/pi/.arduino15/packages/esp8266/hardware/esp8266/2.4.2/libraries/ESP8266WebServer/src/ESP8266WebServer.h line 160
0x4020482c: FunctionRequestHandler::handle(ESP8266WebServer&, HTTPMethod, String) at /home/pi/.arduino15/packages/esp8266/hardware/esp8266/2.4.2/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h line 37
0x402066b7: String::changeBuffer(unsigned int) at /home/pi/.arduino15/packages/esp8266/hardware/esp8266/2.4.2/cores/esp8266/WString.cpp line 156
0x40206703: String::reserve(unsigned int) at /home/pi/.arduino15/packages/esp8266/hardware/esp8266/2.4.2/cores/esp8266/WString.cpp line 146
0x40206735: String::copy(char const*, unsigned int) at /home/pi/.arduino15/packages/esp8266/hardware/esp8266/2.4.2/cores/esp8266/WString.cpp line 175
0x40206782: String::String(char const*) at /home/pi/.arduino15/packages/esp8266/hardware/esp8266/2.4.2/cores/esp8266/WString.cpp line 36
0x40206334: Print::println(char const*) at /home/pi/.arduino15/packages/esp8266/hardware/esp8266/2.4.2/cores/esp8266/Print.cpp line 190
0x4020274e: handleRoot() at /home/pi/Arduino Projects/Garage Door/Garage_Door_Website/Garage_Door_Website.ino line 46
0x401009e4: free at /home/pi/.arduino15/packages/esp8266/hardware/esp8266/2.4.2/cores/esp8266/umm_malloc/umm_malloc.c line 1755
0x40203d80: FunctionRequestHandler::canHandle(HTTPMethod, String) at /home/pi/.arduino15/packages/esp8266/hardware/esp8266/2.4.2/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h line 20
0x4020743e: std::_Function_handler ::_M_invoke(std::_Any_data const&) at /home/pi/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/1.20.0-26-gb404fb9-2/xtensa-lx106-elf/include/c++/4.8.5/functional line 2073
0x40204822: std::function ::operator()() const at /home/pi/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/1.20.0-26-gb404fb9-2/xtensa-lx106-elf/include/c++/4.8.5/functional line 2472
0x4020485e: FunctionRequestHandler::handle(ESP8266WebServer&, HTTPMethod, String) at /home/pi/.arduino15/packages/esp8266/hardware/esp8266/2.4.2/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h line 44
0x40206864: String::String(String const&) at /home/pi/.arduino15/packages/esp8266/hardware/esp8266/2.4.2/cores/esp8266/WString.cpp line 41
0x402048e5: ESP8266WebServer::_handleRequest() at /home/pi/.arduino15/packages/esp8266/hardware/esp8266/2.4.2/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp line 590
0x401067e0: millis at /home/pi/.arduino15/packages/esp8266/hardware/esp8266/2.4.2/cores/esp8266/core_esp8266_wiring.c line 183
0x40203bf0: WiFiServer::available(unsigned char*) at /home/pi/.arduino15/packages/esp8266/hardware/esp8266/2.4.2/libraries/ESP8266WiFi/src/WiFiServer.cpp line 111
0x40203d80: FunctionRequestHandler::canHandle(HTTPMethod, String) at /home/pi/.arduino15/packages/esp8266/hardware/esp8266/2.4.2/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h line 20
0x40204adc: ESP8266WebServer::handleClient() at /home/pi/.arduino15/packages/esp8266/hardware/esp8266/2.4.2/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp line 303
0x40207434: std::_Function_handler ::_M_invoke(std::_Any_data const&) at /home/pi/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/1.20.0-26-gb404fb9-2/xtensa-lx106-elf/include/c++/4.8.5/functional line 2069
0x4020297c: loop() at /home/pi/Arduino Projects/Garage Door/Garage_Door_Website/Garage_Door_Website.ino line 99
0x402071fc: loop_wrapper() at /home/pi/.arduino15/packages/esp8266/hardware/esp8266/2.4.2/cores/esp8266/core_esp8266_main.cpp line 125
line 99 for the Garage_door_website is the last line if my code, I am not sure if it follows the same numbering as the script, or if it skips comments and includes other include files as well.
line 46 is sending the HTML to the client
/*
* ESP8266 NodeMCU LED Control over WiFi Demo
*
* https://circuits4you.com
*/
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
//ESP Web Server Library to host a web page
#include <ESP8266WebServer.h>
//---------------------------------------------------------------
//Our HTML webpage contents in program memory
const char MAIN_page[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
<body>
<center>
<h1>WiFi LED on off demo: 1</h1>
Click to turn <a href="ledOn">LED ON</a>
Click to turn <a href="ledOff">LED OFF</a>
<hr>
</center>
</body>
</html>
)=====";
//---------------------------------------------------------------
//On board LED Connected to GPIO2
#define LED D1
//SSID and Password of your WiFi router
const char* ssid = "SSID";
const char* password = "PASSWORD";
//Declare a global object variable from the ESP8266WebServer class.
ESP8266WebServer server(80); //Server on port 80
//===============================================================
// This routine is executed when you open its IP in browser
//===============================================================
void handleRoot() {
Serial.println("You called root page");
String s = MAIN_page; //Read HTML contents
//Serial.println(s);
server.send(200, "text/html", s); //Send web page <----------------------Line 46
}
void handleLEDon() {
Serial.println("LED on page");
digitalWrite(LED,LOW); //LED is connected in reverse
server.send(200, "text/html", "LED is ON"); //Send ADC value only to client ajax request
}
void handleLEDoff() {
Serial.println("LED off page");
digitalWrite(LED,HIGH); //LED off
server.send(200, "text/html", "LED is OFF"); //Send ADC value only to client ajax request
}
//==============================================================
// SETUP
//==============================================================
void setup(void){
Serial.begin(115200);
WiFi.begin(ssid, password); //Connect to your WiFi router
Serial.println("");
//Onboard LED port Direction output
pinMode(LED,OUTPUT);
//Power on LED state off
digitalWrite(LED,HIGH);
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
//If connection successful show IP address in serial monitor
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP()); //IP address assigned to your ESP
server.on("/", handleRoot); //Which routine to handle at root location. This is display page
server.on("/ledOn", handleLEDon); //as Per <a href="ledOn">, Subroutine to be called
server.on("/ledOff", handleLEDoff);
server.begin(); //Start server
Serial.println("HTTP server started");
}
//==============================================================
// LOOP
//==============================================================
void loop(void){
server.handleClient(); //Handle client requests
}
void handleRoot() {
Serial.println("You called root page");
String s = MAIN_page; //Read HTML contents // what a wasted RAM
//Serial.println(s); // you better commented this
server.send(200, "text/html", s); //Send web page <----------------------Line 46
}
do this instead
void handleRoot() {
Serial.println("You called root page");
//Serial.println(s);
server.send_P(200, "text/html", MAIN_page, sizeof(MAIN_page) ); //Send web page
}