NodeMCU not showing page

Im making a choose your own adventure game in my Arduino esp8266 but I'm having a lot of trouble because sometimes pages won't load. I am using a SD card to hold my page so I don't take up too much memory. I'll give an example of one of my pages below.

Setup:

void setup() {
  Serial.begin(115200);
  connectToWifi("SSID", "PASS"); //Function I made elsewhere. Problem is not here.
//INIT SD
  Serial.print("Initializing SD card...");
  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");

  setupBegin_Intro(); //In this function there is   server.on("/INTRO_3", INTRO_3) <- This means when I get a request for /SCENE_3, I run the function INTRO_3() (see below for function)
  
  server.begin(); //Allows connection from clients
}

void loop() {
  server.handleClient();//Handle URL requests from clients
}

INTRO_2()

void INTRO_2() {
  String s = "";
  fileToUse = "Begin_Intro/INTRO_2";
  correctAns = "NEXT";
  whereToCorrect = "INTRO_3";
  s  = "<html>";
  s += "<head>";
  s += "<style>";
  s += "#main {font-family:'Lucida Console', monospace;}";
  s += "</style>";
  s += "<title>MY WEBSITE</title>";
  s += "</head>";
  s += "<body>";
  s += "<center>";
  s += "<div id=\"main\">";
  s += copyImageToMemory(fileToUse);
  s += "</div>";
  s += "<a href=" + whereToCorrect + "><button>" + correctAns + "</button></a><br />";
  s += "</center>";
  s += "</body></html>"; //Read HTML contents
  Serial.println("SENDING: ");
  server.send(200, "text/html", s); //Send web page

  s = "";
  memset(charPic, 0, sizeof(charPic)); //Resets the array that I hold the pic in
}

Getting Pic (No problem here but I thought to add it)

String copyImageToMemory(String fileName) {
  String pic;
  int i = 0;
  myFile = SD.open(fileName + ".txt");
  if (myFile) {
    Serial.println(fileName + ".txt");
    while (myFile.available() && i < maxPixels) {
      charPic[i] = myFile.read();
      i++;
    }
    pic = charPic;
    myFile.close();
  } else {
    Serial.println("error opening file");
  }
  Serial.println("Image copied to memory");
  Serial.printf("using %d characters\n", i);
  return pic;
}

Notes:
I am using ESP8266WebServer Library
This happens on other pages but others work fine
Pressing "view page source" shows me this:

<html>
<head>
    <style>
    #main {
        font-family: 'Lucida Console', monospace;
    }
    </style>
    <title>MY WEBSITE</title>
</head>
<body>
    <center>
        <div id="main"></div>
        <a href=SCENE_1>
            <button>NEXT</button>
        </a>
        <br/>
    </center>
</body>
</html>

Any and all help appreciated :D.

ALL THE CODE THAT HAS ANYTHING TO DO WITH INTRO_3:

#include <SPI.h>
#include <SD.h>

#include <ESP8266WebServer.h>
ESP8266WebServer server(80); //default server port is 80

File myFile;
String fileName = "INTRO_2";


const int maxPixels = 16000;
char curentChar;
char charPic[maxPixels];
String s = "";
int trust = 100;
int trustSubtract = 50;


String fileToUse = "";
String correctAns = "";
String whereToCorrect = "";
String wrongAns = "";
String whereToWrong = "";

String whereFrom = "";
String address;

void connectToWifi(String myssid, String mypass);

void setup() {
  Serial.begin(115200);
  connectToWifi("iPhone (40)", "FrischSyp");
  Serial.print("Initializing SD card...");
  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");

  setupBegin_Intro();
  setupScenes1_to_5();
  setupWrongs();
  setupEndings();
  
  server.begin(); //Allows connection from clients
}
void loop() {
  server.handleClient();//Handle URL requests from clients
}

void INTRO_3() {
  
  fileToUse = "Begin_Intro/INTRO_3";
  correctAns = "NEXT";
  whereToCorrect = "INTRO_4";
  wrongAns = "NO";
  whereToWrong = "INTRO_2";
  s  = "<html>";
  s += "<head>";
  s += "<style>";
  s += "#main {font-family:'Lucida Console', monospace;}";
  s += "</style>";
  s += "<title>Date Peter The Great</title>";
  s += "</head>";
  s += "<body>";
  s += "<center>";
  s += "<div id=\"main\">";
  s += copyImageToMemory(fileToUse);
  s += "</div>";
  s += "<a href=" + whereToCorrect + "><button>" + correctAns + "</button></a><br>";
  s += "</center>";
  s += "</body></html>"; //Read HTML contents
  Serial.println("SENDING: ");
  printf("%s", s);
  server.send(200, "text/html", s); //Send web page
  memset(charPic, 0, sizeof(charPic));
}

void setupBegin_Intro() {
  server.on("/", BEGIN);
  server.on("/INTRO", INTRO);
  server.on("/INTRO_2", INTRO_2);
  server.on("/INTRO_3", INTRO_3);
  server.on("/INTRO_4", INTRO_4);
}

//**********************WIFI********************
#include <ESP8266HTTPClient.h>
#include "ESP8266WiFi.h"

void connectToWifi(String myssid, String mypass){
  Serial.println("Start");
  // Set WiFi to station mode and disconnect from an AP if it was previously connected
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  Serial.println("Setup done");
  // We start by connecting to a WiFi network
  Serial.print("Connecting to ");
  Serial.println(myssid);
  WiFi.begin(myssid, mypass);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(".");
  Serial.print ("Use this URL to connect: http://");
  Serial.println(WiFi.localIP());
}

Well the function name is

void INTRO_2() {

Now it could be just a typo, but i do suggest you show us a bit more of the code to verify
particularly the

setupBegin_Intro();

function.
A typo is easily made also here

s += "<a href=" + whereToCorrect + "><button>" + correctAns + "</button></a><br />";

<br /> is not html, and whatever comes after may not be displayed correctly or even processed (and that includes </body> & </html>

Thanks for responding. I have added the full code into the post, I just didn't want anyone to have to do too much work to find my issue. I will try fixing the < br />.*
*It did not fix

Without the code it is impossible to find the issue.

It wasn't really expecting it too.

So just to make sure, it connects and tells you an IP address in the Serial monitor ?

I actually tend to start out with a simple sketch that turns a led on and off through a webserver, and which allows both connecting to it as an AP and connecting to a network.

Hmm actually first in your webpage this part is missing the page header, that may cause issues

<!DOCTYPE html>

That should precede the <html> tag
so

whereToWrong = "INTRO_2";
  s  = "<!DOCTYPE html><html>";
  s += "<head>";

but let me post that example sketch i have and which i now for sure works ! (the method is not that different from what you do)

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

const char *ssid = "XXX";
const char *password = "xxxxxxxxx";
const char *apname = "esp8266";
const char *appass = "password"; // minimum length 8 characters

ESP8266WebServer server(80);

const int ledpin = 2;  // should be the builtin led of a nodeMCU

uint8_t ledstatus = 0; // this is keeping track of the state (of our statemachine)

const char   // like this these lines are statically declared and const, so we can't change them at all
*pageheader = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">",
 *htmlhead = "<html><head><title>ESPwebserver</title><meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" ></head>",
  *bodystyle = "<body style=\"color: wheat; background-color: teal; font-size: 12pt; font-family: sans-serif;\">",
   *accessIP = "http://192.168.4.1",
    *htmlclose = "</body></html>";

String webIP;

void setup() {
  webIP.reserve(30);  // prevent fragments
  digitalWrite(ledpin, HIGH);
  pinMode(ledpin, OUTPUT);

  Serial.begin(115200);

  WiFi.softAP(apname, appass); // start AP mode
  webIP = accessIP;
  Serial.print("Started Access Point \"");
  Serial.print(apname);
  Serial.println("\"");
  Serial.print("With password \"");
  Serial.print(appass);
  Serial.println("\"");
  WiFi.begin(ssid, password);  // attempt starting STA mode
  Serial.println("Attempting to start Station mode");

  uint32_t moment = millis();
  while ((WiFi.status() != WL_CONNECTED) && (millis() < moment + 8000)) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  if (WiFi.status() == WL_CONNECTED) {
    Serial.print("Connected to ");
    Serial.println(ssid);
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());

    if (MDNS.begin("esp8266")) {  // type esp8266.local/ in your browser
      Serial.println("MDNS responder started, type esp8266.local/ in your browser");
    }
    webIP = StationIP();
  }
  else if (WiFi.status() == WL_CONNECT_FAILED) {
    Serial.print("Connecting to ");
    Serial.print(ssid);
    Serial.println(" Unsuccessful.");
  }
  else if (WiFi.status() == WL_NO_SSID_AVAIL) {
    Serial.print("Network ");
    Serial.print(ssid);
    Serial.println(" not available.");
  }
  WiFi.reconnect();   // reconnect AP after attempting to connect STA

  server.on("/", handleRoot);
  server.begin();
  Serial.println("HTTP server started");
}

void loop() {
  server.handleClient();
  checkLedStatus();
}

void checkLedStatus() {  // our statemachine
  switch (ledstatus) {
    case 0: {
        digitalWrite(ledpin, HIGH);
        return;
      }
    case 1: {
        digitalWrite(ledpin, LOW);
        return;
      }
    case 2: {
        if (ledBlink(500)) ; // here the return value (of ledBlink() ) gets discarded
        return;
      }
    case 3: {
        modulateLed();
        return;
      }
  }
}

void modulateLed() {
  static uint16_t ms = 100;
  static bool increase = true;

  if (!ledBlink(ms)) return;
  if (ms > 250) increase = false;
  if (ms < 20) increase = true;
  if (increase) ms = (ms * 10) / 9;
  else ms = (ms * 9) / 10;
}

bool ledBlink(uint32_t wait) {
  static bool pinstate = false;
  static uint32_t moment = millis();
  if (millis() > moment + wait) {
    pinstate = !pinstate;
    moment = millis();
    if (pinstate) digitalWrite(ledpin, LOW);
    else digitalWrite(ledpin, HIGH);
    return pinstate;  // if pinstate is true and the pinstate has changed, the modulator will change speed
  }
  return false;
}

void handleRoot() {
  String ledstatusupdate;
  if (server.hasArg("led")) {
    if (server.arg("led") == "off") {
      ledstatus = 0;
      ledstatusupdate = "The LED has been turned Off<br>";
    }
    else if (server.arg("led") == "on") {
      ledstatus = 1;
      ledstatusupdate = "The LED has been turned On<br>";
    }
    else if (server.arg("led") == "blink") {
      ledstatus = 2;
      ledstatusupdate = "The LED has been set to Blink<br>";
    }
    else if (server.arg("led") == "modulate") {
      ledstatus = 3;
      ledstatusupdate = "The LED has been set to Modulate<br>";
    }
  }

  String s = "";
  s += pageheader;
  s += htmlhead;
  s += bodystyle;

  s += "<h1>Welcome to ESP webserver</h1><p>From here you can control your LED making it blink or just turn on or off. ";
  s += "</p>";

  s += ledstatusupdate;
  s += "<br>";

  s += "<form action=\"";
  s += webIP;
  s += "\" method=\"get\" name=\"button\">";
  s += "<input type=\"hidden\" name=\"led\" value=\"on\">"; // the hidden parameter gets included
  s += "<input type=\"submit\" value=\" LED ON \"></form><br>"; // the button simply submits the form

  s += "<form action=\"";
  s += webIP;
  s += "\" method=\"get\" name=\"button\">";
  s += "<input type=\"hidden\" name=\"led\" value=\"off\">";
  s += "<input type=\"submit\" value=\" LED OFF\"></form><br>";

  s += "<form action=\"";
  s += webIP;
  s += "\" method=\"get\" name=\"button\">";
  s += "<input type=\"hidden\" name=\"led\" value=\"blink\">";
  s += "<input type=\"submit\" value=\"  BLINK  \"></form><br>";

  s += "<form action=\"";
  s += webIP;
  s += "\" method=\"get\" name=\"button\">";
  s += "<input type=\"hidden\" name=\"led\" value=\"modulate\">";
  s += "<input type=\"submit\" value=\"MODULATE\"></form><br>";

  s += htmlclose;
  yield();  // not stricktly neccesary, though the String class can be slow
  server.send(200, "text/html", s); //Send web page
}


String StationIP() {
  String stationIP = "http://";
  stationIP += WiFi.localIP().toString();
  return stationIP;
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.