SparkFun Forums 

Where electronics enthusiasts find answers.

All things pertaining to wireless and RF links
By hworost
#186361
Hello,

I am using RedBoard with ESP8266. I have tried the basic example (ESP8266_Shield_Demo) and it worked fine:
* https://learn.sparkfun.com/tutorials/es ... at-library

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

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:
Code: Select all
htmlBody += "Current time: ";
htmlBody += String(now()); //Yes, for the moment just as a number of seconds elapsed since Jan 1 1970.
htmlBody += "<br>\n"
The HTML code would contain only "Current time: <br>". As the call to the Time function would not exist at all.

Furthermore, the original code contains the reading and displaying of analog inputs:
Code: Select all
// 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 += "<br>\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:
Code: Select all
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.
By Valen
#186413
hworost wrote:Hello,

I am using RedBoard with ESP8266. I have tried the basic example (ESP8266_Shield_Demo) and it worked fine:
* https://learn.sparkfun.com/tutorials/es ... at-library

However, after I tried to extend the example I have started to hit some yet invisible wall. :)...
We can't see it either. Show the rest of the code where the bug might be hiding. Not just tidbits.
By hworost
#186436
Hello,

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

The Code:
Code: Select all
/************************************************************
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 += "<br>\n";

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

          htmlBody += "<br>\n";
          
          htmlBody += "LTM: ";

          htmlBody += "<br>\n";
          
          htmlBody += "LTL: ";

          htmlBody += "<br>\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 += "<br>\n";
          }
          
          htmlBody += "<hr>\n";
          htmlBody += "<br>\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:"):
Code: Select all
Client Connected!
Sending HTML page
Just some big text. This is very big text in front.<br>
LTQ: <br>
LTM: <br>
LTL: <br>
A0: 8<br>
A: <br>
A: <br>
A: <br>
A: <br>
A: <br>
<hr>
<br>
CT: </html>
Client disconnected

If I comment out in the code following line (the big text):
Code: Select all
 htmlBody += "Just some big text. This is very big text in front.";
Then, the resulting web page displays as it should (note "An: value"):
Code: Select all
Client Connected!
Sending HTML page
<br>
LTQ: <br>
LTM: <br>
LTL: <br>
A0: 7<br>
A1: 567<br>
A2: 470<br>
A3: 410<br>
A4: 348<br>
A5: 295<br>
<hr>
<br>
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.
By Valen
#186438
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.