Web server strange behaviour (ESP8266 + RedBoard)?

Hello,

I am using RedBoard with ESP8266. I have tried the basic example ([ESP8266_Shield_Demo) and it worked fine:

However, after I tried to extend the example I have started to hit some yet invisible wall. :slight_smile:

It looks like as the web server would have certain limit in bytes it is willing to send in response. I have added the [Time library and simply try to show in the web page the current time. Well, it gives no result. It looks like as the calls to the Time library functions would be simply ignored.

If I try in the extended code:

htmlBody += "Current time: ";
htmlBody += String(now()); //Yes, for the moment just as a number of seconds elapsed since Jan 1 1970.
htmlBody += "
\n"

The HTML code would contain only "Current time:
". As the call to the Time function would not exist at all.

Furthermore, the original code contains the reading and displaying of analog inputs:

// output the value of each analog input pin
          for (int a = 0; a < 6; a++)
          {
            htmlBody += "A";
            htmlBody += String(a);
            htmlBody += ": ";
            htmlBody += String(analogRead(a));
            htmlBody += "
\n";
          }

If I simply start to add the text (even without calls of any functions/libraries) - just some text, then at some point the result of the given for loop will be presented without indexes and values. It will contain a column of "A:"s displayed in the web page.

What is puzzling me is that after construction of the htmlBody String there is the line in the code that actually sends the html page:

client.print(htmlBody);

But the result is strangely selective, if I would try to extend the code… as the program would suddenly say: “Arghh, lets not wait the result of these function readings or int-to-string parsing; we have more important things to do, lets send partial data…” Even more, it does not matter where I put extra text before the for loop OR after it. If the text hits “some yet-unknown limit”, the result goes without indexes or values.

Well, I could still understand if there will be some sort of limited buffer, but it would be rather cutting only the end of the htmlBody String or some concrete part. Instead comes some sort of “selective” “removal” of intermediate results for the functions.

What could be the reason for such strange behaviour? Could anyone kindly bring the enlightenment by opening new horizons in understanding of programming principles for RedBoard and ESP8266?

Thank you.](Arduino Playground - HomePage)](https://learn.sparkfun.com/tutorials/esp8266-wifi-shield-hookup-guide#installing-the-esp8266-at-library)

hworost:
Hello,

I am using RedBoard with ESP8266. I have tried the basic example ([ESP8266_Shield_Demo) and it worked fine:

However, after I tried to extend the example I have started to hit some yet invisible wall. :)…[/quote]We can’t see it either. Show the rest of the code where the bug might be hiding. Not just tidbits.](https://learn.sparkfun.com/tutorials/esp8266-wifi-shield-hookup-guide#installing-the-esp8266-at-library)

Have you considered sending the htmlBody over serial to the Pc, so you can see what is actually in those memory spots?

Hello,

Here you are. Illustration of “strange behaviour” using “the very big text” in serverDemo() function below.

The Code:

/************************************************************
ESP8266_Shield_Demo.h
SparkFun ESP8266 AT library - Demo
Jim Lindblom @ SparkFun Electronics
Original Creation Date: July 16, 2015
https://github.com/sparkfun/SparkFun_ESP8266_AT_Arduino_Library

This example demonstrates the basics of the SparkFun ESP8266
AT library. It'll show you how to connect to a WiFi network,
get an IP address, connect over TCP to a server (as a client),
and set up a TCP server of our own.

Development environment specifics:
  IDE: Arduino 1.6.5
  Hardware Platform: Arduino Uno
  ESP8266 WiFi Shield Version: 1.0

This code is released under the MIT license.

Distributed as-is; no warranty is given.
************************************************************/

//////////////////////
// Library Includes //
//////////////////////
// SoftwareSerial is required (even you don't intend on
// using it).
#include <SoftwareSerial.h> 
#include <SparkFunESP8266WiFi.h>
#include <Time.h>  

//////////////////////////////
// WiFi Network Definitions //
//////////////////////////////
// Replace these two character strings with the name and
// password of your WiFi network.
const char mySSID[] = "<my_SSID>";
const char myPSK[] = "<my_PSK>";

//////////////////////////////
// ESP8266Server definition //
//////////////////////////////
// server object used towards the end of the demo.
// (This is only global because it's called in both setup()
// and loop()).
ESP8266Server server = ESP8266Server(80);


//////////////////
// HTTP Strings //
//////////////////
const char destServer[] = "example.com";
const String htmlHeader = "HTTP/1.1 200 OK\r\n"
                          "Content-Type: text/html\r\n"
                          "Connection: close\r\n\r\n"
                          "<!DOCTYPE HTML>\r\n"
                          "<html><head><meta http-equiv=\"refresh\" content=\"4\"></head>\r\n";

const String httpRequest = "GET / HTTP/1.1\n"
                           "Host: example.com\n"
                           "Connection: close\n\n";

// All functions called from setup() are defined below the
// loop() function. They modularized to make it easier to
// copy/paste into sketches of your own.
void setup() 
{
  // Serial Monitor is used to control the demo and view
  // debug information.
  Serial.begin(9600);
  serialTrigger(F("Press any key to begin."));

  // initializeESP8266() verifies communication with the WiFi
  // shield, and sets it up.
  initializeESP8266();

  // connectESP8266() connects to the defined WiFi network.
  connectESP8266();

  // displayConnectInfo prints the Shield's local IP
  // and the network it's connected to.
  displayConnectInfo();

 // serialTrigger(F("Press any key to connect client."));
 // clientDemo();

  unsigned long pctime;
  Serial.println();
  Serial.println("Enter current time (seconds passed since Jan 1 1970)");
  Serial.println();
  while (!Serial.available())
    ;
  
  pctime = Serial.parseInt();
  setTime(pctime);

  digitalClockDisplay();
  
  //serialTrigger(F("Press any key to test server."));
  serverSetup();
}

void loop() 
{
  serverDemo();
}

void initializeESP8266()
{
  // esp8266.begin() verifies that the ESP8266 is operational
  // and sets it up for the rest of the sketch.
  // It returns either true or false -- indicating whether
  // communication was successul or not.
  // true
  int test = esp8266.begin();
  if (test != true)
  {
    Serial.println(F("Error talking to ESP8266."));
    errorLoop(test);
  }
  Serial.println(F("ESP8266 Shield Present"));
}

void connectESP8266()
{
  // The ESP8266 can be set to one of three modes:
  //  1 - ESP8266_MODE_STA - Station only
  //  2 - ESP8266_MODE_AP - Access point only
  //  3 - ESP8266_MODE_STAAP - Station/AP combo
  // Use esp8266.getMode() to check which mode it's in:
  int retVal = esp8266.getMode();
  if (retVal != ESP8266_MODE_STA)
  { // If it's not in station mode.
    // Use esp8266.setMode([mode]) to set it to a specified
    // mode.
    retVal = esp8266.setMode(ESP8266_MODE_STA);
    if (retVal < 0)
    {
      Serial.println(F("Error setting mode."));
      errorLoop(retVal);
    }
  }
  Serial.println(F("Mode set to station"));

  // esp8266.status() indicates the ESP8266's WiFi connect
  // status.
  // A return value of 1 indicates the device is already
  // connected. 0 indicates disconnected. (Negative values
  // equate to communication errors.)
  retVal = esp8266.status();
  if (retVal <= 0)
  {
    Serial.print(F("Connecting to "));
    Serial.println(mySSID);
    // esp8266.connect([ssid], [psk]) connects the ESP8266
    // to a network.
    // On success the connect function returns a value >0
    // On fail, the function will either return:
    //  -1: TIMEOUT - The library has a set 30s timeout
    //  -3: FAIL - Couldn't connect to network.
    retVal = esp8266.connect(mySSID, myPSK);
    if (retVal < 0)
    {
      Serial.println(F("Error connecting"));
      errorLoop(retVal);
    }
  }
}

void displayConnectInfo()
{
  char connectedSSID[24];
  memset(connectedSSID, 0, 24);
  // esp8266.getAP() can be used to check which AP the
  // ESP8266 is connected to. It returns an error code.
  // The connected AP is returned by reference as a parameter.
  int retVal = esp8266.getAP(connectedSSID);
  if (retVal > 0)
  {
    Serial.print(F("Connected to: "));
    Serial.println(connectedSSID);
  }

  // esp8266.localIP returns an IPAddress variable with the
  // ESP8266's current local IP address.
  IPAddress myIP = esp8266.localIP();
  Serial.print(F("My IP: ")); Serial.println(myIP);
}

void clientDemo()
{
  // To use the ESP8266 as a TCP client, use the 
  // ESP8266Client class. First, create an object:
  ESP8266Client client;

  // ESP8266Client connect([server], [port]) is used to 
  // connect to a server (const char * or IPAddress) on
  // a specified port.
  // Returns: 1 on success, 2 on already connected,
  // negative on fail (-1=TIMEOUT, -3=FAIL).
  int retVal = client.connect(destServer, 80);
  if (retVal <= 0)
  {
    Serial.println(F("Failed to connect to server."));
    return;
  }

  // print and write can be used to send data to a connected
  // client connection.
  client.print(httpRequest);

  // available() will return the number of characters
  // currently in the receive buffer.
  while (client.available())
    Serial.write(client.read()); // read() gets the FIFO char
  
  // connected() is a boolean return value - 1 if the 
  // connection is active, 0 if it's closed.
  if (client.connected())
    client.stop(); // stop() closes a TCP connection.
}

void serverSetup()
{
  // begin initializes a ESP8266Server object. It will
  // start a server on the port specified in the object's
  // constructor (in global area)
  server.begin();
  Serial.print(F("Server started! Go to "));
  Serial.println(esp8266.localIP());
  Serial.println();
}

void serverDemo()
{
  // available() is an ESP8266Server function which will
  // return an ESP8266Client object for printing and reading.
  // available() has one parameter -- a timeout value. This
  // is the number of milliseconds the function waits,
  // checking for a connection.
  ESP8266Client client = server.available(700);
  
  if (client) 
  {
    Serial.println(F("Client Connected!"));
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) 
    {
      if (client.available()) 
      {
        char c = client.read();
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) 
        {
          Serial.println(F("Sending HTML page"));
          // send a standard http response header:
          client.print(htmlHeader);
          String htmlBody;


          htmlBody += "Just some big text. This is very big text in front.";
          htmlBody += "
\n";

          htmlBody += "LTQ: "; //Just some labels for future use

          htmlBody += "
\n";
          
          htmlBody += "LTM: ";

          htmlBody += "
\n";
          
          htmlBody += "LTL: ";

          htmlBody += "
\n";
      
         // output the value of each analog input pin
          for (int a = 0; a < 6; a++)
          {
            htmlBody += "A";
            htmlBody += String(a);
            htmlBody += ": ";
            htmlBody += String(analogRead(a));
            htmlBody += "
\n";
          }
          
          htmlBody += "<hr>\n";
          htmlBody += "
\n";
          htmlBody += "CT: ";
          //htmlBody += String(now()); //Yes, this line is just commented out for the moment.
          
          htmlBody += "</html>\n";
          Serial.print(htmlBody);
          client.print(htmlBody);
          break;
        }
        if (c == '\n') 
        {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') 
        {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(20);
   
    // close the connection:
    client.stop();
    Serial.println(F("Client disconnected"));
  }
  
}

// errorLoop prints an error code, then loops forever.
void errorLoop(int error)
{
  Serial.print(F("Error: ")); Serial.println(error);
  Serial.println(F("Looping forever."));
  for (;;)
    ;
}

// serialTrigger prints a message, then waits for something
// to come in from the serial port.
void serialTrigger(String message)
{
  Serial.println();
  Serial.println(message);
  Serial.println();
  while (!Serial.available())
    ;
  while (Serial.available())
    Serial.read();
}

void digitalClockDisplay(){
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year()); 
  Serial.println(); 
}

void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

Output of The Code on Serial Monitor (Please note what happens to As. First “A0: value” and then… “A:”):

Client Connected!
Sending HTML page
Just some big text. This is very big text in front.

LTQ: 

LTM: 

LTL: 

A0: 8

A: 

A: 

A: 

A: 

A: 

<hr>


CT: </html>
Client disconnected

If I comment out in the code following line (the big text):

 htmlBody += "Just some big text. This is very big text in front.";

Then, the resulting web page displays as it should (note “An: value”):

Client Connected!
Sending HTML page


LTQ: 

LTM: 

LTL: 

A0: 7

A1: 567

A2: 470

A3: 410

A4: 348

A5: 295

<hr>


CT: </html>
Client disconnected

So in fact the Time library seems to have nothing to do here. The “strange behaviour” starts if to add “big text”: A1-A5 label indexes and values are not “generated” in the for loop in the servoDemo() function.

What could be the reason?

Thank you.

Did you want to run this code on the ESP8266, or on the Redboard? Because I think it was first compiled for the ESP8266, considering it has only 1 analog input. After you commented out the very long text line at the beginning something else must have happened in the Arduino IDE to make it compile for the Redboard and show the 6 analog input values.

Valen:
Did you want to run this code on the ESP8266, or on the Redboard?

[ESP8266 rests on top of the RedBoard. “Arduino/Genuino Uno” is selected as a Board from tools menu of Arduino 1.6.6 IDE that is used to upload the code. The usb cable is connected from PC to the RedBoard. The code is executed on the RedBoard.](ESP8266 WiFi Shield Hookup Guide - SparkFun Learn)