ESP8266 fast wifi connect/post

400ms from power-on to UDP post, 500~700ms for a GET. I was pretty surprised it could be so fast. Wake up from deep-sleep is quicker! (see comment below).

My GET target was to another ESP8266 running a simple server. Browser tools say it takes about 144ms to do the complete set of transactions to get the page data so not a huge amount of overhead. Its just an OK and a count.

When the ESP goes into deep-sleep, some of the WiFi connection details are retained by the chip so on wake-up, the retained info is used to enable a fast connection (if your sketch is configured to allow its use). If the chip is power-cycled instead of put in deep-sleep none of this connection info is available so it adds quite a bit of time to the duration required to connect.

I have several ESP8266 modules on my network doing varied tasks. Currently my sensor boards have been RFM12/RFM69 based and they work just fine. They all feed back to a collector (an ESP8266 board with a plug-in RFM module) which forwards the collected data to be logged.

There is lots of info on the web about people using ESP’s to directly run the sensors and post data and how they have achieved as low-connect times as possible. This is my attempt at the same.

I don’t think I’ll be swapping over to ESP’s for general sensor use. I like my ATtiny1634 + RFM69CW which can run from a coin cell for a good 6-8 months, sending temperature data every 3-min. But now I know that the ESP connect times can be really good, it opens new options for the future. The Arduino test-sketch is below for anyone who wants to try it. Or download it.

/*
Fast WiFi connect for an ESP8266.

The first time you program it, do a FULL-ERASE to clear out old info.
The connect speed will be long for the first time. reboots or power-cycles
after the first will be LOTS quicker.

The figures you will get are very dependant on the router you are connecting to.

The GET target in this case is a second ESP running a simple web-server
It's on the same home network and is to mimic the scenario of
a wifi sensor (this device) posting its data to a collector

WiFi connected by 240ms (using static IP)
GET is finished by 400-700ms
consistantly Lowest times are a warm-boot, ie reset button.
power-on is a bit higher (500ms-ish and above, to GET done)

For MAX speed, if its a UDP send, it's all over by 250mS (warm boot)
Power-on to send-complete takes a bit longer, 420-ish ms

I use a UDP listener on my android phone to see the test message

tested on a lolin-mini, nodeMCU-V1, ESP-01
Built with Arduino ESP8266 addon V2.6.3
Use at your own risk, no guarantees it will work for you!
*/

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h>
#include <WiFiUdp.h>

// ---------------------------------------------------------

// wifi credentials. Change the ** stuff to suit your network

#define STASSID "YOURSSID"					// ** your SSID
#define STAPSK  "YOURPASSWORD"					// ** your password

const char* ssid = STASSID;
const char* password = STAPSK;

// change to suit your local network. Static IP etc for the ESP
#define IPA  IPAddress(11, 0, 0, 40)			// **  IP address
#define GATE IPAddress(11, 0, 0, 138)			// **  gateway
#define MASK IPAddress(255, 255, 255, 0)		// **  netmask

// the MAC address of your wifi router
uint8_t home_mac[6] = { 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };		// **
int channel = 2;		// the wifi channel to be used							// **

// address of a UDP listener on the same network
char UDPtarget[] = { "11.0.0.11" };											// **
const uint16_t udpPort = 63001;													// ** UDP port number 

// this is for the GET test. I used a 2nd ESP running a simple web-server
// the http:// is REQUIRED
String localServer = "http://11.0.0.233/";							// ** 

// ---------------------------------------------------------

String response = "                    ";			// to hold rootpage response
uint32_t counter = 0;													// rootpage counter

#define INSIZE 512	// fixed max size for server response
String input = "";	// in setup, this string has INSIZE bytes reserved

// these are for the three millis() timestamps
unsigned long t1;		// start of sketch
unsigned long t2;		// after wifi connected
unsigned long t3;		// after GET or UDP send, or both

// reboot webpage. You can have any page load after the delay
const String bootreload = "<!doctype html><html lang = 'en'><head><meta charset = 'utf-8'>\
<title>My Redirect Page</title></head><body><div>\
Rebooting,  reloading in 5 seconds...\
</div><script type = 'text/javascript'>\
setTimeout(function(){window.location.replace('/');}, 5000);\
</script></body></html>";
// the above (after 5 sec (5000) ) redirects to the place within [window.location.replace('/')]
// '/' is the rootpage at the current location but can be a fully qualified internet address.
// so an initial web page can be displayed then after the delay, a different one comes up.

const String UDPtestMessage = "Hi, this is a test message by UDP\r\n";

int aNumber = 0;
int temp;

ESP8266WebServer server(80);
HTTPClient http;
WiFiUDP udp;

// ===========================================================================

// webserver handler
void handleRoot() {
	response = "OK, ";
	response += (String)++aNumber;
	server.send(200, "text/plain", response);
	Serial.print("Rootpage accessed, content sent: ");
	Serial.println(response);
}

// webserver handler
void handleReboot() {
	server.send(200, "text/html", bootreload);
	Serial.println("Reboot, webpage auto-reload in 5...");
	delay(500);			// give things time to happen
	ESP.restart();
}

// webserver handler
void handleNotFound() {
	server.send(404, "text/plain", "404: File Not Found");
}

// send a html string by UDP packet
void sendUDPpacket()
{
	Serial.print("sending UDP packet -> ");
	udp.beginPacket(UDPtarget, udpPort);			// set up the IP and port
	udp.print(UDPtestMessage);					// send it
	udp.endPacket();
	Serial.println(UDPtestMessage);			// and copy string to serial

}

// ===================================================================================
// note that there is no WiFi.begin() in the setup.
// It IS accessed in a function the 1st time the sketch is run
// so that the details can be stored, but any restarts after that
// are connected by the saved credentials and it happens MUCH faster.

void setup(void) {
enableWiFiAtBootTime();  // required for release >= 3
	t1 = millis();							// first timestamp

// a significant part of the speed gain is by using a static IP config
	WiFi.config(IPA, GATE, MASK);

	input.reserve(INSIZE);			// allocate fixed space for remote server response

	Serial.begin(115200);				// start up serial port

// so even though no WiFi.connect() so far, check and see if we are connecting.
// The 1st time sketch runs, this will time-out and THEN it accesses WiFi.connect().
// After the first time (and a successful connect), next time it connects very fast
	while (WiFi.status() != WL_CONNECTED) {
		delay(5);			// use small delays, NOT 500ms
		if (++counter > 1000) break;     // 5 sec timeout
	}
	//if timed-out, connect the slow-way
	if (counter > 1000) launchSlowConnect();

	t2 = millis();			// second time-stamp. WiFi is now connected


// some web pages for the server
	server.onNotFound(handleNotFound);
	server.on("/", handleRoot);
	server.on("/reboot", handleReboot);

	server.begin();
	Serial.println("\nHTTP server started");

	Serial.print("Connected to ");
	Serial.println(ssid);
	Serial.print("IP address: ");
	Serial.println(WiFi.localIP());

		// ----------------------------------------------
		// comment out ONE of the following to check timings

		//sendUDPpacket();							// UDP send (this is fast)
	TestLink();										// do a GET (slower)

		// when both active, elapsed time (using reset button) is about 570ms on my router
// --------------------------------------------------

	t3 = millis();			// third timestamp, network actions completed.

// delay added here as sometimes it all happens before the USB 
// serial port is back (after a power-cycle)
	delay(2000);
	Serial.println();
	Serial.println("snapshots of millis() counter..");
	Serial.print("Sketch begins: ");
	Serial.println(t1);			// start of sketch
	Serial.print("WiFi connected: ");
	Serial.println(t2);			// wifi connected
	Serial.print("Network transaction completed: ");
	Serial.println(t3);			// network actions done
//		Serial.println(input);		// received by GET

}
// ===================================================================================


// ------------------------------------------------------------------------------------------
void loop(void) {
	server.handleClient();			// local web-server
}
// ------------------------------------------------------------------------------------------



// ------------------------------------------------------------------------------------------
// this is accessed when the initial run fails to connect because no (or old) credentials
void launchSlowConnect() {
	Serial.println("No (or wrong) saved WiFi credentials. Doing a fresh connect.");
	counter = 0;
		// persistent and autoconnect should be true by default, but lets make sure.
	if (!WiFi.getAutoConnect()) WiFi.setAutoConnect(true);	// autoconnect from saved credentials
	if (!WiFi.getPersistent()) WiFi.persistent(true);			// save the wifi credentials to flash


// Note the two forms of WiFi.begin() below. If the first version is used
// then no wifi-scan required as the RF channel and the AP mac-address are provided.
// so next boot, all this info is saved for a fast connect.
// If the second version is used, a scan is required and for me, adds about 2-seconds
// to my connect time. (on a cold-boot, ie power-cycle)

	WiFi.begin(ssid, password, channel, home_mac, true);
//	WiFi.begin(ssid, password);


		// now wait for good connection, or reset
	while (WiFi.status() != WL_CONNECTED) {
		delay(500);
		Serial.print(".");
		if (++counter > 20) {				// allow up to 10-sec to connect to wifi
				Serial.println("wifi timed-out. Rebooting..");
				delay(10);	// so the serial message has time to get sent
				ESP.restart();
		}
	}
	Serial.println("WiFi connected and credentials saved");
}
// ------------------------------------------------------------------------------------------


// this does a GET to a local server. I use another ESP8266 running a basic server.

int TestLink() {

	int z;

	// only go thru if wifi connected
	if ((WiFi.status() == WL_CONNECTED)) {

		WiFiClient client;
		http.begin(client, localServer);			// NEEDS fully qualified addr (http://...etc etc)

		temp = http.GET();
		if (temp > 0) {
			//Serial.printf("[HTTP] GET... code: %d\n", temp);
			// file found at server
			if (temp == HTTP_CODE_OK) {		// needs a 200 to continue..
				z = http.getSize();			// how big is the payload?
//				Serial.print("Payload size: ");
//				Serial.println(z);				// show it
				if (z < INSIZE) {				// payload must fit in the available space.
					input = http.getString();	// read it in
//					Serial.println(input);		// and show the payload
				}
				else Serial.println("payload too big!");	// error if it wont fit
			}
		}
		else {  // show the connect error
			Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(temp).c_str());
		}
		http.end();	// close it
	}
	return temp;
}


2 thoughts on “ESP8266 fast wifi connect/post

  1. Tested with Deep-sleep. Terminal o/p as below.
    The times are very consistent, only a few ms difference each time.
    1st o/p is from UDP posting. 2nd is a GET.

    snapshots of millis() counter..
    Sketch begins: 63
    WiFi connected: 213
    Network transaction completed: 215
    deep sleep for 20 seconds

    snapshots of millis() counter..
    Sketch begins: 63
    WiFi connected: 216
    Network transaction completed: 493
    deep sleep for 20 seconds

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.