{"id":72,"date":"2020-01-20T17:28:34","date_gmt":"2020-01-20T09:28:34","guid":{"rendered":"https:\/\/pokewithastick.net\/?page_id=72"},"modified":"2021-09-21T03:44:18","modified_gmt":"2021-09-20T19:44:18","slug":"esp8266-fast-wifi-connect-post","status":"publish","type":"page","link":"https:\/\/pokewithastick.net\/?page_id=72","title":{"rendered":"ESP8266 fast wifi connect\/post"},"content":{"rendered":"\n<p>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).<\/p>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>There is lots of info on the web about people using ESP&#8217;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. <\/p>\n\n\n\n<p>I don&#8217;t think I&#8217;ll be swapping over to ESP&#8217;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 <a href=\"https:\/\/pokewithastick.net\/wp-content\/uploads\/2020\/01\/ESP_FastConnect.zip\">download<\/a> it.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n\/*\nFast WiFi connect for an ESP8266.\n\nThe first time you program it, do a FULL-ERASE to clear out old info.\nThe connect speed will be long for the first time. reboots or power-cycles\nafter the first will be LOTS quicker.\n\nThe figures you will get are very dependant on the router you are connecting to.\n\nThe GET target in this case is a second ESP running a simple web-server\nIt&#039;s on the same home network and is to mimic the scenario of\na wifi sensor (this device) posting its data to a collector\n\nWiFi connected by 240ms (using static IP)\nGET is finished by 400-700ms\nconsistantly Lowest times are a warm-boot, ie reset button.\npower-on is a bit higher (500ms-ish and above, to GET done)\n\nFor MAX speed, if its a UDP send, it&#039;s all over by 250mS (warm boot)\nPower-on to send-complete takes a bit longer, 420-ish ms\n\nI use a UDP listener on my android phone to see the test message\n\ntested on a lolin-mini, nodeMCU-V1, ESP-01\nBuilt with Arduino ESP8266 addon V2.6.3\nUse at your own risk, no guarantees it will work for you!\n*\/\n\n#include &lt;ESP8266WiFi.h&gt;\n#include &lt;WiFiClient.h&gt;\n#include &lt;ESP8266WebServer.h&gt;\n#include &lt;ESP8266HTTPClient.h&gt;\n#include &lt;WiFiUdp.h&gt;\n\n\/\/ ---------------------------------------------------------\n\n\/\/ wifi credentials. Change the ** stuff to suit your network\n\n#define STASSID &quot;YOURSSID&quot;\t\t\t\t\t\/\/ ** your SSID\n#define STAPSK  &quot;YOURPASSWORD&quot;\t\t\t\t\t\/\/ ** your password\n\nconst char* ssid = STASSID;\nconst char* password = STAPSK;\n\n\/\/ change to suit your local network. Static IP etc for the ESP\n#define IPA  IPAddress(11, 0, 0, 40)\t\t\t\/\/ **  IP address\n#define GATE IPAddress(11, 0, 0, 138)\t\t\t\/\/ **  gateway\n#define MASK IPAddress(255, 255, 255, 0)\t\t\/\/ **  netmask\n\n\/\/ the MAC address of your wifi router\nuint8_t home_mac&#x5B;6] = { 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };\t\t\/\/ **\nint channel = 2;\t\t\/\/ the wifi channel to be used\t\t\t\t\t\t\t\/\/ **\n\n\/\/ address of a UDP listener on the same network\nchar UDPtarget&#x5B;] = { &quot;11.0.0.11&quot; };\t\t\t\t\t\t\t\t\t\t\t\/\/ **\nconst uint16_t udpPort = 63001;\t\t\t\t\t\t\t\t\t\t\t\t\t\/\/ ** UDP port number \n\n\/\/ this is for the GET test. I used a 2nd ESP running a simple web-server\n\/\/ the http:\/\/ is REQUIRED\nString localServer = &quot;http:\/\/11.0.0.233\/&quot;;\t\t\t\t\t\t\t\/\/ ** \n\n\/\/ ---------------------------------------------------------\n\nString response = &quot;                    &quot;;\t\t\t\/\/ to hold rootpage response\nuint32_t counter = 0;\t\t\t\t\t\t\t\t\t\t\t\t\t\/\/ rootpage counter\n\n#define INSIZE 512\t\/\/ fixed max size for server response\nString input = &quot;&quot;;\t\/\/ in setup, this string has INSIZE bytes reserved\n\n\/\/ these are for the three millis() timestamps\nunsigned long t1;\t\t\/\/ start of sketch\nunsigned long t2;\t\t\/\/ after wifi connected\nunsigned long t3;\t\t\/\/ after GET or UDP send, or both\n\n\/\/ reboot webpage. You can have any page load after the delay\nconst String bootreload = &quot;&lt;!doctype html&gt;&lt;html lang = &#039;en&#039;&gt;&lt;head&gt;&lt;meta charset = &#039;utf-8&#039;&gt;\\\n&lt;title&gt;My Redirect Page&lt;\/title&gt;&lt;\/head&gt;&lt;body&gt;&lt;div&gt;\\\nRebooting,  reloading in 5 seconds...\\\n&lt;\/div&gt;&lt;script type = &#039;text\/javascript&#039;&gt;\\\nsetTimeout(function(){window.location.replace(&#039;\/&#039;);}, 5000);\\\n&lt;\/script&gt;&lt;\/body&gt;&lt;\/html&gt;&quot;;\n\/\/ the above (after 5 sec (5000) ) redirects to the place within &#x5B;window.location.replace(&#039;\/&#039;)]\n\/\/ &#039;\/&#039; is the rootpage at the current location but can be a fully qualified internet address.\n\/\/ so an initial web page can be displayed then after the delay, a different one comes up.\n\nconst String UDPtestMessage = &quot;Hi, this is a test message by UDP\\r\\n&quot;;\n\nint aNumber = 0;\nint temp;\n\nESP8266WebServer server(80);\nHTTPClient http;\nWiFiUDP udp;\n\n\/\/ ===========================================================================\n\n\/\/ webserver handler\nvoid handleRoot() {\n\tresponse = &quot;OK, &quot;;\n\tresponse += (String)++aNumber;\n\tserver.send(200, &quot;text\/plain&quot;, response);\n\tSerial.print(&quot;Rootpage accessed, content sent: &quot;);\n\tSerial.println(response);\n}\n\n\/\/ webserver handler\nvoid handleReboot() {\n\tserver.send(200, &quot;text\/html&quot;, bootreload);\n\tSerial.println(&quot;Reboot, webpage auto-reload in 5...&quot;);\n\tdelay(500);\t\t\t\/\/ give things time to happen\n\tESP.restart();\n}\n\n\/\/ webserver handler\nvoid handleNotFound() {\n\tserver.send(404, &quot;text\/plain&quot;, &quot;404: File Not Found&quot;);\n}\n\n\/\/ send a html string by UDP packet\nvoid sendUDPpacket()\n{\n\tSerial.print(&quot;sending UDP packet -&gt; &quot;);\n\tudp.beginPacket(UDPtarget, udpPort);\t\t\t\/\/ set up the IP and port\n\tudp.print(UDPtestMessage);\t\t\t\t\t\/\/ send it\n\tudp.endPacket();\n\tSerial.println(UDPtestMessage);\t\t\t\/\/ and copy string to serial\n\n}\n\n\/\/ ===================================================================================\n\/\/ note that there is no WiFi.begin() in the setup.\n\/\/ It IS accessed in a function the 1st time the sketch is run\n\/\/ so that the details can be stored, but any restarts after that\n\/\/ are connected by the saved credentials and it happens MUCH faster.\n\nvoid setup(void) {\nenableWiFiAtBootTime();  \/\/ required for release &gt;= 3\n\tt1 = millis();\t\t\t\t\t\t\t\/\/ first timestamp\n\n\/\/ a significant part of the speed gain is by using a static IP config\n\tWiFi.config(IPA, GATE, MASK);\n\n\tinput.reserve(INSIZE);\t\t\t\/\/ allocate fixed space for remote server response\n\n\tSerial.begin(115200);\t\t\t\t\/\/ start up serial port\n\n\/\/ so even though no WiFi.connect() so far, check and see if we are connecting.\n\/\/ The 1st time sketch runs, this will time-out and THEN it accesses WiFi.connect().\n\/\/ After the first time (and a successful connect), next time it connects very fast\n\twhile (WiFi.status() != WL_CONNECTED) {\n\t\tdelay(5);\t\t\t\/\/ use small delays, NOT 500ms\n\t\tif (++counter &gt; 1000) break;     \/\/ 5 sec timeout\n\t}\n\t\/\/if timed-out, connect the slow-way\n\tif (counter &gt; 1000) launchSlowConnect();\n\n\tt2 = millis();\t\t\t\/\/ second time-stamp. WiFi is now connected\n\n\n\/\/ some web pages for the server\n\tserver.onNotFound(handleNotFound);\n\tserver.on(&quot;\/&quot;, handleRoot);\n\tserver.on(&quot;\/reboot&quot;, handleReboot);\n\n\tserver.begin();\n\tSerial.println(&quot;\\nHTTP server started&quot;);\n\n\tSerial.print(&quot;Connected to &quot;);\n\tSerial.println(ssid);\n\tSerial.print(&quot;IP address: &quot;);\n\tSerial.println(WiFi.localIP());\n\n\t\t\/\/ ----------------------------------------------\n\t\t\/\/ comment out ONE of the following to check timings\n\n\t\t\/\/sendUDPpacket();\t\t\t\t\t\t\t\/\/ UDP send (this is fast)\n\tTestLink();\t\t\t\t\t\t\t\t\t\t\/\/ do a GET (slower)\n\n\t\t\/\/ when both active, elapsed time (using reset button) is about 570ms on my router\n\/\/ --------------------------------------------------\n\n\tt3 = millis();\t\t\t\/\/ third timestamp, network actions completed.\n\n\/\/ delay added here as sometimes it all happens before the USB \n\/\/ serial port is back (after a power-cycle)\n\tdelay(2000);\n\tSerial.println();\n\tSerial.println(&quot;snapshots of millis() counter..&quot;);\n\tSerial.print(&quot;Sketch begins: &quot;);\n\tSerial.println(t1);\t\t\t\/\/ start of sketch\n\tSerial.print(&quot;WiFi connected: &quot;);\n\tSerial.println(t2);\t\t\t\/\/ wifi connected\n\tSerial.print(&quot;Network transaction completed: &quot;);\n\tSerial.println(t3);\t\t\t\/\/ network actions done\n\/\/\t\tSerial.println(input);\t\t\/\/ received by GET\n\n}\n\/\/ ===================================================================================\n\n\n\/\/ ------------------------------------------------------------------------------------------\nvoid loop(void) {\n\tserver.handleClient();\t\t\t\/\/ local web-server\n}\n\/\/ ------------------------------------------------------------------------------------------\n\n\n\n\/\/ ------------------------------------------------------------------------------------------\n\/\/ this is accessed when the initial run fails to connect because no (or old) credentials\nvoid launchSlowConnect() {\n\tSerial.println(&quot;No (or wrong) saved WiFi credentials. Doing a fresh connect.&quot;);\n\tcounter = 0;\n\t\t\/\/ persistent and autoconnect should be true by default, but lets make sure.\n\tif (!WiFi.getAutoConnect()) WiFi.setAutoConnect(true);\t\/\/ autoconnect from saved credentials\n\tif (!WiFi.getPersistent()) WiFi.persistent(true);\t\t\t\/\/ save the wifi credentials to flash\n\n\n\/\/ Note the two forms of WiFi.begin() below. If the first version is used\n\/\/ then no wifi-scan required as the RF channel and the AP mac-address are provided.\n\/\/ so next boot, all this info is saved for a fast connect.\n\/\/ If the second version is used, a scan is required and for me, adds about 2-seconds\n\/\/ to my connect time. (on a cold-boot, ie power-cycle)\n\n\tWiFi.begin(ssid, password, channel, home_mac, true);\n\/\/\tWiFi.begin(ssid, password);\n\n\n\t\t\/\/ now wait for good connection, or reset\n\twhile (WiFi.status() != WL_CONNECTED) {\n\t\tdelay(500);\n\t\tSerial.print(&quot;.&quot;);\n\t\tif (++counter &gt; 20) {\t\t\t\t\/\/ allow up to 10-sec to connect to wifi\n\t\t\t\tSerial.println(&quot;wifi timed-out. Rebooting..&quot;);\n\t\t\t\tdelay(10);\t\/\/ so the serial message has time to get sent\n\t\t\t\tESP.restart();\n\t\t}\n\t}\n\tSerial.println(&quot;WiFi connected and credentials saved&quot;);\n}\n\/\/ ------------------------------------------------------------------------------------------\n\n\n\/\/ this does a GET to a local server. I use another ESP8266 running a basic server.\n\nint TestLink() {\n\n\tint z;\n\n\t\/\/ only go thru if wifi connected\n\tif ((WiFi.status() == WL_CONNECTED)) {\n\n\t\tWiFiClient client;\n\t\thttp.begin(client, localServer);\t\t\t\/\/ NEEDS fully qualified addr (http:\/\/...etc etc)\n\n\t\ttemp = http.GET();\n\t\tif (temp &gt; 0) {\n\t\t\t\/\/Serial.printf(&quot;&#x5B;HTTP] GET... code: %d\\n&quot;, temp);\n\t\t\t\/\/ file found at server\n\t\t\tif (temp == HTTP_CODE_OK) {\t\t\/\/ needs a 200 to continue..\n\t\t\t\tz = http.getSize();\t\t\t\/\/ how big is the payload?\n\/\/\t\t\t\tSerial.print(&quot;Payload size: &quot;);\n\/\/\t\t\t\tSerial.println(z);\t\t\t\t\/\/ show it\n\t\t\t\tif (z &lt; INSIZE) {\t\t\t\t\/\/ payload must fit in the available space.\n\t\t\t\t\tinput = http.getString();\t\/\/ read it in\n\/\/\t\t\t\t\tSerial.println(input);\t\t\/\/ and show the payload\n\t\t\t\t}\n\t\t\t\telse Serial.println(&quot;payload too big!&quot;);\t\/\/ error if it wont fit\n\t\t\t}\n\t\t}\n\t\telse {  \/\/ show the connect error\n\t\t\tSerial.printf(&quot;&#x5B;HTTP] GET... failed, error: %s\\n&quot;, http.errorToString(temp).c_str());\n\t\t}\n\t\thttp.end();\t\/\/ close it\n\t}\n\treturn temp;\n}\n\n\n<\/pre><\/div>\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 &hellip; <a href=\"https:\/\/pokewithastick.net\/?page_id=72\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"open","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-72","page","type-page","status-publish","hentry"],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/pokewithastick.net\/index.php?rest_route=\/wp\/v2\/pages\/72","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pokewithastick.net\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/pokewithastick.net\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/pokewithastick.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pokewithastick.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=72"}],"version-history":[{"count":30,"href":"https:\/\/pokewithastick.net\/index.php?rest_route=\/wp\/v2\/pages\/72\/revisions"}],"predecessor-version":[{"id":234,"href":"https:\/\/pokewithastick.net\/index.php?rest_route=\/wp\/v2\/pages\/72\/revisions\/234"}],"wp:attachment":[{"href":"https:\/\/pokewithastick.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=72"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}