SparkFun Forums 

Where electronics enthusiasts find answers.

All things pertaining to wireless and RF links
By GregM
#180884
I have been experimenting with the ESP-8266 (wrl-13252) WIFI module. Here is some information on it that may help others. A good source of information on the device is available
here: https://github.com/esp8266/esp8266-wiki

The SparkFun module is the ESP-8266-01 version 2 as far as I can tell. The github esp8266 wiki gives this pin information for the eight pins:

Pins to chip names
Pin Name Description
1 GND Ground
2 U0TXD UART0 Transmit
3 GPIO2 Has internal pull-up
4 CHIP_EN Chip Enable, active high, needs to connect to 3.3 for proper operation
5 GPIO0 Has internal pull-up
6 EXT_RSTB External reset signal, active low, has no pull-up?
7 U0RXD UART0 Receive, has internal pull-up
8 Vdd +3.3V power input

These are the common AT commands as given by multiple sources. In testing, I found it was best to use all capital letters for the commands. Sometimes, lower case would work and others, only capital letters worked.

1. AT-Attention
2. AT+RST-Soft reset
3. AT+GMR-Retrieve firmware version
4. AT+CWMODE-Operation mode selection
5. AT+CWJAP-Join network
6. AT+CWLAP-Available network listing
7. AT+CWQAP-Exit network
8. AT+ CWSAP-Setup network name, password, radio channel and security scheme
9. AT+ CWLIF-Listing connected stations
10. AT+ CIPSTATUS-Connection listing
11. AT+CIPSTART-Initiating connection
12. AT+CIPSEND-Sending data
13. AT+CIPCLOSE-Closing connection
14. AT+CIFSR-Displaying IP from access point
15. AT+CIPMUX-Single or multiple connection selection
16. AT+CIPSERVER-Socket server on/off
17. AT+CIPMODE-Serial port transparent or connecdtion based data output selection
18. AT+CIPSTO-Socket server automatic connection timeout setting
19. +IPD-Serial port connection based data output

At this time, I have used AT, AT+RST, AT+GMR, AT+CWMODE and AT+CWLAP commands. The AT+CWMODE is an important command, AT+CWMODE=1 sets the unit as a station(STA), AT+CWMODE=2 sets the unit as an access point(AP) and AT+CWMODE=3 sets the unit to operate in both modes (either STA or AP). Mode 3 seems the best to use.

The ESP-8266 is a WIFI device and can draw significant amounts of current (over 200 mA). For my testing, I used 3.3/5 volt breadboard power supply (prt-00114) to power the ESP-8266. I also used an inexpensive USB to TTL serial device. I also tried the SparkFun FTDI Basic Breakout 3.3, but it did not work. The funny thing is the USB to TTL serial device is a terrible device to program the standard Arduino boards, but, the SparkFun Basic works great with the Arduino boards.

Here are the five connections that I used for testing:
ESP-8266 Pin To Device
Vdd +3.3V output of the Breadboard Power supply
GND GND of Powersupply. Also the Gnd of the USB to TTL was tied to same GND buss
CHIP_EN +3.3V output of the Breadboard Power supply
U0TXD USB to TTL RX
U0RXD USB to TTL TX

I used the serial monitor tool of the Arduino IDE to send commands and get the ESP-8266 response. The baud rate was 9600 and a carriage return/new line sent with the text command.

The next step for me is to connect the ESP-8266 to an Ardunio Pro-Micro as serial repeater to work out serial communciations between the ESP-8266 and the board. I will also attempt to connect to my home WIFI network. I will post the results under this topic when I get some results.
By GregM
#180896
Thank you very much for the information, jremington! The Ardunio forum reference points to this web site: http://www.arduinesp.com It provides information on how to use the Arduino IDE to directly program the ESP-8266. I will have to try the process out.

I have found a good Arduino library for the ESP-8266 located here: https://github.com/sleemanj/ESP8266_Simple

Here is a good site with information on the AT commands: https://nurdspace.nl/ESP8266#AT_Commands
Using the information on this site, I have connected to my WIFI network using a USB to TTL converter and ADE IDE serial monitor tool.

I hope this helps someone.
By GregM
#180907
With ESP-8266 in mode=3, it is possible to telnet to it. One connects to the ESP-8266 WIFI point, ssid ESP_9F3321 for my unit. The ssid is tied to mac address of the unit. The telnet connection is to 192.168.4.1 on port 2000. It is possible to pass commands to an Ardunio controller via the serial connection. I have not tried, but, I have found the telnet port.

I looked at the direct programing of the ESP-8266 site, http://www.arduinesp.com . It is only for Window$ operating system. I run Linux(FatDog64). Therefore, I can not try the process out. Maybe someone with Window$ will in the future.
By GregM
#180915
Thanks for the information, jremington on the site with Linux version. I will take at look at it.

Here is the sequence of commands to connect to a WIFI network:
First one needs to be in STA mode
AT+CWMODE=3 (or 1)

Then:
AT+CWJAP="SSID","PASSWORD"

One can confirm the connection with AT+CWJAP?

To see the assign IP address from the Access Point use AT+CIFSR

Unless, one changes the mode, the device will remember the WIFI network SSID and PASSWORD. At the next power up, the device will attempt to connect to WIFI network.
By GregM
#180922
I did get the ESPlorer program from http://esp8266.ru/esplorer/ It is a Java program, which gives it the ability to run under multiple operating system. It does work and one can use with Linux. There are two issues. The first is the script ESPlorer.bat, which runs the main java program, needs the permission set to allow it to run. The second issue is the program window can not be resize to show all the controls. There is a file, AbsoluteLayout.jar, which probably controls the window size. However, it does not appear to be easily modified.
By GregM
#180945
The reset function pin is a bit strange. Just touching the bare lead, will cause a reset of the device. I searched the web for information on it. The best way to reset the was from the Olimex site. On their product, they use a 220 (or 200) ohm resistor in series with a push button (normally open) switch to ground then connected to the reset line 0f the ESP-8266. I have not been able to get the ESP-8266 reset using the reset line of the arduino processor.

reset pin ---220 ohm resistor --- normally open switch --- ground

I have not been able to tell If there is an internal pull up to the reset pin of the device. A voltage meter reads a low millivolt value. The sampling of the DVM sometimes causes the device to reset.

I going with the resistor and switch from now on. I hope this is a help to people.
By GregM
#180975
Here is the Ardunio code that I used to teach myself how to communicate between the Ardunio Pro Mini and the ESP8266. The code process the command input from the serial monitor tool. It makes sure the command is all upper case letters, which ESP8266 prefers.
Code: Select all
/*
  This sketch was developed for the Mini Pro Ardunio device.
  This a beerware license for this software.  There is no warranty that 
  this even works.    If does for you then great.  Nor is the author 
  liable for any claim, damages   or other liability, whether in an 
  action of contract, tort, or otherwise, arising from, out of in 
  connection with this software or the use or dealings in 
  this software.   I can not control your use of this software, 
  therefore I can not be   liable for your problems.  The proceeding 
  should keep the lawyers happy.  
  
  If you use it for your purposes with success
  and we meet,then please buy me a beer.  G. Majewski 4 April 2015
  
  Need to set the serial monitor tool of the IDE to 57600 baud with 
  "no line ending"
  
  serial.println() sends a carriage return and new line at the end to 
  data transfer
*/

#include <Arduino.h>
#include <SoftwareSerial.h>

/* Create the serial link for the ESP8266 device on pins 
   8 for Arduino RX (TX on ESP connects to this pin) 
   9 for Arduino TX (RX on ESP connects to this pin)
   The I/0 for the ESP8622 is 3.3 volts ONLY! Make sure the
   connection is at the 3.3 volts for logic high
*/
  
SoftwareSerial wifi(8,9);  //pins for communications to ESP8266
//String cmdEnd = "\r\n";  //all commands to ESP8266 end with carriage return \r and new line \n
 
void setup() {
  // put your setup code here, to run once:
  Serial.begin(57600); // Reduce this if serial problems result and for debug
  Serial.println("ESP8266 Test Command Sketch");
  wifi.begin(9600);  // starts wifi serial connect at baudrate
  wifi.setTimeout(5000);  //ensures enough time to get ESP8266 output
}

void loop() 
 { 
  // need to set up variables for the serial data transfers to/from ESP8266
  String outStr=""; // reset outStr to be empty for next command to ESP8266
  char serialIn;
  char wifiIn;  //for output of the ESP8266
  int CharCount = 0;

  // need to get serial input to create command
  while (Serial.available() > 0)
   {
   // read the incoming byte as char:
   serialIn = Serial.read();
   outStr = outStr + serialIn; // create command
   } 
   if (outStr.length() > 0)  //if non zero then process command
   {
    Serial.println();  //empty line to space between commands and responses
    outStr.toUpperCase(); // ensure all upper case
    Serial.println("Command " + outStr);
    Serial.println("with a response of");
    wifi.println(outStr);
   }
   
  while (wifi.available() > 0)
   {
    wifiIn = Serial1.read(); 
   Serial.write(wifiIn);
   }
 } 
I have also tried the Arduino library for the ESP-8266 located here: https://github.com/sleemanj/ESP8266_Simple
Most of the examples do work. But, the server example does not work properly. The browser reports it is an empty page without any data. Any suggestions for a server that may work? Thanks in advance for any help.
Last edited by GregM on Tue Apr 07, 2015 8:10 pm, edited 1 time in total.
By GregM
#180976
Here is the modified setup code to use a Pro Micro instead of Pro Mini for the command test sketch.
Code: Select all
/* Create the serial link for the ESP8266 device on pins 
   serial1 pin 2 for mirco RXI (TX on ESP connects to this pin) 
   serial1 pin 1 for micro TXO (RX on ESP connects to this pin)
   The I/0 for the ESP8622 is 3.3 volts ONLY! Make sure the
   connection is at the 3.3 volts for logic high
*/
 
void setup() {
  // put your setup code here, to run once:
  Serial.begin(57600); // Reduce this if serial problems result and for debug
  while (!Serial) {
         ; // wait for serial port to connect. Needed for atmega32U4 processor
  }
  Serial.println("ESP8266 Test Command Sketch for Pro Micro");
  Serial1.begin(9600);  // starts wifi serial connect at baudrate
  Serial1.setTimeout(5000);  //ensures enough time to get ESP8266 output
}
This does work. I have noticed the Pro Micro sketches are bigger in size than the same sketch for a Pro Mini.
I do not know the reason.
By GregM
#181039
I found an example web server that works. However, it very slow. This maybe the result of serial communication rate(9600) and the time required by ESP8266 to process a command. The combination of the Pro Micro and ESP8266 is slower that Ardunio Yun for web service.

There is an undocumented ESP8266 command to report (AT+CIOBAUD?) and set (AT+CIOBAUD=<baudrate>) a new rate. I have tried the report command and it works. I have not tried the set command. I have found mention of this command on a few web sites. However, I have not found the command in the various lists of commands.

Additionally, there is special firmware available called NodeMCU. It may be faster and with a version of the ESP8266 with access to all its pins, then the Arduino process may not be required. I have no real knowledge of NodeMCU.

Here is the code, I modified for use with Pro Micro:
Code: Select all
/* Basic Arduino & ESP8266 webserver from
   http://www.martyncurrey.com/arduino-esp8266-web-server/
   uses AltSoftSerial download from https://www.pjrc.com/teensy/td_libs_AltSoftSerial.html
   this can be replaced with the normal software serial
   modified by G.Majewski, 8 April 2015 for use with Pro Micro
*/
 
//#include <AltSoftSerial.h>
// Arduino pin 8 for RX
// Arduino Pin 9 for TX
//AltSoftSerial espSerial;
// sub Serial1 for espSerial with Pro Micro second UART (hardware) pin 0,1
 
const bool printReply = true;
const char line[] = "-----\n\r";
int loopCount=0;
 
char html[50];
char command[20];
char reply[500]; // 500 seems to be the size needed
 
char ipAddress [20];
char name[30];
int lenHtml = 0;
char temp[5];
 
void setup()
{
      Serial.begin(9600);
      while (!Serial) {
      ; // wait for serial port to connect. Needed for ATmeg32u4 boards only
      }
      Serial.println("Start\r\n\r\n");
      Serial1.begin(9600); // your ESP8266 module's baud rate might be different
 
      // reset the ESP8266
      Serial.println("reset the module"); 
      Serial1.print("AT+RST\r\n");
      getReply( 2000 );
 
      // configure as a station
      Serial.println("Change to station mode"); 
      Serial1.print("AT+CWMODE=1\r\n");
      getReply( 1500 );
 
      // connect to the network. Uses DHCP. ip will be assigned by the router.
      Serial.println("Connect to a network ");
 
     // Enter the SSID and password for your own network
      Serial1.print("AT+CWJAP=\"wireless1_ext\",\"PI~355/113\"\r\n");
      getReply( 6000 );
 
      // get ip address
      Serial.println("Get the ip address assigned ny the router"); 
      Serial1.print("AT+CIFSR\r\n");
      getReply( 1000 );
 
      // parse ip address.
      int len = strlen( reply ); 
      bool done=false;
      bool error = false;
      int pos = 0;
      while (!done)
      {
           if ( reply[pos] == 10) { done = true;} 
           pos++;
           if (pos > len) { done = true;  error = true;}
      }
 
      if (!error)
      {
            int buffpos = 0;
            done = false;
            while (!done)
            {
               if ( reply[pos] == 13 ) { done = true; }
               else { ipAddress[buffpos] = reply[pos];    buffpos++; pos++;   }
            }
            ipAddress[buffpos] = 0;
      }
      else { strcpy(ipAddress,"ERROR"); }
 
      // configure for multiple connections
      Serial.println("Set for multiple connections"); 
      Serial1.print("AT+CIPMUX=1\r\n");
      getReply( 1500 );
 
      // start server on port 8
      Serial.println("Start the server"); 
      Serial1.print("AT+CIPSERVER=1,80\r\n");
      getReply( 1500 );
 
      Serial.println("");

      Serial.println("Waiting for page request");
      Serial.print("Connect to "); Serial.println(ipAddress);
      Serial.println("");
}

void loop()
{
      if(Serial1.available()) // check if the ESO8266 is sending data
      {
          // this is the +IPD reply - it is quite long. 
          // normally you would not need to copy the whole message in to a variable you can copy up to "HOST" only
          // or you can just search the data character by character as you read the serial port.
          getReply( 2000 );      
 
          bool foundIPD = false;
          for (int i=0; i<strlen(reply); i++)
          {
               if (  (reply[i]=='I') && (reply[i+1]=='P') && (reply[i+2]=='D')   ) { foundIPD = true;    }
          }
 
          if ( foundIPD  )  
          {
              loopCount++;
              // Serial.print( "Have a request.  Loop = ");  Serial.println(loopCount); Serial.println(""); 
 
              // check to see if we have a name - look for name=
              bool haveName = false;
              int nameStartPos = 0;
              for (int i=0; i<strlen(reply); i++)
              {
                   if (!haveName) // just get the first occurrence of name
                   {
                         if (  (reply[i]=='n') && (reply[i+1]=='a') && (reply[i+2]=='m') && (reply[i+3]=='e')  && (reply[i+4]=='=') ) 
                         { 
                             haveName = true;
                             nameStartPos = i+5;
                         }
                   }     
              }
 
              // get the name - copy everything from nameStartPos to the first space character
              if (haveName)
              {
                    int tempPos = 0;
                    bool finishedCopying = false;
                    for (int i=nameStartPos; i<strlen(reply); i++)
                    {
                         if ( (reply[i]==' ') && !finishedCopying )  { finishedCopying = true;   } 
                         if ( !finishedCopying )                     { name[tempPos] = reply[i];   tempPos++; }
                    }              
                    name[tempPos] = 0;
              }
 
              if (haveName) { Serial.print( "name = ");  Serial.println(name); Serial.println(""); }
              else          { Serial.println( "no name entered");   Serial.println("");           }

              // start sending the HTML
              strcpy(html,"<html><head></head><body>");
              strcpy(command,"AT+CIPSEND=0,25\r\n");
              Serial1.print(command);
              getReply( 2000 );          
              Serial1.print(html);
              getReply( 2000 );                      
 
              strcpy(html,"<h1>ESP8266 Webserver</h1>");
              strcpy(command,"AT+CIPSEND=0,26\r\n");
              Serial1.print(command);
              getReply( 2000 );         
              Serial1.print(html);
              getReply( 2000 );          
 
              strcpy(html,"<p>Served by Arduino and ESP8266</p>");
              strcpy(command,"AT+CIPSEND=0,36\r\n");
              Serial1.print(command);
              getReply( 2000 );          
              Serial1.print(html);
              getReply( 2000 );           
 
              strcpy(html,"<p>Request number ");
              itoa( loopCount, temp, 10);
              strcat(html,temp);
              strcat(html,"</p>");
 
              // need the length of html
              int lenHtml = strlen( html );
              strcpy(command,"AT+CIPSEND=0,");
              itoa( lenHtml, temp, 10);
              strcat(command, temp);
              strcat(command, "\r\n");
              Serial1.print(command);
              getReply( 2000 );          
              Serial1.print(html);
              getReply( 2000 );                       

             if (haveName)
             {
                  // write name
                  strcpy(html,"<p>Your name is "); strcat(html, name ); strcat(html,"</p>");
 
                  // need the length of html for the cipsend command
                  lenHtml = strlen( html );
                  strcpy(command,"AT+CIPSEND=0,"); itoa( lenHtml, temp, 10); strcat(command, temp); strcat(command, "\r\n");
                  Serial1.print(command);
                  getReply( 2000 );          
                  Serial1.print(html);
                  getReply( 2000 );                           
             }
 
              strcpy(html,"<form action=\""); strcat(html, ipAddress); strcat(html, "\" method=\"GET\">"); strcat(command, "\r\n");
              lenHtml = strlen( html );
              itoa( lenHtml, temp, 10);
              strcpy(command,"AT+CIPSEND=0,"); 
              itoa( lenHtml, temp, 10); 
              strcat(command, temp);  
              strcat(command, "\r\n");
 
              Serial1.print(command);
              getReply( 2000 );          
              Serial1.print(html);
              getReply( 2000 );          
 
              strcpy(html,"Name:<br><input type=\"text\" name=\"name\">");
              strcpy(command,"AT+CIPSEND=0,40\r\n");
              Serial1.print(command);
              getReply( 2000 );         
              Serial1.print(html);
              getReply( 2000 );         
 
              strcpy(html,"<input type=\"submit\" value=\"Submit\"></form>");
              strcpy(command,"AT+CIPSEND=0,43\r\n");
              Serial1.print(command);
              getReply( 2000 );       
              Serial1.print(html);
              getReply( 2000 );       
 
              strcpy(html,"</body></html>");
              strcpy(command,"AT+CIPSEND=0,14\r\n");
              Serial1.print(command);
              getReply( 2000 ); 
              Serial1.print(html);
              getReply( 2000 ); 
 
              // close the connection
              Serial1.print( "AT+CIPCLOSE=0\r\n" );
              getReply( 1500 );            
 
              Serial.println("last getReply 1 ");
              getReply( 1500 );  
 
              Serial.println("last getReply 2 ");
              getReply( 1500 ); 
 
          } // if(espSerial.find("+IPD"))
      } //if(espSerial.available())
        delay (100);
 
      // drop to here and wait for next request.
}
 
void getReply(int wait)
{
    // had to change espSerial to Serial1 due espSerial not being in scope
    int tempPos = 0;
    long int time = millis();
    while( (time + wait) > millis())
    {
        while(Serial1.available())
        {
            char c = Serial1.read(); 
            if (tempPos < 500) { reply[tempPos] = c; tempPos++;   }
        }
        reply[tempPos] = 0;
    } 
 
    if (printReply) { Serial.println(reply);  Serial.println(line);     }
}
I think I have said enough on this topic. This will be the last post, unless someone has a question. I hope this is a help.
User avatar
By Ross Robotics
#181044
Personally, I am glad you decided to write a thread like this. I am sure it will help someone in the future. Haven't quite got into WiFi yet, but when I do, I will have bookmarked this thread!
By GregM
#181301
Thank you, codlink for the comment. I thought I was finished with this thread, but, I learn something about the AT+CIOBAUD command. It is only available with a firmware that is 0.9.2 or newer. At the boot, (pull the reset pin low), the boot message show the version.

I also got the ESP8266 ESP-12 development board with the nodemcu firmware. It is very interesting. It eliminates the need for the Ardunio processor. It works directly with the ESPlorer software. One has access to all the GPIO pins for interfacing to other devices.

The other issue with both of these devices is they are not FCC certified. There is no problem with experimenting with them and a "one off" board for your own use. But, if they are part of a commercial product, then FCC certification is required and the process is not inexpensive.

I hope this helps
By GregM
#181686
I have been doing some work with ESP-8266 and found a very good web server for it. I have tried many example ESP8266 web servers. Many are very slow and a couple were extremely slow. This one is reasonable. The code also uses no libraries, which allows one to see how the ESP8266 commands are used for a web server. I modified the original code to add the reporting of an analog measured value. The code both controls a LED and reports the current used by the LED. This code provides the basic operations of the ESP8266 combined with an Arduino processor. The code has many comments to help me in the future.
Code: Select all
/*
This sketch was based on the code at this site:
  https://gist.github.com/prasertsakd/5c5deb80e37344250cc1
  
  The original sketch was for the Leonardo processor.

  This version was developed for the Mini Pro, Uno and Nano Ardunio devices.
  
  This software is covered by a beerware license.  There is no warranty that this even works
  If does for you then great.  Nor is the author liable for any claim, damages
  or other liability, whether in an action of contract, tort, or otherwise,
  arising from, out of in connection with this software or the use or dealings in 
  this software.   I can not control your use of this software therefore I can not be
  liable for your problems.  The proceeding words should keep the lawyers happy.  
  If you use it for your purposes with success and we meet,then please 
  buy me a beer.  G. Majewski 1 May 2015
  
Need to set the serial monitor tool of the IDE to correct baud rate 
with "no line ending.  This sketch requires the use of a serial monitor to run properly.
  
Software Serial connections for Uno/Nano ATmega328 processor
Pins 7 and 8 are not used for all special functions like I2C, SPI, PWM or
interrupts.  They would be the best to use and still have additional 
functionality.

Create the serial link for the ESP8266 device on pins 
   7 for Arduino RX (TX on ESP connects to this pin) 
   8 for Arduino TX (RX on ESP connects to this pin)
The I/0 for the ESP8622 is 3.3 volts ONLY! Make sure the connection is 
at the 3.3 volts for logic high

This works. It controls and reports the state of the ledPin

To use, after connecting to a serial monitor, open a web browser and
go to "reported IP/led" (e.g. 192.168.100.103/led)
*/

#include <SoftwareSerial.h>
SoftwareSerial espSerial(7,8);  //pins for serial communications to ESP8266

const int ledPin = 9; // the number of the LED pin, pin 9 only digital or PWM
/* connections for LED is
   pin 9 --> LED anode  LED cathode --> 100 ohm --> Gnd
                                     |
                                     ^
                                     pin A0 to 100 ohm
*/

int ledState = HIGH;   // ledState used to set the LED, changes with post

#define BUFFER_SIZE 128
#define pTime 200
char buffer[BUFFER_SIZE];

void setup() { 
  pinMode(ledPin, OUTPUT);  
      
  Serial.begin(9600); // Serial monitor
  espSerial.begin(9600); // ESP8266 default rate

  Serial.println(F("ESP8266 demo."));

  clearSerialBuffer();
  
  //connect to router, need to do this only once, device saves data
  //connectWiFi("yourSSID", "yourPassword");
  
  //test if the module is ready
  //Serial.print("AT : ");
  //Serial.println( GetResponse("AT",100) );
    
  //Change to mode 1
  //Serial.print("AT+CWMODE=1 : ");
  //Serial.println( GetResponse("AT+CWMODE=1",10) );
        
  //set the multiple connection mode
  Serial.print(F("AT+CIPMUX=1 : "));
  Serial.println( GetResponse("AT+CIPMUX=1",5000) );
  
  //set the server of port 80 check "no change" or "OK"
  Serial.print(F("AT+CIPSERVER=1,80 : "));
  Serial.println( GetResponse("AT+CIPSERVER=1,80", 5000) );
 
  //set time out
  Serial.print("AT+CIPSTO=15 : ");
  Serial.println( GetResponse("AT+CIPSTO=15",10) );
  
   //print the ip addr
  Serial.print(F("ip address : "));
  Serial.println( GetResponse("AT+CIFSR", 5000) ); //need wait longer to get IP addr
  delay(200);

   
  Serial.println();
  Serial.println(F("Start Webserver"));

  digitalWrite(ledPin,ledState); //start with LED ON, pin High State 
}

void loop() {
  int ch_id, packet_len, rawCurrent;
  char *pb;  
  espSerial.readBytesUntil('\n', buffer, BUFFER_SIZE);
  
  if(strncmp(buffer, "+IPD,", 5)==0) {
    // request: +IPD,ch,len:data
    sscanf(buffer+5, "%d,%d", &ch_id, &packet_len);  
    if (packet_len > 0) {
      // read serial until packet_len character received
      // start from :
      pb = buffer+5;
      while(*pb!=':') pb++;
      pb++;
      if (strncmp(pb, "GET /led", 8) == 0) {
        Serial.print(millis()); //time value
        Serial.print(" : ");
        Serial.println(buffer);
        Serial.print( "get led from ch :" );
        Serial.println(ch_id); //ch_id is which instance of the web server connected
 
        delay(100);
        clearSerialBuffer();
        
        if (ledState == LOW) { ledState = HIGH;}
        else { ledState = LOW;}
        digitalWrite(ledPin, ledState);
        rawCurrent = analogRead(0);          
        homepage(ch_id, rawCurrent);       
       }
       
       else if (strncmp(pb, "GET / ", 6) == 0) {
        Serial.print(millis());
        Serial.print(" : ");
        Serial.println(buffer);
        Serial.print( "get Status from ch:" );
        Serial.println(ch_id);
        delay(100);
        clearSerialBuffer();
        homepage(ch_id, 348);
      }
    }
  }
  clearBuffer();
}

void homepage(int ch_id, int current) {
  String Header;  
  Header =  "HTTP/1.1 200 OK\r\n";
  Header += "Content-Type: text/html\r\n";
  Header += "Connection: close\r\n";  
  //Header += "Refresh: 5\r\n";
  
  String curVal;
  float tmp = current / 20.46; //milliamp current through 100 ohm
  curVal = String(tmp);
  
  String Content;
  Content = "<h2 ALIGN=center><br>Led is ";
  Content += String(ledState);
  Content += "</h2>";
  Content += "<h3 align=center>Led Current is ";
  Content += curVal;
  Content += "</h3>";
  
  Header += "Content-Length: ";
  Header += (int)(Content.length());
  Header += "\r\n\r\n";
   
  espSerial.print("AT+CIPSEND=");
  espSerial.print(ch_id);
  espSerial.print(",");
  espSerial.println(Header.length()+Content.length());
  delay(10);
  
  // for debug buffer serial error
  //while (espSerial.available() >0 )  {
  //  char c = espSerial.read();
  //  Serial.write(c);
  //  if (c == '>') {
  //      espSerial.print(Header);
  //      espSerial.print(Content);
  //  }
  //}
  
  if (espSerial.find(">")) {
      espSerial.print(Header);
      espSerial.print(Content);
      delay(10);
   }
 
  espSerial.print("AT+CIPCLOSE=");
  espSerial.println(ch_id); //this closes the connection to save resources

}

// Get the data from the WiFi module and send it to the debug serial port
String GetResponse(String AT_Command, int wait){
  String tmpData = "";  //ensure it is empty
  espSerial.println(AT_Command);
  delay(wait);  //good value for wait = 500
  while (espSerial.available() >0 )  {
    char c = espSerial.read();
    tmpData += c;  // this is better for adding character
   }
   return tmpData;
}

void clearSerialBuffer(void) {
       while ( espSerial.available() > 0 ) {
         espSerial.read();
       }
}

void clearBuffer(void) {
       for (int i =0;i<BUFFER_SIZE;i++ ) {
         buffer[i]=0;
       }
}
         
boolean connectWiFi(String NetworkSSID,String NetworkPASS) {
  String cmd = "AT+CWJAP=\"";
  cmd += NetworkSSID;
  cmd += "\",\"";
  cmd += NetworkPASS;
  cmd += "\"";  
  Serial.println(cmd); 
  Serial.println(GetResponse(cmd,pTime));
}
The above code uses about 41 percent of the NANO resources.

I have also tried using ModeMCU version. It requires the use of LUA programing language to make effective use of it. The learning curve of LUA for me, did not make it worthwhile.

I hope the above helps.