Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter...

55
A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to be very popular, so I decided to create a follow-up: A Beginner's Guide to the ESP8266. That's right, a tutorial on how to use the world's most popular $3 Wi-Fi board. This is going to be a very in-depth tutorial, covering some networking concepts as well. If you're a beginner, and just want to go straight to the more exciting Wi-Fi part, feel free to do so, I included short TL;DR's in the longer, more technical parts. A short overview of what I'll cover in this article: 1. What is an ESP8266? A short overview of what an ESP8266 is, and what you can do with it 2. Deciding on what board to buy: There's loads of different ESP8266 available these days, finding the one that's best for you can be hard 3. Installing the software: you need to install some software to program the ESP8266, and maybe a USB driver 4. Setting up the hardware: some modules and boards need some external components 5. The ESP8266 as a microcontroller: the ESP8266 can be used as a normal microcontroller, just like an Arduino 6. Network protocols: Before we start using the Wi-Fi capabilities of the ESP8266, I'll teach you some of the network protocols involved 7. Setting up a Wi-Fi connection: That's probably why you're reading this, right? 8. Name resolution: Find the ESP8266 on your local network using mDNS 9. Setting up a simple web server: This enables you to add web pages to the ESP8266, and browse them from your computer or phone 10. Setting up an advanced web server: a more advanced server with a real file system that allows you to upload new files over Wi-Fi 11. OTA - uploading programs over Wi-Fi: You don't have to upload programs over USB, you can use Wi-Fi instead 12. Wirelessly controlling your RGB lighting: Change the color of your LED strips using your phone or computer 13. Getting the time: Connect to a time server using NTP and sync the ESP's clock 14. Monitoring sensors: log the temperature in your living room, save it in flash memory and show it in a fancy graph in your browser 15. Getting email notifications: Turn on a notification light when you've got unread emails 16. Advanced features: use DNS, captive portals, Wi-Fi connector libraries, OSC ... This guide expects some basic knowledge of microcontrollers like the Arduino. If that's something you're not already familiar with, I'd recommend you to read my Beginner's Guide to Arduino first, it covers a lot of the basics that I won't go into in this article. I really want to focus on the ESP8266-specific things, like Wi-Fi and other network protocols, the ESP's hardware, software, IoT, etc ... What is an ESP8266? The ESP8266 is a System on a Chip (SoC), manufactured by the Chinese company Espressif . It consists of a Tensilica L106 32-bit micro controller unit (MCU) and a Wi-Fi transceiver. It has 11 GPIO pins* (General Purpose Input/Output pins), and an analog input as well. This means that you can program it like any normal Arduino or other microcontroller. And on top of that, you get Wi-Fi communication, so you can use it to connect to your Wi-Fi network, connect to the Internet, host a web server with real web pages, let your smartphone connect to it, etc ... The possibilities are endless! It's no wonder that this chip has become the most popular IOT device available. There are many different modules available, standalone modules like the ESP-## series by AI Thinker, or complete development boards like the NodeMCU DevKit or the WeMos D1 . Different boards may have different pins broken out, have different Wi-Fi antennas, or a different amount of flash memory on board. (*) The ESP8266 chip itself has 17 GPIO pins, but 6 of these pins (6-11) are used for communication with the on-board flash memory chip. Programming There are different ways to program the ESP8266, but I'll only cover the method using the Arduino IDE. This is really easy for beginners, and it's a very familiar environment if you've used Arduino boards before. Just keep in mind that it's not limited to this option: there's also an official SDK available to program it in real C, this is very useful if you want to optimize your code or do some advanced tricks that aren't supported by the Arduino IDE. Another possibility is to flash it with a LUA interpreter, so you can upload and run LUA scripts. Or maybe you're more familiar with Python? Then you should check out the MicroPython firmware to interpret MicroPython scripts. I'm sure there's other languages available as well, so just do a quick Google search and write your code in the language of your choice. Requirements You'll need a couple of things in order to follow this guide: An ESP8266 board A computer that can run the Arduino IDE (Windows, Mac or Linux) A USB-to-Serial converter, it is very important that you use a 3.3V model* A USB cable A 3.3V power supply or voltage regulator* A Wi-Fi network to connect to (*) Your board may already include these. More information can be found in the next chapter.

Transcript of Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter...

Page 1: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

ABeginner'sGuidetotheESP8266PieterP, 08-03-2017

Sometimeago,IwroteaBeginner'sGuidetoArduinothatseemstobeverypopular,soIdecidedtocreateafollow-up:ABeginner'sGuidetotheESP8266.That'sright,atutorialonhowtousetheworld'smostpopular$3Wi-Fiboard.

Thisisgoingtobeaveryin-depthtutorial,coveringsomenetworkingconceptsaswell.Ifyou'reabeginner,andjustwanttogostraighttothemoreexcitingWi-Fipart,feelfreetodoso,IincludedshortTL;DR'sinthelonger,moretechnicalparts.

AshortoverviewofwhatI'llcoverinthisarticle:

1. WhatisanESP8266?AshortoverviewofwhatanESP8266is,andwhatyoucandowithit2. Decidingonwhatboardtobuy:There'sloadsofdifferentESP8266availablethesedays,findingtheonethat'sbestforyou

canbehard3. Installingthesoftware:youneedtoinstallsomesoftwaretoprogramtheESP8266,andmaybeaUSBdriver4. Settingupthehardware:somemodulesandboardsneedsomeexternalcomponents5. TheESP8266asamicrocontroller:theESP8266canbeusedasanormalmicrocontroller,justlikeanArduino6. Networkprotocols:BeforewestartusingtheWi-FicapabilitiesoftheESP8266,I'llteachyousomeofthenetworkprotocols

involved7. SettingupaWi-Ficonnection:That'sprobablywhyyou'rereadingthis,right?8. Nameresolution:FindtheESP8266onyourlocalnetworkusingmDNS9. Settingupasimplewebserver:ThisenablesyoutoaddwebpagestotheESP8266,andbrowsethemfromyourcomputeror

phone10. Settingupanadvancedwebserver:amoreadvancedserverwitharealfilesystemthatallowsyoutouploadnewfilesover

Wi-Fi11. OTA-uploadingprogramsoverWi-Fi:Youdon'thavetouploadprogramsoverUSB,youcanuseWi-Fiinstead12. WirelesslycontrollingyourRGBlighting:ChangethecolorofyourLEDstripsusingyourphoneorcomputer13. Gettingthetime:ConnecttoatimeserverusingNTPandsynctheESP'sclock14. Monitoringsensors:logthetemperatureinyourlivingroom,saveitinflashmemoryandshowitinafancygraphinyour

browser15. Gettingemailnotifications:Turnonanotificationlightwhenyou'vegotunreademails16. Advancedfeatures:useDNS,captiveportals,Wi-Ficonnectorlibraries,OSC...

ThisguideexpectssomebasicknowledgeofmicrocontrollersliketheArduino.Ifthat'ssomethingyou'renotalreadyfamiliarwith,I'drecommendyoutoreadmyBeginner'sGuidetoArduinofirst,itcoversalotofthebasicsthatIwon'tgointointhisarticle.IreallywanttofocusontheESP8266-specificthings,likeWi-Fiandothernetworkprotocols,theESP'shardware,software,IoT,etc...

WhatisanESP8266?TheESP8266isaSystemonaChip(SoC),manufacturedbytheChinesecompanyEspressif.ItconsistsofaTensilicaL10632-bitmicrocontrollerunit(MCU)andaWi-Fitransceiver.Ithas11GPIOpins*(GeneralPurposeInput/Outputpins),andananaloginputaswell.ThismeansthatyoucanprogramitlikeanynormalArduinoorothermicrocontroller.Andontopofthat,yougetWi-Ficommunication,soyoucanuseittoconnecttoyourWi-Finetwork,connecttotheInternet,hostawebserverwithrealwebpages,letyoursmartphoneconnecttoit,etc...Thepossibilitiesareendless!It'snowonderthatthischiphasbecomethemostpopularIOTdeviceavailable.

Therearemanydifferentmodulesavailable,standalonemodulesliketheESP-##seriesbyAIThinker,orcompletedevelopmentboardsliketheNodeMCUDevKitortheWeMosD1.Differentboardsmayhavedifferentpinsbrokenout,havedifferentWi-Fiantennas,oradifferentamountofflashmemoryonboard.

(*)TheESP8266chipitselfhas17GPIOpins,but6ofthesepins(6-11)areusedforcommunicationwiththeon-boardflashmemorychip.

Programming

TherearedifferentwaystoprogramtheESP8266,butI'llonlycoverthemethodusingtheArduinoIDE.Thisisreallyeasyforbeginners,andit'saveryfamiliarenvironmentifyou'veusedArduinoboardsbefore.Justkeepinmindthatit'snotlimitedtothisoption:there'salsoanofficialSDKavailabletoprogramitinrealC,thisisveryusefulifyouwanttooptimizeyourcodeordosomeadvancedtricksthataren'tsupportedbytheArduinoIDE.AnotherpossibilityistoflashitwithaLUAinterpreter,soyoucanuploadandrunLUAscripts.Ormaybeyou'remorefamiliarwithPython?ThenyoushouldcheckouttheMicroPythonfirmwaretointerpretMicroPythonscripts.I'msurethere'sotherlanguagesavailableaswell,sojustdoaquickGooglesearchandwriteyourcodeinthelanguageofyourchoice.

RequirementsYou'llneedacoupleofthingsinordertofollowthisguide:

AnESP8266boardAcomputerthatcanruntheArduinoIDE(Windows,MacorLinux)AUSB-to-Serialconverter,itisveryimportantthatyouusea3.3Vmodel*AUSBcableA3.3Vpowersupplyorvoltageregulator*AWi-Finetworktoconnectto

(*)Yourboardmayalreadyincludethese.Moreinformationcanbefoundinthenextchapter.

Page 2: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

HardwareDecidingonwhatboardtobuy

ESP8266isjustthenameofthechip,manycompanieshavedesignedtheirownboardsthatusethischip,sotherearemanydifferentESP8266boardsonthemarket.Ifyoudon'tknowthedifferencebetweenallthesedifferentmodels,youmighthaveahardtimedecidingonwhatboardtobuy.

Theeasiest(andfastest)waytogetanESP8266boardistobuyonefromawell-knownelectronicsshoplikeAdafruitorSparkFun,butifyouwantitcheap,youshouldcheckoutEbayorothersiteswhereyoucanorderthemdirectlyfromChina.

Developmentboards

Someboardshaveallkindsoffeatureson-boardtohelpdevelopingESP8266hardwareandsoftware:forexample,aUSBtoSerialconverterforprogramming,a3.3Vregulatorforpower,on-boardLEDsfordebugging,avoltagedividertoscaletheanaloginput...Ifyou'reabeginner,Iwoulddefinitelyrecommendadevelopmentboard.It'seasiertogetstartedifyoudon'thavetoworryaboutallthesethings.

Bare-bonesAIThinkerboards

IfyouwanttoaddanESP8266toasmallproject,orifyouwantacheaper*board,youmightwanttobuyaboardthatdoesn'thavethesefeatures.Inthatcase,youcanbuyoneofthemanyESP-##modulesdevelopedbyAIThinker.TheycontainjusttheESP8266andthenecessarycomponentstorunit.Toprogramtheboard,you'llneedanexternalUSB-to-Serialconverter.Withsomemodules,yougetanon-boardantenna(PCBorceramic)andanLED,someboardshavejustanantennaconnector,ornoLEDsatall.Theyalsodifferinphysicalsize,andflashmemorysize.Animportantthingtonotice,isthatsomeboardsdonotbreakoutallGPIOpins.Forexample,theESP-01onlyhas2I/Opinsavailable(apartfromtheTXandRXpins),whileothermodulesliketheESP-07orESP-12breakoutallavailableI/Opins.

(*)Theboarditselfischeaper,butyou'llhavetospendmoreonexternalparts.

Overview

Here'satablewithsomeofthemostpopularESP8266developmentboardsandtheirfeatures:

Board GPIO 3.3VVreg

USB-to-Serial

Auto-Reset

Auto-Program Flash ADC

range Extra

SparkFunESP8266Thing 11 + - + ±* 512KB(4Mb) 0-1V Batterycharger,cryptoelement,temperaturesensor,lightsensor

SparkFunESP8266Thing-DevBoard 11 + + + + 512KB(4Mb) 0-1V

NodeMCU 11 + + + + 4MB(32Mb) 0-3.3V

AdafruitFeatherHUZZAHwithESP8266 11 + + + + 4MB(32Mb) 0-1V Batterycharger

AdafruitHUZZAHESP8266Breakout 11 + - - - 4MB(32Mb) 0-1V 5V-tolerantRXandResetpins

ESP-## 4-11 - - - - 512KB(4Mb)–

4MB(32Mb) 0-1V Smallandcheap

YoucanfindthefulllistofESP-##moduleshere.

Asyoucansee,boththeNodeMCUandtheAdafruitFeatherHUZZAHaresolidchoices.

(*)Whenauto-programontheSparkFunESP8266Thingisenabled,youcan'tusetheSerialMonitor.

Gettingthehardwareready

TherearetwomaincategoriesofESP8266boards:developmentboardswithaUSBinterface(USB-to-Serialconvertor)on-board,andboardswithoutaUSBconnection.

DevelopmentboardswithaUSBinterface

Forexample:NodeMCU,SparkFunESP8266Thing-DevBoard,SparkFunBlynkBoard,AdafruitFeatherHUZZAHwithESP8266Wi-Fi...

TheseboardswillshowupinDevicemanager(Windows)orinlsusb(Linux)assoonasyouplugthemin.Theyhavea3.3Vregulatoron-board,andcanbeprogrammedoverUSBdirectly,soyoudon'tneedanyexternalcomponentstogetitworking.Theonlythingyoumayneedtodo,issolderonsomeheaders.

Bare-bonesboardsandboardswithoutaUSBinterface

Thiscategoryhas2sub-categories:boardswitha3.3Vregulatoron-board,andboardswithjusttheESP8266andaflashmemorychip,without3.3Vregulator.Ifyourboarddoesn'thavea5Vto3.3Vregulator,buyoneseparately.YoucoulduseanLM1117-3.3forexample.Theon-board3.3VregulatorofmostArduinoboardsisnotpowerfulenoughtopowertheESP.

Toprogramtheboard,you'llneedaUSB-to-Serialconverter.TheFTDIFT232RLisquitepopular,becauseitcanswitchbetween5Vand3.3V.ItisessentialthattheUSB-to-Serialconverteryoubuyoperatesat3.3V.Ifyoubuya5Vmodel,youwilldamagetheESP8266.

ConnectingtheUSB-to-Serialconverter

Page 3: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

1. Connecttheground(GND)oftheUSB-to-SerialconvertertothegroundoftheESP8266.2. ConnecttheRX-pinoftheUSB-to-SerialconvertertotheTXDpinoftheESP8266.(Onsomeboards,it'slabelledTXinsteadof

TXD,butit'sthesamepin.)3. ConnecttheTX-pinoftheUSB-to-SerialconvertertotheRXDpinoftheESP8266.(Onsomeboards,it'slabelledRXinsteadof

RXD,butit'sthesamepin.)4. IfyourESP8266boardhasaDTRpin,connectittotheDTRpinoftheUSB-to-Serialconverter.Thisenablesauto-resetwhen

uploadingasketch,moreonthatlater.

Enablingthechip

Ifyou'reusingabare-boneESP-##boardbyAIThinker,youhavetoaddsomeresistorstoturnontheESP8266,andtoselecttherightbootmode.

1. EnablethechipbyconnectingtheCH_PD(ChipPowerDown,sometimeslabeledCH_ENorchipenable)pintoVCCthrougha10KΩresistor.

2. DisableSD-cardbootbyconnectingGPIO15togroundthrougha10KΩresistor.3. SelectnormalbootmodebyconnectingGPIO0toVCCthrougha10KΩresistor.4. PreventrandomresetsbyconnectingtheRST(reset)pintoVCCthrougha10KΩresistor.5. Makesureyoudon'thaveanythingconnectedtoGPIO2(moreinformationinthenextchapter).

Addingresetandprogrambuttons

IfyourESP8266boarddoesn'thavearesetbutton,youcouldaddonebyconnectingapushbuttontobetweentheRSTpinandground.

Toputthechipintoprogrammingmode,youhavetopullGPIO0lowduringstartup.That'swhywealsoneedaprogrambutton.Becauseit'spossibletouseGPIO0asanoutput,wecan'tdirectlyshortittoground,thatcoulddamagethechip.Topreventthis,connect470Ωresistorinserieswiththeswitch.It'simportantthatthisresistanceislowenough,otherwise,itwillbepulledhighbythe10KΩresistorweaddedinthepreviousparagraph.

Connectingthepowersupply

IftheESP8266moduleyouhavedoesn'thavea3.3Vvoltageregulatoronboard,youhavetoaddoneexternally.YoucoulduseanLM1117-3.3forexample.

1. Connectthefirstpinoftheregulatortoground.2. Placea10µFcapacitorbetweenpin2(Vout)andground.Watchthepolarity!3. Placea10µFcapacitorbetweenpin3(Vin)andground.4. Connectpin2tothe3.3VorVCCoftheESP8266.5. Connectpin3toa5Vpowersource,aUSBport,forexample.

Page 4: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to
Page 5: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

Beforeyoubegin...There'safewthingsyouhavetolookoutforwhenusinganESP8266:Themostimportantthingisthatitrunsat3.3V,soifyouconnectittoa5Vpowersupply,you'llkillit.Unlikesome3.3VArduinoorTeensyboards,theESP8266'sI/Opinsarenot5Vtolerant,soifyouusea5VUSB-to-Serialconverter,or5Vsensorsetc.you'llblowitup.AsecondthingtokeepinmindisthattheESP8266canonlysourceorsink12mAperoutputpin,comparedto20-40mAformostArduinos.TheESP8266hasoneanalogtodigitalconverter,butithasastrangevoltagerange:0-1V,voltagesabove1Vmightdamagetheboard.

OnelastthingtokeepinmindisthattheESP8266hastosharethesystemresourcesandCPUtimebetweenyoursketchandtheWi-Fidriver.Also,featureslikePWM,interruptsorI²Careemulatedinsoftware,mostArduinosontheotherhand,havededicatedhardwarepartsforthesetasks.Formostapplicationshowever,thisisnottoomuchofanissue.

Page 6: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

SoftwareInstallationoftherequiredsoftware

ThefirststepistodownloadandinstalltheArduinoIDE.IexplainedthisinABeginner'sGuidetoArduino.(AsofFebruary7th2017,thelateststableversionoftheIDEis1.8.1.)

ToprogramtheESP8266,you'llneedapluginfortheArduinoIDE,itcanbedownloadedfromGitHubmanually,butitiseasiertojustaddtheURLintheArduinoIDE:

1. OpentheArduinoIDE.2. GotoFile>Preferences.3. PastetheURLhttp://arduino.esp8266.com/stable/package_esp8266com_index.jsonintotheAdditionalBoardManagerURLsfield.

(YoucanaddmultipleURLs,separatingthemwithcommas.)4. GotoTools>Board>BoardManagerandsearchfor'esp8266'.Selectthenewestversion,andclickinstall.(AsofFebruary7th

2017,thelateststableversionis2.3.0.)

Youcancheckouttheofficialinstallguidehere.

Drivers

IfyouareusingaboardwiththeCH340(G)USB-to-Serialchip,liketheNodeMCU,you'llprobablyhavetoinstalltheUSBdriversforit.TheycanbefoundonGitHub.IfyouareusingaboardwiththeCP2104USB-to-Serialchip,liketheAdafruitFeatherHUZZAHboard,you'llprobablyhavetoinstallUSBdriversaswell.YoucanfindthemontheSiliconLabswebsite.BoardswithanFTDIchipshouldworkrightoutofthebox,withouttheneedofinstallinganydrivers.

Python

IfyouwanttouseOverTheAirupdatesonWindows,youhavetoinstallPython2.7.Youcandownloaditfrompython.org.Duringtheinstallation,youhavetoselecttheoptiontoaddPythontoyourpath.Ifyoudon'tdothis,theArduinoIDEwon'tbeabletofindthePythonexecutable.

Examples

YoucanfindallexamplesusedinthisarticleonmyGitHub.Justdownloaditasa.ZIPfile,unzipittoaconvenientlocation,andyou'regoodtogo!

Page 7: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

TheESP8266asamicrocontroller-HardwareWhiletheESP8266isoftenusedasa‘dumb’Serial-to-WiFibridge,it’saverypowerfulmicrocontrolleronitsown.Inthischapter,we’lllookatthenon-Wi-FispecificfunctionsoftheESP8266.

DigitalI/OJustlikeanormalArduino,theESP8266hasdigitalinput/outputpins(I/OorGPIO,GeneralPurposeInput/Outputpins).Asthenameimplies,theycanbeusedasdigitalinputstoreadadigitalvoltage,orasdigitaloutputstooutputeither0V(sinkcurrent)or3.3V(sourcecurrent).

Voltageandcurrentrestrictions

TheESP8266isa3.3Vmicrocontroller,soitsI/Ooperatesat3.3Vaswell.Thepinsarenot5Vtolerant,applyingmorethan3.6Vonanypinwillkillthechip.

ThemaximumcurrentthatcanbedrawnfromasingleGPIOpinis12mA.

Usablepins

TheESP8266has17GPIOpins(0-16),however,youcanonlyuse11ofthem,because6pins(GPIO6-11)areusedtoconnecttheflashmemorychip.Thisisthesmall8-leggedchiprightnexttotheESP8266.Ifyoutrytouseoneofthesepins,youmightcrashyourprogram.

GPIO1and3areusedasTXandRXofthehardwareSerialport(UART),soinmostcases,youcan’tusethemasnormalI/Owhilesending/receivingserialdata.

Bootmodes

Asmentionedinthepreviouschapter,someI/Opinshaveaspecialfunctionduringboot:Theyselect1of3bootmodes:

GPIO15 GPIO0 GPIO2 Mode0V 0V 3.3V UartBootloader0V 3.3V 3.3V Bootsketch(SPIflash)3.3V x x SDIOmode(notusedforArduino)

Note:youdon’thavetoaddanexternalpull-upresistortoGPIO2,theinternaloneisenabledatboot.

Wemadesurethattheseconditionsaremetbyaddingexternalresistorsinthepreviouschapter,ortheboardmanufacturerofyourboardaddedthemforyou.Thishassomeimplications,however:

GPIO15isalwayspulledlow,soyoucan’tusetheinternalpull-upresistor.YouhavetokeepthisinmindwhenusingGPIO15asaninputtoreadaswitchorconnectittoadevicewithanopen-collector(oropen-drain)output,likeI²C.GPIO0ispulledhighduringnormaloperation,soyoucan’tuseitasaHi-Zinput.GPIO2can’tbelowatboot,soyoucan’tconnectaswitchtoit.

Internalpull-up/-downresistors

GPIO0-15allhaveabuilt-inpull-upresistor,justlikeinanArduino.GPIO16hasabuilt-inpull-downresistor.

PWM

UnlikemostAtmelchips(Arduino),theESP8266doesn’tsupporthardwarePWM,however,softwarePWMissupportedonalldigitalpins.ThedefaultPWMrangeis10-bits@1kHz,butthiscanbechanged(upto>14-bit@1kHz).

AnaloginputTheESP8266hasasingleanaloginput,withaninputrangeof0-1.0V.Ifyousupply3.3V,forexample,youwilldamagethechip.SomeboardsliketheNodeMCUhaveanon-boardresistivevoltagedivider,togetaneasier0-3.3Vrange.Youcouldalsojustuseatrimpotasavoltagedivider.

TheADC(analogtodigitalconverter)hasaresolutionof10bits.

Communication

Serial

TheESP8266hastwohardwareUARTS(Serialports):UART0onpins1and3(TX0andRX0resp.),andUART1onpins2and8(TX1andRX1resp.),however,GPIO8isusedtoconnecttheflashchip.ThismeansthatUART1canonlytransmitdata.

UART0alsohashardwareflowcontrolonpins15and13(RTS0andCTS0resp.).ThesetwopinscanalsobeusedasalternativeTX0andRX0pins.

I²C

TheESPdoesn’thaveahardwareTWI(TwoWireInterface),butitisimplementedinsoftware.Thismeansthatyoucanuseprettymuchanytwodigitalpins.Bydefault,theI²Clibraryusespin4asSDAandpin5asSCL.(ThedatasheetspecifiesGPIO2asSDAandGPIO14asSCL.)Themaximumspeedisapproximately450kHz.

SPI

Page 8: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

TheESP8266hasoneSPIconnectionavailabletotheuser,referredtoasHSPI.ItusesGPIO14asCLK,12asMISO,13asMOSIand15asSlaveSelect(SS).ItcanbeusedinbothSlaveandMastermode(insoftware).

GPIOoverview

GPIO Function State Restrictions0 Bootmodeselect 3.3V NoHi-Z1 TX0 - NotusableduringSerialtransmission

2 BootmodeselectTX1 3.3V(bootonly) Don’tconnecttogroundatboottime

Sendsdebugdataatboottime3 RX0 - NotusableduringSerialtransmission4 SDA(I²C) - -5 SCL(I²C) - -6-11 Flashconnection x Notusable,andnotbrokenout12 MISO(SPI) - -13 MOSI(SPI) - -14 SCK(SPI) - -15 SS(SPI) 0V Pull-upresistornotusable

16 Wakeupfromsleep - Nopull-upresistor,butpull-downinsteadShouldbeconnectedtoRSTtowakeup

TheESP8266asamicrocontroller-SoftwareMostofthemicrocontrollerfunctionalityoftheESPusesexactlythesamesyntaxasanormalArduino,makingitreallyeasytogetstarted.

DigitalI/O

JustlikewitharegularArduino,youcansetthefunctionofapinusingpinMode(pin,mode);wherepinistheGPIOnumber*,andmodecanbeeitherINPUT,whichisthedefault,OUTPUT,orINPUT_PULLUPtoenablethebuilt-inpull-upresistorsforGPIO0-15.Toenablethepull-downresistorforGPIO16,youhavetouseINPUT_PULLDOWN_16.

(*)NodeMCUusesadifferentpinmapping,readmorehere.ToaddressaNodeMCUpin,e.g.pin5,useD5:forinstance:pinMode(D5,OUTPUT);

Tosetanoutputpinhigh(3.3V)orlow(0V),usedigitalWrite(pin,value);wherepinisthedigitalpin,andvalueeither1or0(orHIGHandLOW).

Toreadaninput,usedigitalRead(pin);

ToenablePWMonacertainpin,useanalogWrite(pin,value);wherepinisthedigitalpin,andvalueanumberbetween0and1023.

Youcanchangetherange(bitdepth)ofthePWMoutputbyusinganalogWriteRange(new_range);

ThefrequencycanbechangedbyusinganalogWriteFreq(new_frequency);.new_frequencyshouldbebetween100and1000Hz.

Analoginput

JustlikeonanArduino,youcanuseanalogRead(A0)togettheanalogvoltageontheanaloginput.(0=0V,1023=1.0V).

TheESPcanalsousetheADCtomeasurethesupplyvoltage(VCC).Todothis,includeADC_MODE(ADC_VCC);atthetopofyoursketch,anduseESP.getVcc();toactuallygetthevoltage.Ifyouuseittoreadthesupplyvoltage,youcan’tconnectanythingelsetotheanalogpin.

Communication

Serialcommunication

TouseUART0(TX=GPIO1,RX=GPIO3),youcanusetheSerialobject,justlikeonanArduino:Serial.begin(baud).

Tousethealternativepins(TX=GPIO15,RX=GPIO13),useSerial.swap()afterSerial.begin.

TouseUART1(TX=GPIO2),usetheSerial1object.

AllArduinoStreamfunctions,likeread,write,print,println,...aresupportedaswell.

I²CandSPI

YoucanjustusethedefaultArduinolibrarysyntax,likeyounormallywould.

SharingCPUtimewiththeRFpartOnethingtokeepinmindwhilewritingprogramsfortheESP8266isthatyoursketchhastoshareresources(CPUtimeandmemory)withtheWi-Fi-andTCP-stacks(thesoftwarethatrunsinthebackgroundandhandlesallWi-FiandIPconnections).Ifyourcodetakestoolongtoexecute,anddon’tlettheTCPstacksdotheirthing,itmightcrash,oryoucouldlosedata.It’sbesttokeeptheexecutiontimeofyouloopunderacoupleofhundredsofmilliseconds.

Everytimethemainloopisrepeated,yoursketchyieldstotheWi-FiandTCPtohandleallWi-FiandTCPrequests.

Ifyourlooptakeslongerthanthis,youwillhavetoexplicitlygiveCPUtimetotheWi-Fi/TCPstacks,byusingincludingdelay(0);oryield();.Ifyoudon’t,networkcommunicationwon’tworkasexpected,andifit’slongerthan3seconds,thesoftWDT(WatchDogTimer)willresettheESP.IfthesoftWDTisdisabled,afteralittleover8seconds,thehardwareWDTwillresetthechip.

Page 9: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

Fromamicrocontroller’sperspectivehowever,3secondsisaverylongtime(240millionclockcycles),sounlessyoudosomeextremelyheavynumbercrunching,orsendingextremelylongstringsoverSerial,youwon’tbeaffectedbythis.Justkeepinmindthatyouaddtheyield();insideyourfororwhileloopsthatcouldtakelongerthan,say100ms.

SourcesThisiswhereIgotmostofmyinformationtowritthisarticle,there’ssomemoredetailsontheGitHubpages,ifyou’reintosomemoreadvancedstuff,likeEEPROMordeepsleepetc.

https://github.com/esp8266/Arduino/issues/2942https://github.com/esp8266/Arduino/pull/2533/fileshttps://github.com/esp8266/Arduino/blob/master/doc/libraries.mdhttps://github.com/esp8266/Arduino/blob/master/doc/reference.mdhttps://github.com/esp8266/Arduino/blob/master/doc/boards.md

Page 10: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

Wi-FiUsingtheESP8266asasimplemicrocontrollerisgreat,butthereasonwhymostpeopleuseit,isitsWi-Ficapabilities.Inthischapter,we'lldiveintothewonderfulworldofnetworkprotocols,likeWi-Fi,TCP,UDP,HTTP,DNS...Alltheseacronymsmightintimidateyou,butI'lltrymybesttoexplainthemstep-by-stepandinaneasyway.

Someparagraphsareinitalic.Theseprovidesomeextrainformation,butarenotcriticaltounderstandingtheESP'sWi-Fifunctions,sodon'tgetfrustratediftherearethingsyoudon'tunderstand.

It'sreallyhardtogiveaclearexplanation,withoutover-complicatingthingsandwhilekeepingitshortenoughaswell.Ifyou'vegotanyfeedbackorremarks,besuretoleaveacommenttohelpimprovethisarticle.Thanks!

TheTCP/IPstackThesystemmostpeoplerefertoas'TheInternet'isn'tjustoneprotocol:it'sanentirestackoflayersofprotocols,oftenreferredtoastheTCP/IPstack.We'llgooverthesedifferentlayers,becauseweneedtounderstandhowourESP8266communicateswithotherdevicesonthenetwork.

Layer ProtocolsApplication HTTP,FTP,mDNS,WebSocket,OSC...Transport TCP,UDPInternet IPLink Ethernet,Wi-Fi...

TheLinklayer

Thelinklayercontainsthephysicallinkbetweentwodevices,anEthernetcable,forexample,oraWi-Ficonnection.Thisisthelayerthatisclosesttothehardware.ToconnectanESP8266tothenetwork,youhavetocreateaWi-Filink.Thiscanhappenintwodifferentways:

1. TheESP8266connectstoawirelessaccesspoint(WAPorsimplyAP).TheAPcanbebuilt-intoyourmodemorrouter,forexample.Inthisconfiguration,theESPactslikeawirelessstation.

2. TheESP8266actsasanaccesspointandwirelessstationscanconnecttoit.Thesestationscouldbeyourlaptop,asmartphone,orevenanotherESPinstationmode.

OncetheWi-Filinkisestablished,theESP8266ispartofalocalareanetwork(LAN).AlldevicesonaLANcancommunicatewitheachother.Mostofthetime,theAPisconnectedtoaphysicalEthernetnetworkaswell,thismeansthattheESP8266canalsocommunicatewithdevicesthatareconnectedtotheAP(modem/router)viaawiredEthernetconnection(desktopcomputers,gamingconsolesandset-topboxes,forinstance).IftheESP8266isinaccesspointmode,itcancommunicatewithanystationthatisconnectedtoit,andtwostations(e.g.alaptopandasmartphone)canalsocommunicatewitheachother.

TheESPcanbeusedinAP-only,station-only,orAP+stationmode.

TL;DR

Thelinklayeristhephysicallinkbetweendevices:inthecaseoftheESP8266,thisisaWiFiconnection.TheESPcanactasastationandconnecttoanaccesspoint,oractasanaccesspointandletotherdevicesconnecttoit.

TheInternetorNetworklayer

Althoughthedevicesarenowphysicallyconnected(eitherthroughactualwires(Ethernet)orthroughradiowaves(Wi-Fi)),theycan'tactuallytalktoeachotheryet,becausetheyhavenowayofknowingwheretosendthemessageto.That'swheretheInternetProtocol(IP)comesin.EverydeviceonthenetworkhasapersonalIPaddress.TheDHCPserver(DynamicHostConfigurationProtocolServer)makessurethattheseaddressesareunique.Thismeansthatyoucannowsendamessagetoaspecificaddress.

TherearetwoversionsoftheInternetProtocol:IPv4andIPv6.IPv6isanimprovedversionofIPv4andhasmuchmoreaddressesthanIPv4(becausetherearemuchmoredevicesthanavailableIPv4addresses).Inthisarticle,we'llonlytalkaboutIPv4addresses,sincemostLANsstillusethem.

TheIPaddressconsistsof4numbers,forexample192.168.1.5isavalidIPv4address.Itactuallyconsistsoftwoparts:thefirstpartis192.168.1,thisistheaddressofthelocalnetwork.Thelastdigit,5inthiscase,isspecifictothedevice.

ByusingIPaddresses,wecanfindtheESP8266onthenetwork,andsendmessagestoit.TheESPcanalsofindourcomputerorourphone,ifitknowstheirrespectiveIPaddresses.

Sub-netmask(optional)

ThissubdivisionoftheIPaddressisdeterminedbythesub-netmask,oftenwrittenas255.255.255.0.Youcanseethatitconsistsoffournumbers,justliketheIPaddress.Ifapartofthesub-netmaskis255,itmeansthatthecorrespondingpartoftheIPaddressispartofthenetworkaddress,ifit's0,thecorrespondingIPpartispartoftheaddressofthespecificaddress.Adifferentnotationto"IP:192.168.1.5,sub-netmask:255.255.255.0"wouldbe"192.168.1.5/24",becausethebinaryrepresentationofthesub-netmaskis11111111.11111111.11111111.00000000,andithas24ones.Ifyouwanttoknowmoreaboutsub-nets,I'drecommendyoutoreadtheWikipediaarticle.(Aquicktiptohelpyouremember:it'scalledthesub-netmask,becauseifyouperformabitwiseANDoperationontheIPaddressandthesub-netmask(i.e.usethesub-netmaskasamaskfortheIPaddress),yougettheaddressofthesub-net.)

Page 11: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

MACaddressesandARP(optional)

ItisactuallyimpossibletosendpacketsdirectlytoanothermachineusingonlytheIPaddress.TosendapackettoaspecificdeviceontheLAN(Wi-FiorEthernet),youhavetoknowitsMAC-address.TheMACaddressisauniquenumberthatisuniqueforeverynetworkdevice,anditneverchanges,it'shardwiredinthenetworkchip.ThismeansthateveryESP8266,everynetworkcard,everysmartphone...evermade,hasadifferentMACaddress.SobeforetheESPcansendapackettoyoursmartphoneforexample,ithastoknowitsMACaddress.Itdoesn'tknowthisyet,theESPonlyknowstheIPaddressofthesmartphone,say192.168.1.6.Todothis,theESPsendsabroadcastmessage(i.e.amessageaddressedtoalldevicesontheLAN)saying"I'mlookingfortheMACaddressofthedevicewiththeIPaddress192.168.1.6".TheESPalsoincludesitsownIPandMACaddresswiththemessage.Whenthesmartphonereceivesthisbroadcastmessage,itrecognizesitsownIPaddress,andrespondstotheESPbysendingitsownMACaddress.NowtheESPandthephonebothknoweachother'sIPandMACaddresses,andtheycancommunicateusingIPaddresses.ThismethodiscalledtheAddresResolutionProtocol,orARP.

WhatabouttheInternet?

Asyoumighthavenoticed,Ionlytalkedaboutthelocalareanetwork,thesearethecomputersinyourownhouse.SohowcantheESP8266communicatewiththeInternet,youmayask?Well,there'salotofnetworkinfrastructureinvolvedin'TheInternet',andtheyallobeytheIPrules,tomakesuremostofyourpacketsarriveattheredestination.It'snotthatsimpleofcourse,there'salotofthingsgoingon,likeroutingandNetworkAddressTranslation(NAT),butthatfallsoutsidethescopeofthisarticle,andit'snotreallysomethingmostpeoplehavetoworryabout.

TL;DR

TheInternetlayerusesIPaddressesinordertoknowwhereitshouldsendthedata.Thismeansthattwodevicescannowsendpacketsofdatatoeachother,evenovertheInternet.

TheTransportlayer

ThedifferentdevicesinthenetworkdotheirbesttodelivertheseIPpacketstotheaddressee,however,it'snotuncommonforapackettogetlost,soitwillneverarrive.Orthepacketmightgetcorruptedontheway:thedataisnolongercorrect.IPalsocan'tguaranteethatthepacketsarriveinthesameordertheyweresentin.Thismeansthatwecan'treliablysendmessagesyetbyonlyusingthelinkandtheInternetlayer,sincewecanneverknowwhenandwhetherapacketwillarrive,orknowforcertainthatareceivedpacketiscorrect.WeneedathirdlayerontopoftheInternetlayer:theTransportlayer.

Therearemainlytwoprotocolsthatmakeupthisthirdlayer:theTransmissionControlProtocol(TCP)andtheUserDatagramProtocol(UDP).

TCPmakessurethatallpacketsarereceived,thatthepacketsareinorder,andthatcorruptedpacketsarere-sent.Thismeansthatitcanbeusedforcommunicationbetweenmultipleapplications,withouthavingtoworryaboutdataintegrityorpacketloss.Thisiswhyit'susedforthingslikedownloadingwebpages,sendingemail,uploadingfilesetc.UDPontheotherhand,doesn'tguaranteethateverypacketreachesitsdestination,itdoescheckforerrorshowever,butwhenitfindsone,itjustdestroysthepacket,withoutre-sendingit.Thismeansthatit'snotasreliableasTCP,butit'sfaster,andhasamuchlowerlatency,becauseitdoesn'trequireanopenconnectiontosendmessages,likeTCPdoes.That'swhyit'susedinvoiceandvideochats,andforexampleinonlinegames.

IfyouwanttoknowmoreaboutthedifferencesbetweenTCPandUDP,checkoutthisvideo.

TL;DR

TheIPprotocolisnotreliable,andhasnoerrorchecking.TCPsolvesthisbyre-sendinglostorcorruptpackages,andorderspacketsthatarereceivedinthewrongorder.UDPalsochecksforcorruptpackages,butdoesn'tre-sendthem,soithaslesslatencythanTCP.

TheApplicationlayer

WenowhavereliablecommunicationusingTCP,butthere'sstilloneproblem.Thinkofitthisway:youaresendingaletter,andTCPguaranteesthatitwillarriveatitsdestination,butifthereceiverdoesn'tunderstandthelanguageit'swrittenin,hewon'tknowwhattodowithit.Inotherwords,weneedafourthlayerofprotocols,fortwoprogramstobeabletocommunicatewitheachother.There'slotsofdifferentprotocolsoutthere,butwe'llmostlyfocusontheprotocolsforwebserversandbrowsers.

HyperTextTransferProtocol

TheHyperTextTransferProtocol,orHTTP,istheprotocol(cfr.language)thatisusedbybothwebserversandwebclientsinordertocommunicate.Itusestexttoperformsendrequestsandresponsesfromtheclienttotheserverandbackagain.Forexample,whenyoutypehttp://www.google.comintotheaddressbarofawebbrowser(client),itwillsendanHTTPGETrequesttotheGooglewebserver.TheserverunderstandsthisHTTPrequest,andwillsendtheGooglewebpageasaresponse.OrwhenyouuploadanimagetoInstagram,yourbrowsersendsanHTTPPOSTrequestwithyourselfieattachedtotheInstagramserver.Theserverunderstandstherequest,savestheimageandaddsitintothedatabase,sendstheURLofthenewimagebacktoyourbrowser,andthebrowserwilladdtheimageonthewebpage.Asyoucansee,neithertheclientnortheserverhastoworryabouttheintegrityofthemessagestheysend,andtheyknowthattherecipientunderstandstheirlanguage,andthatitwillknowwhattodowithacertainHTTPrequest.MostmodernsitesuseasecureversionofHTTP,calledHTTPS.Thissecureconnectionencryptsthedata,forsecurityreasons.(Youdon'twantanyonereadingthepacketsfromyourmailserver,orthepacketsyousenttoyourbank,forinstance.)

WebSocket

HTTPisgreatforthingslikedownloadingwebpages,uploadingphotosetc.butit'squiteslow:everytimeyousendanHTTPrequest,youhavetostartanewTCPconnectiontotheserver,thensendyourrequest,waitfortheservertorespond,anddownloadtheresponse.Wouldn'titbegreatifwedidn'thavetoopenanewconnectioneverytimewewanttosendsomedata,andifwecouldsendandreceivedataatthesametimeatanymomentwe'dlike?That'swhereWebSocketcomestotherescue:youcankeeptheTCPconnectionwiththeserveropenatalltimes,yougetperfectTCPreliability,andit'sprettyfast.

OpenSoundControl

Page 12: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

HTTPandWebSocketbothuseTCPconnections.Whatifyouwantlowerlatency?Well,OpenSoundControl,orOSC,usesUDPtosendsmallpiecesofdata,likeints,floats,shorttextetc...withverylowlatency.Itwasoriginallydesignedforcontrollinglowlatencyaudioapplications,butit'saveryflexibleprotocol,soit'softenusedforlow-latencytasksotherthanaudiocontrol.

DomainNameSystem

Asmentionedbefore,youcanonlysendamessagetoanothercomputerifyouknowitsIPaddress.ButwhenyoubrowsetheInternet,youonlyknowawebsite'sdomainname(e.g.www.google.com).YourcomputerusestheDomainNameSystemtotranslatethisdomainnametotherightIPaddress.Moreonthislater.

Sources

https://en.wikipedia.org/wiki/Internet_protocol_suitehttps://en.wikipedia.org/wiki/Port_(computer_networking)https://en.wikipedia.org/wiki/Transmission_Control_Protocolhttps://en.wikipedia.org/wiki/Internet_Protocolhttps://en.wikipedia.org/wiki/User_Datagram_Protocol

Page 13: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

UploadingsketchestotheESP8266TheuploadprocedureforESP8266boardsisalittledifferentfromthenormalArduinoprocedure.MostArduinoswillautomaticallyresetwhenanewprogramisbeinguploaded,andwillautomaticallyenterprogrammingmode.OnsomeESPboardsyouhavetomanuallyenterprogrammingmode,andonthebare-bonesmodules,youevenhavetoresetthemmanually.However,therearesomesimplecircuitsyoucanusetogetautomaticuploads.

Auto-resetThisonlyappliestoboardswithoutanon-boardUSB-to-Serialconverter.

IftheUSB-to-Serialconverteryou'reusinghasaDTRflowcontrolline,youcanautomatetheresetsignal.WhensendingdatatotheESP,theDTRlinegoeslow,andstayslowforsometime.ToresettheESP,weneedalowpulseontheRSTpin.TheproblemisthattheDTRpinstayslow.Tosolvethis,we'regoingtobuildacrudeedgedetectorcircuit,usingacapacitor.Takealookatthefollowingschematic:

Youmightrecognizethatthisisbasicallyalow-cutfilter.Innormalconditions,DTRishigh(3.3V),andtheresetlineisalsohigh,becauseofthepull-upresistorR2.Thismeansthatthevoltageacrossthecapacitoris0V.WhenDTRsuddenlydrops(to0V),thevoltageacrossthecapacitorisstill0V,meaningthattheresetlinewillbeat0V+0V=0V,andaresetistriggered.

However,C1immediatelystartschargingthroughR2,andreaches3.3V.Atthispoint,DTRisstillat0V,meaningthatthere'snow3.3Vacrossthecapacitor.WhenDTRrisesagain,theresetlinewillbeat3.3V+3.3V=6.6V,andthenimmediatelystartstodischargethroughR2,finallyreaching3.3Vagain,with0VacrossC1.Thisisaproblem:6.6VcandamagetheESP,sowehavetofindawaytogetridofthepositivepeak.

OneglanceatthisMATLABsimulationshowsustheproblemevenbetter:

Page 14: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

ThebluesignalisthevoltageontheDTRpin,andtheyellowsignalisthevoltageontheresetpin.

Thesolutionistoaddadiode:whilechargingthecapacitor,itshouldn'tchangeanything,soitshouldbereversebiased(justafancywayofsayingthatit'snotconductinganycurrentbecausethepolarityistheotherwayaround),andwhilethecapacitorisdischarging,itshoulddischargethecapacitor"immediately".Here'swhatthatlookslike:

Let'srunthesimulationagaintocheckifourproblemissolved:

Page 15: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

Asyoucansee,the6.6Vpeakisnowverynarrow,justlikewewanted.It'simpossibletodischargethecapacitorinstantly,thatwouldrequireacapacitorandadiodewith0Ωofseriesresistance,andaninfinitecurrent,whichisimpossible,obviously.There'salsoasmallerbutrelativelywidepeakofapproximately3.9V.Thisisbecauseadiodeonlyconductswhenthevoltageacrossitishigherthan~600mV.Thismeansthatthelast0.6Vthat'sleftinthecapacitor(from3.9to3.3V)willstillbedischargedthroughR2only.Nevertheless,thevoltagepeakismuchlowerandnarrowerthanwithoutthediode,andit'ssafetoconnecttotheESP8266.

ThisexactcircuitisalsousedintheArduinoUno,forexample.

Note:ifyoufollowedtheinstructionsinthehardwarestepcorrectly,youshouldalreadyhaveaddedR2toyourESP.

HowtouseAuto-reset

Tousethisauto-resetcircuit,connectittotheDTRlineofyourUSB-to-Serialconverter,andtotheresetlineoftheESP,asshowninthediagram.Thenclickcompile(justbecausethefirstcompilationcantakequitesometime).GotoTools>Resetandselect'ck'.Whenit'sdonecompiling,holddowntheprogrambuttonweaddedinthehardwarestep,andclickupload.Waitforittosay"Uploading..."andthenreleasetheprogrambutton.

Auto-resetandAuto-program

Thisonlyappliestoboardswithoutanon-boardUSB-to-Serialconverter.

Themethodabovestillrequiresyoutopressabuttontouploadanewsketch.IfyourUSB-to-SerialconverterhasaRTSlineaswellasaDTRline,youcanautomatetheentireprocess.

Page 16: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

Youmayfindoutthatthe4.7kΩresistordoesn'tworkforyou.Inthatcase,trysomeothervalue,like10kΩ,forexample.

ThismethodwasfirstusedintheNodeMCU,sogotoTools>ResetMethod,andselect"nodemcu".ThiswilldrivetheDTR&RTSpinshighandlowintherightsequencetogetitinprogrammingmodebeforeuploading.

Thisisbyfarthebestmethod,buttheproblemisthatyouneedaccesstoboththeRTSandDTRpins,whilemostUSB-to-Serialadaptersbreakoutonlyoneofthetwo.

ManualresetandmanualprogramThisonlyappliestoboardswithoutanon-boardUSB-to-Serialconverter.

Ifyoudon'thaveaUSB-to-SerialconverterwithDTRandRTSlines,youcouldalsojustusetheresetandprogrambuttonsweaddedinthehardwarechapter.TogettheESPinprogrammode,GPIO0mustbelowwhilebooting:

1. pressandholdtheresetbutton2. pressandholdtheprogrambutton3. releasetheresetbutton,theESPwillbootinprogrammode4. releasetheprogrambutton5. uploadthesketch

Ifyouwanttogetoutofprogrammodewithoutuploading,justpressreset(withoutpressingtheprogrambutton).

Boardoptions

IfyourspecificboardisintheTools>Boardlist(e.g.NodeMCU,SparkFunandAdafruitboards),youcanjustselectit,andyouwillgettherightsettings.Whenyourboardisn'tinthelist,you'llhavetoselectaGenericESP8266.Inthatcasethere'slotsofnewoptionsintheToolsmenuoftheArduinoIDE,solet'sgooverthemandpicktherightsettings.

FlashMode

LikeIsaidbefore,theESP8266usesanexternalflashchipforstorage.Youcancommunicatewiththischipover2datalines(DIO),oroverall4datalines(QIO).Using4linesistwotimesfasterthan2lines,soinmostcases,youshouldchooseQIO.(Ifyou'redoingsomeadvancedstuffandyouneed2moreGPIOpins,youcoulduse2linesinsteadof4,andusethe2linesasI/O.Mostmodulesdon'tgiveyouaccesstothesepins,though.)

FlashSize

Differentboards/moduleshavedifferentsizesofflashchipsonboard.Thereareboardswith512kB,1MB,2MBand4MBofflash.To

Page 17: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

knowhowmuchflashyourboardhas,youcantrytheExamples>ESP8266>CheckFlashConfigtoseeifyourflashsettingiscorrect,oryoucancheckthespecificationsofyourspecificboardonline.YoucanalsoselecttheSPIFFS(SPIFlashFileSystem)size.TheSPIFFSpartitionisasmallfilesystemtostorefiles.Ifyou'renotusingit,youcanselecttheminimum.Lateroninthearticle,we'lluseSPIFFS,andI'llremindyoutoselectalargerSPIFFSsize,butfornow,itdoesn'treallymatter.

Debugport

There'saloadofthingsgoingonwhentheESPisrunning:ThingslikeWi-Ficonnections,TCPconnections,DNSlookups...younameit.Allthesesmalltasksproduceawholelotofdebugoutputtohelpyoutroubleshoot.However,inanormalsituation,whereyourprogramisbehavingasexpected,youdon'tneedallthosedebugmessagestofloodtheSerialMonitor,soyoucanjustturnthemoffbyselecting'Disabled'.Ifyoudowishtoreceivedebugmessages,youcanselecttheporttosendthemto.(Serialonpins1and3,orSerial1onpin2)

Debuglevel

Thisallowsyoutochoosewhatkindofdebugmessagesyouwanttoshow.

ResetMethod

Asmentionedintheparagraphsabove,therearedifferentmethodsforauto-resetandauto-program.Ifyou'reusingthefirstmethod(usingtheedgedetector),youshoulduse'ck',ifyouusethetwo-transistorcircuit,select'nodemcu'.

FlashFrequency

Ifyouneedsomeextramemoryspeed,youcouldchangetheflashfrequencyfrom40MHzto80MHz.ThisistheclockfrequencyoftheSPI/SDIOlink.

CPUFrequency

IfyouneedsomeextraCPUperformance,youcandoubletheclockspeedfrom80MHzto160MHz.It'sactuallyanoverclock,butI'veneverhadanyissuesorinstability.

UploadSpeed

ThebaudrateforuploadingtotheESP.Thedefaultis115200baud,butyoucangohigher(ifyou'rechangingyoursketchalot,itmightbetooslow).921600baudworksmostofthetime,butyoumaygetanerrorsometimes,ifthat'sthecase,switchingbackto115200willprobablysolveallproblems.

Page 18: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

EstablishingaWi-FiconnectionLikeImentionedinthepreviouschapter,theESP8266canoperateinthreedifferentmodes:Wi-Fistation,Wi-Fiaccesspoint,andbothatthesametime.We'llstartbylookingattheconfigurationofaWi-Fistation.

Stationmode

Connectingtoonespecificnetwork

#include<ESP8266WiFi.h>//IncludetheWi-Filibrary

constchar*ssid="SSID";//TheSSID(name)oftheWi-Finetworkyouwanttoconnecttoconstchar*password="PASSWORD";//ThepasswordoftheWi-Finetwork

voidsetup(){Serial.begin(115200);//StarttheSerialcommunicationtosendmessagestothecomputerdelay(10);Serial.println('\n');WiFi.begin(ssid,password);//ConnecttothenetworkSerial.print("Connectingto");Serial.print(ssid);Serial.println("...");

inti=0;while(WiFi.status()!=WL_CONNECTED){//WaitfortheWi-Fitoconnectdelay(1000);Serial.print(++i);Serial.print('');}

Serial.println('\n');Serial.println("Connectionestablished!");Serial.print("IPaddress:\t");Serial.println(WiFi.localIP());//SendtheIPaddressoftheESP8266tothecomputer}

voidloop(){}

Thecodetoconnecttoawirelessaccesspointisrelativelystraightforward:entertheSSIDandthepasswordofthenetworkyouwanttoconnectto,andcalltheWiFi.beginfunction.Thenwaitfortheconnectiontocomplete,etvoilà,yourESP8266isnowconnectedtoyourLocalAreaNetwork.

Don'tbelieveme?I'llproveittoyou:opentheSerialmonitor(CTRL+SHIFT+M)anduploadthesketch.Youshouldseesomethinglikethis:

ConnectingtoSSID...123456...

Connectionestablished!IPaddress: 192.168.1.3

Nowgotoyourcomputerandopenupaterminal:OnWindows,searchfor"CommandPrompt",onMacorLinux,searchfor"Terminal".Youcouldalsousetheshortcuts:onWindows,hit +R,type"cmd"andhitenter,onLinux,useCTRL+ALT+T.

Next,typeping,andthentheIPaddressyoureceivedintheSerialmonitor.Ifyou'reonMacorLinux,useCTRL+Ctostopitafteracoupleoflines.Theoutputshouldlooksomethinglikethis:

user@computername:~$ ping192.168.1.3PING192.168.1.3(192.168.1.3)56(84)bytesofdata.64bytesfrom192.168.1.3:icmp_seq=1ttl=128time=6.38ms64bytesfrom192.168.1.3:icmp_seq=2ttl=128time=45.2ms64bytesfrom192.168.1.3:icmp_seq=3ttl=128time=69.1ms64bytesfrom192.168.1.3:icmp_seq=4ttl=128time=94.0ms64bytesfrom192.168.1.3:icmp_seq=5ttl=128time=20.5ms64bytesfrom192.168.1.3:icmp_seq=6ttl=128time=7.37ms^C---192.168.1.3pingstatistics---6packetstransmitted,6received,0%packetloss,time5003msrttmin/avg/max/mdev=6.384/40.463/94.047/32.588ms

ThepingcommandsendssmallpacketstotheIPaddressoftheESP8266.WhentheESPreceivessuchapacket,itsendsitbacktothesender.PingispartofthesecondlayeroftheTCP/IPstack,theInternetlayer.ItreliesonboththeDataLinklayer(Wi-Fi)andtheInternetProtocol*.Youcanseethatintheexampleabove,wesent6packetstotheESP,andwealsoreceived6response(echo)packets.ThistellsusthattheDataLink,theWi-Ficonnection,andtheInternetProtocolareworkingcorrectly.

WenowknowthattheESPcansuccessfullycommunicatewithotherdevicesonthenetwork,andifyourlocalnetworkisonline(ifitisconnectedtotheInternetviayourmodem),theESPcanalsocommunicatewithanydeviceontheweb!

PingisagreattooltocheckiftheESP(oranydevice,really)isstillconnectedtothenetwork,andifit'sstillworkingfine.OnedrawbackisthatIPaddressescanchangeovertime,butthat'saproblemwe'lladdressinoneofthefollowingchapters...

(*)I'msimplifyingthingsabithere.Actually,pingispartoftheInternetControlMessageProtocol(ICMP),that'salsopartofthesecondlayer,justliketheInternetProtocol.Don'tworrytoomuchaboutit,justrememberthatifyoucansendpingpacketstoadevice,youcanalsosendIPpackets.

Page 19: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

Thedevicewiththeantennaservesmanydifferentpurposes:

Accesspoint:OtherWi-Fidevicescanconnecttoit,tobepartofthelocalnetwork.Router:ItroutesIPpacketstotherightsub-netssothattheywillarriveattheirdestination.E.g.ifthecomputersendsamessagethatismeantfortheESPovertheEthernetsub-net,therouterwillsendthepackettotheWi-Fisub-net,becauseitknowsthat'swheretheESPis.Modem:iftheroutercan'tfindtheaddresseeonthelocalnetwork,thepacketwillbepassedontotheintegratedmodem,anditwillbesenttotheInternetServiceProvideroveraDSLline,headingfortheInternet,wherelotsofotherrouterswilltrytogetthepackettotherightdestination.

Butinreality,youdon'thavetoworrytoomuchaboutit,becauseit'salldoneforyou,inafractionofasecondwithoutyouevennoticingit!

Automaticallyconnecttothestrongestnetwork

Thesketchabovemightbeenoughforyourspecificapplication,butifyouneedtobeabletoconnecttomultipleWi-Finetworks,forexampletheWi-FiathomeandtheWi-Fiattheoffice,itwon'twork.Tosolvethisproblem,we'llusetheWi-Fi-Multilibrary:Youcanaddasmanynetworksasyoulike,anditautomaticallyconnectstotheonewiththestrongestsignal.

#include<ESP8266WiFi.h>//IncludetheWi-Filibrary#include<ESP8266WiFiMulti.h>//IncludetheWi-Fi-Multilibrary

ESP8266WiFiMultiwifiMulti;//CreateaninstanceoftheESP8266WiFiMulticlass,called'wifiMulti'

voidsetup(){Serial.begin(115200);//StarttheSerialcommunicationtosendmessagestothecomputerdelay(10);Serial.println('\n');

wifiMulti.addAP("ssid_from_AP_1","your_password_for_AP_1");//addWi-FinetworksyouwanttoconnecttowifiMulti.addAP("ssid_from_AP_2","your_password_for_AP_2");wifiMulti.addAP("ssid_from_AP_3","your_password_for_AP_3");

Serial.println("Connecting...");inti=0;while(wifiMulti.run()!=WL_CONNECTED){//WaitfortheWi-Fitoconnect:scanforWi-Finetworks,andconnecttothestrongestofthenetworksabovedelay(1000);Serial.print('.');}Serial.println('\n');Serial.print("Connectedto");Serial.println(WiFi.SSID());//Telluswhatnetworkwe'reconnectedtoSerial.print("IPaddress:\t");Serial.println(WiFi.localIP());//SendtheIPaddressoftheESP8266tothecomputer}

voidloop(){}

AccessPointmode

Page 20: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

ToconfiguretheESP8266asanaccesspoint,toallowotherdeviceslikesmartphonesorlaptopstoconnecttoit,youcanusethesoftAPfunction:

#include<ESP8266WiFi.h>//IncludetheWi-Filibrary

constchar*ssid="ESP8266AccessPoint";//ThenameoftheWi-Finetworkthatwillbecreatedconstchar*password="thereisnospoon";//Thepasswordrequiredtoconnecttoit,leaveblankforanopennetwork

voidsetup(){Serial.begin(115200);delay(10);Serial.println('\n');

WiFi.softAP(ssid,password);//StarttheaccesspointSerial.print("AccessPoint\"");Serial.print(ssid);Serial.println("\"started");

Serial.print("IPaddress:\t");Serial.println(WiFi.softAPIP());//SendtheIPaddressoftheESP8266tothecomputer}

voidloop(){}

Toseeifitworks,opentheWi-Fisettingsonyourcomputer,lookforanetworkcalled"ESP8266AccessPoint",enterthepassword"thereisnospoon",andconnecttoit.Thenopenaterminal,andpingto192.168.4.1(thisisthedefaultIPaddressofourESPAP).You'llseethattheESPrespondstoyourpings.

However,ifyoutrytogotoanonlinewebsite,you'llgetatimeoutoraDNSerror.ThisisbecausetheESPitselfisnotconnectedtotheinternet.Thesub-netthatconsistsoftheESPandthecomputerisnotconnectedtoanyothernetworks,sothere'snowayforapacketonthisnetworktomakeittotheInternet.

IfyouconnectedasecondstationtotheESPaccesspointontheotherhand,youwouldbeabletopingfromonestationtotheotherwithoutproblems,becausethey'reonthesamenetwork.

Page 21: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

MulticastDomainNameSystemDNS

Let'sfaceit,constantlytypingIPaddressesisreallycumbersome,anditwouldbeimpossibletorememberallyourfavoritewebsites'addresses,especiallyiftheyuseIPv6.That'swhydomainnameswereintroduced:asimplestringoftextthat'seasytoremember,forexamplewww.google.com.

However,tosendarequesttoawebsite,yourcomputerstillneedstoknowitsIPaddress.That'swhereDNScomesin.ItstandsforDomainNameSystem,andisawaytotranslateawebsite'sdomainnametoitsIPaddress.OntheInternet,therearealotofDNSservers.EachDNSserverhasalonglistofdomainnamesandtheircorrespondingIPaddresses.DevicescanconnecttoaDNSserverandsendadomainname,theDNSserverwillthenrespondwiththeIPaddressoftherequestedsite.Youcouldcompareittoatelephonedirectory:youcanlookupanametofindthecorrespondingphonenumber.

TheDNSlookuphappenscompletelyinthebackground:whenyougotoawebsiteinyourbrowser,itwillfirstsendarequesttoaDNSserver(thisimpliesthatthecomputerknowstheIPaddressoftheDNSserveritself),waitfortheresponseofthelookup,andthensendtheactualrequesttotherightIPaddress.

mDNS

DNSworksgreatfornormalsitesontheInternet,butmostlocalnetworksdon'thavetheirownDNSserver.Thismeansthatyoucan'treachlocaldevicesusingadomainname,andyou'restuckusingIPaddresses...

Fortunately,there'sanotherway:multicastDNS,ormDNS.mDNSusesdomainnameswiththe.localsuffix,forexamplehttp://esp8266.local.Ifyourcomputerneedstosendarequesttoadomainnamethatendsin.local,itwillsendamulticastquerytoallotherdevicesontheLANthatsupportmDNS,askingthedevicewiththatspecificdomainnametoidentifyitself.ThedevicewiththerightnamewillthenrespondwithanothermulticastandsenditsIPaddress.NowthatyourcomputerknowstheIPaddressofthedevice,itcansendnormalrequests.

Luckilyforus,theESP8266ArduinoCoresupportsmDNS:

#include<ESP8266WiFi.h>//IncludetheWi-Filibrary#include<ESP8266WiFiMulti.h>//IncludetheWi-Fi-Multilibrary#include<ESP8266mDNS.h>//IncludethemDNSlibrary

ESP8266WiFiMultiwifiMulti;//CreateaninstanceoftheESP8266WiFiMulticlass,called'wifiMulti'

voidsetup(){Serial.begin(115200);//StarttheSerialcommunicationtosendmessagestothecomputerdelay(10);Serial.println('\n');

wifiMulti.addAP("ssid_from_AP_1","your_password_for_AP_1");//addWi-FinetworksyouwanttoconnecttowifiMulti.addAP("ssid_from_AP_2","your_password_for_AP_2");wifiMulti.addAP("ssid_from_AP_3","your_password_for_AP_3");

Serial.println("Connecting...");inti=0;while(wifiMulti.run()!=WL_CONNECTED){//WaitfortheWi-Fitoconnect:scanforWi-Finetworks,andconnecttothestrongestofthenetworksabovedelay(1000);Serial.print(++i);Serial.print('');}Serial.println('\n');Serial.print("Connectedto");Serial.println(WiFi.SSID());//Telluswhatnetworkwe'reconnectedtoSerial.print("IPaddress:\t");Serial.println(WiFi.localIP());//SendtheIPaddressoftheESP8266tothecomputer

if(!MDNS.begin("esp8266")){//StartthemDNSresponderforesp8266.localSerial.println("ErrorsettingupMDNSresponder!");}Serial.println("mDNSresponderstarted");}

voidloop(){}

Uploaditandopenpingagain.Trytopingtoesp8266.local:

user@computername:~$ pingesp8266.localPINGesp8266.local(10.92.237.128)56(84)bytesofdata.64bytesfrom10.92.237.128:icmp_seq=1ttl=128time=5.68ms64bytesfrom10.92.237.128:icmp_seq=2ttl=128time=3.41ms64bytesfrom10.92.237.128:icmp_seq=3ttl=128time=2.55ms64bytesfrom10.92.237.128:icmp_seq=4ttl=128time=2.19ms64bytesfrom10.92.237.128:icmp_seq=5ttl=128time=2.29ms64bytesfrom10.92.237.128:icmp_seq=6ttl=128time=2.74ms^C---esp8266.localpingstatistics---6packetstransmitted,6received,0%packetloss,time5007msrttmin/avg/max/mdev=2.190/3.148/5.687/1.202ms

Asyoucansee,pingwillautomaticallyfindtheIPaddressoftheESPforyou.

mDNSissupportedonWindows,OSX,LinuxandiOS,butnot(yet?)onAndroid.It'sarealshamethatAndroiddoesn'tsupportit,youcanhelpbystarringthisissuereportfortheChromiumprojecttoaskformDNSsupportinChromeonAndroid.

Ofcourse,youcanchangethedomainnameoftheESPbychangingtheparameterofMDNS.begin.

Page 22: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to
Page 23: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

ESP8266WebServerBeingabletopingtheESPisquiteanachievementifyoulookatitfromatechnicalpointofview,butformostpeople,it'snotthatexciting,andnotreallyuseful.Inthischapter,I'llcoverthebasicsofawebserver,andteachyouhowtohostawebpageontheESP.

WebserversAwebserverisanInternet-connecteddevicethatstoresandservesfiles.Clientscanrequestsuchafileoranotherpieceofdata,andtheserverwillthensendtherightdata/filesbacktotheclient.RequestsaremadeusingHTTP.

HTTP

HTTPortheHypertextTransferProtocolisthetext-basedprotocolusedtocommunicatewith(web)servers.TherearemultipleHTTPrequestmethods,butI'llonlycoverthetwomostwidelyusedones:GETandPOST.

HTTPGET

GETrequestsareusedtoretrievedatafromaserver,awebpageforinstance.Itshouldn'tchangeanythingontheserver,itjustgetsthedatafromtheserver,withoutsideeffects.

Whenyouopenawebpageinyourbrowser,itwilltaketheURLandputitinanHTTPGETrequest.Thisisjustplaintext.ThenitwillsendtherequesttotherightserverusingTCP.Theserverwillreadtherequest,checktheURL,andsendtherightHTTPresponseforthatURLbacktothebrowser.

TheanatomyofaGETrequest

ThemostimportantpartsofaGETrequestaretherequestlineandthehostheader.Let'stakealookatanexample:Ifyouclickthefollowinglink:https://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html,yourbrowserwillsendoutthefollowingHTTPrequest:

GET/Protocols/rfc2616/rfc2616-sec5.htmlHTTP/1.1Host:www.w3.orgConnection:keep-alivePragma:no-cacheCache-Control:no-cacheUpgrade-Insecure-Requests:1User-Agent:Mozilla/5.0(X11;Linuxx86_64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/56.0.2924.87Safari/537.36Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8DNT:1Referer:https://www.google.be/Accept-Encoding:gzip,deflate,sdch,brAccept-Language:en-US,en;q=0.8

Thefirstlineistherequestline:itcontainstherequestmethod:GET,inthiscase,theURIorUniformResourceIdentifier:/Protocols/rfc2616/rfc2616-sec5.html,andtheHTTPversion:1.1.Thesecondlineisthehostheader,itspecifiesthedomainnameofthehost(server).Therearemanyotherheadersaswell,butthey'renotreallyimportantwhenusinganESP8266.MostserverswillcheckiftheURIisafileontheirfilesystem,andifthat'sthecase,they'llsendthatfileasaresponse.

ViewingHTTPheadersinthebrowser

Ifyouwanttochecktheheadersyourbrowsersends,youcanpressF12,gotothenetworktab,reloadthepage,andclicktherequestyouwanttoinspect.Ifyouwant,youcanclick'viewsource',thiswillshowyoutheactualHTTPtext.Here'swhatthatlookslikeinChrome:

Page 24: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

Sendingextrainformationtotheserver

Sometimes,youmightwanttoaddextrainformationtotheGETrequest.Youcansendkey-valuepairsbyaddingaquestionmark(?)totheURI,followedbykey=value.Multiplepairsareseparatedbyanampersand(&).Forexample:

GET/get-phone-number.php?firstName=John&lastName=DoeHTTP/1.1Host:www.phonebook.example.com...

Ifyouuseanyspecialcharactersinthekeyorvaluenames,youhavetoURL-encodethem.

HTTPPOST

POSTrequestsareusedtosenddatatotheserver,forexample,tosendyourusernameandpasswordtotheserverwhenyoulogin,orwhenyouuploadaphoto.UnlikeGET,POSTcanchangethedataontheserverorthestateoftheserver.POSThasabodythatcancontaindatathatissenttotheserver.

TheanatomyofaPOSTrequest

Forexample,theloginpageofyourfavoritesitemightsendsomethinglikethiswhenyouenteryourcredentialsandclicktheloginbutton:

POST/login.phpHTTP/1.1Host:www.example.comConnection:keep-aliveContent-Length:480Origin:http://www.example.comContent-Type:multipart/form-data;boundary=----WebKitFormBoundaryQNEJOasMvgAOg8Kt...

Asyoucansee,therequestlinenowhasthePOSTmethodinit,andisstillfollowedbyaURI,/login.php,andtheHTTPversion,1.1.Thehostheaderstillcontainsjustthedomainname.

Therealdifferenceistherequestbody:aGETrequesthasnopayload,whileyoucanaddalotofdatatothebodyofaPOSTrequest.Thisdatacouldbenormalkey-valuepairs,likeausernameandapassword,oractualfilesthatarebeinguploaded.AlsonotetheContent-Typeheader:ittellstheserverwhatkindofdatacanbefoundinthebodyofthePOSTrequest.

Let'stakealookatthebodyoftheloginexample:

------WebKitFormBoundaryQNEJOasMvgAOg8KtContent-Disposition:form-data;name="username"

JohnDoe------WebKitFormBoundaryQNEJOasMvgAOg8KtContent-Disposition:form-data;name="password"

p@ssw0rd123------WebKitFormBoundaryQNEJOasMvgAOg8KtContent-Disposition:form-data;name="token"

9i9ZoLHl5pkRAeuKCEu76TbaCnMphwYkPEovEUY9PHk=------WebKitFormBoundaryQNEJOasMvgAOg8Kt--

Asyoucansee,therearethreeparametersinsidethebody,everyparameterhasaname(e.g.username),andavalue(e.g.JohnDoe).

YoucouldalsousethesamesyntaxweusedbeforewhenaddingparameterstoaGETrequest:

Page 25: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

POST/add-user.phpHTTP/1.1Host:www.example.comContent-Length:27Content-Type:application/x-www-form-urlencoded...

Andthepayload:

firstName=John&lastName=Doe

Asyoucansee,theContent-Typeheaderisdifferent,indicatingthattheencodingofthevaluesinthepayloadisdifferent.

HTTPstatuscodesAservershouldanswerallrequestswithanHTTPstatuscode.Thisisa3-digitnumberindicatingiftherequestwassuccessfulortellingtheclientwhatwentwrong.Here'satablewithsomeofthemostimportantandusefulones.StatusCode Meaning200 OK:therequestwassuccessful303 SeeOther:usedtoredirecttoadifferentURI,afteraPOSTrequest,forinstance400 BadRequest:theservercouldn'tunderstandtherequest,becausethesyntaxwasincorrect401 Unauthorized:userauthenticationisrequired403 Forbidden:theserverrefusestoexecutetherequest,authorizationwon'thelp404 NotFound:therequestedURIwasnotfound500 InternalServerError:Theserverencounteredanunexpectedconditionandcouldn'tfulfilltherequest

TCP&UDPPorts

Inmostcases,onedevicehasmanydifferentservices,forexample,awebserver,anemailserver,anFTPserver,aSpotifystreamingservice,...IfthedevicehadjustanIPaddress,itwouldbeimpossibletoknowwhichapplicationapacketwassentto.That'swhyeveryservicehasaportnumber.It'sanidentifierforalldifferentservicesorapplicationsonasingledevice.Intheexampleabove,thewebserverwillonlylistenforrequestsonport80,theemailserveronlyonport25,theFTPserveronlyonport20,Spotifywillonlyreceivestreamsonport4371...Tospecifyacertainport,youcanuseacolonaftertheIPaddressofafterthedomainname.Butmostofthetime,youdon'thavetoadditexplicitly.Forexample,allwebserverslistenonport80,soawebbrowserwillalwaysconnecttoport80.

http://stackoverflow.com/questions/176264/what-is-the-difference-between-a-uri-a-url-and-a-urnhttps://www.w3.org/Protocols/rfc2616/rfc2616-sec10.htmlhttps://en.wikipedia.org/wiki/List_of_HTTP_status_codes

Page 26: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

ESP8266FirstWebServerTheactualimplementationofawebserverismucheasierthanitsounds,becausetheESP8266ArduinoCoreincludessomegreatlibrariesthathandleprettymucheverythingforyou.Let'slookatabasicHelloWorld!example.

#include<ESP8266WiFi.h>#include<WiFiClient.h>#include<ESP8266WiFiMulti.h>#include<ESP8266mDNS.h>#include<ESP8266WebServer.h>//IncludetheWebServerlibrary

ESP8266WiFiMultiwifiMulti;//CreateaninstanceoftheESP8266WiFiMulticlass,called'wifiMulti'

ESP8266WebServerserver(80);//CreateawebserverobjectthatlistensforHTTPrequestonport80

voidhandleRoot();//functionprototypesforHTTPhandlersvoidhandleNotFound();

voidsetup(void){Serial.begin(115200);//StarttheSerialcommunicationtosendmessagestothecomputerdelay(10);Serial.println('\n');

wifiMulti.addAP("ssid_from_AP_1","your_password_for_AP_1");//addWi-FinetworksyouwanttoconnecttowifiMulti.addAP("ssid_from_AP_2","your_password_for_AP_2");wifiMulti.addAP("ssid_from_AP_3","your_password_for_AP_3");

Serial.println("Connecting...");inti=0;while(wifiMulti.run()!=WL_CONNECTED){//WaitfortheWi-Fitoconnect:scanforWi-Finetworks,andconnecttothestrongestofthenetworksabovedelay(250);Serial.print('.');}Serial.println('\n');Serial.print("Connectedto");Serial.println(WiFi.SSID());//Telluswhatnetworkwe'reconnectedtoSerial.print("IPaddress:\t");Serial.println(WiFi.localIP());//SendtheIPaddressoftheESP8266tothecomputer

if(MDNS.begin("esp8266")){//StartthemDNSresponderforesp8266.localSerial.println("mDNSresponderstarted");}else{Serial.println("ErrorsettingupMDNSresponder!");}

server.on("/",handleRoot);//Callthe'handleRoot'functionwhenaclientrequestsURI"/"server.onNotFound(handleNotFound);//WhenaclientrequestsanunknownURI(i.e.somethingotherthan"/"),callfunction"handleNotFound"

server.begin();//ActuallystarttheserverSerial.println("HTTPserverstarted");}

voidloop(void){server.handleClient();//ListenforHTTPrequestsfromclients}

voidhandleRoot(){server.send(200,"text/plain","Helloworld!");//SendHTTPstatus200(Ok)andsendsometexttothebrowser/client}

voidhandleNotFound(){server.send(404,"text/plain","404:Notfound");//SendHTTPstatus404(NotFound)whenthere'snohandlerfortheURIintherequest}

There'salotofcodethat'sthesameasintheWi-FiandmDNSexamples.Theactualservercodeisprettystraightforward.First,wecreateaserverinstancethatlistensforHTTPrequestsonport80.Thisisthedefaultportforwebservers.Inthesetup,wetelltheserverwhattodowithcertainHTTPrequests.IftheURI'/'isrequested,theservershouldreplywithaHTTPstatuscodeof200(Ok)andthensendaresponsewiththewords'Helloworld!'.Weputthecodeforgeneratingaresponseinaseparatefunction,andthewetelltheservertoexecuteitwhen'/'isrequested,usingtheserver.onfunction.

Wehaven'tspecifiedwhattheservershoulddoiftheclientrequestsanyURIotherthan'/'.ItshouldrespondwithanHTTPstatus404(NotFound)andamessagefortheuser.Weputthisinafunctionaswell,anduseserver.onNotFoundtotellitthatitshouldexecuteitwhenitreceivesarequestforaURIthatwasn'tspecifiedwithserver.on.

ThenwestartlisteningforHTTPrequestsbyusingserver.begin.Duringtheloop,weconstantlycheckifanewHTTPrequestisreceivedbyrunningserver.handleClient.IfhandleClientdetectsnewrequests,itwillautomaticallyexecutetherightfunctionsthatwespecifiedinthesetup.

Totestitout,uploadthesketch,openanewbrowsertab,andbrowsetohttp://esp8266.local.YoushouldgetawebpagesayingHelloworld!.Ifyoutrytogotoadifferentpage,http://esp8266.local/test,forinstance,youshouldgeta404error:404:Notfound.

TurningonandoffanLEDoverWi-FiWecanusethewebservertoserveinteractivepages,andtoreacttocertainPOSTrequest.Inthefollowingexample,theESP8266hostsawebpagewithabutton.Whenthebuttonispressed,thebrowsersendsaPOSTrequestto/LED.WhentheESPreceivessuchaPOSTrequestonthe/LEDURI,itwillturnonorofftheLED,andthenredirectthebrowserbacktothehomepagewiththebutton.

Inordertoperformthisredirect,theESPhastoaddaLocationheadertotheresponse,andusea303(SeeOther)HTTPstatuscode.

ThebuttontosendthePOSTrequestinthebrowserispartofanHTMLform.YouhavetospecifythetargetURItosendtherequestto,andtherequestmethod,inthiscasethisis"/LED"andPOSTrespectively.

NotethatIchangedthecontenttypeoftheresponsefrom"text/plain"to"text/html".Ifyousenditasplaintext,thebrowserwill

Page 27: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

displayitastextinsteadofinterpretingitasHTMLandshowingitasabutton.

#include<ESP8266WiFi.h>#include<WiFiClient.h>#include<ESP8266WiFiMulti.h>#include<ESP8266mDNS.h>#include<ESP8266WebServer.h>

ESP8266WiFiMultiwifiMulti;//CreateaninstanceoftheESP8266WiFiMulticlass,called'wifiMulti'

ESP8266WebServerserver(80);//CreateawebserverobjectthatlistensforHTTPrequestonport80

constintled=2;

voidhandleRoot();//functionprototypesforHTTPhandlersvoidhandleLED();voidhandleNotFound();

voidsetup(void){Serial.begin(115200);//StarttheSerialcommunicationtosendmessagestothecomputerdelay(10);Serial.println('\n');

pinMode(led,OUTPUT);

wifiMulti.addAP("ssid_from_AP_1","your_password_for_AP_1");//addWi-FinetworksyouwanttoconnecttowifiMulti.addAP("ssid_from_AP_2","your_password_for_AP_2");wifiMulti.addAP("ssid_from_AP_3","your_password_for_AP_3");

Serial.println("Connecting...");inti=0;while(wifiMulti.run()!=WL_CONNECTED){//WaitfortheWi-Fitoconnect:scanforWi-Finetworks,andconnecttothestrongestofthenetworksabovedelay(250);Serial.print('.');}Serial.println('\n');Serial.print("Connectedto");Serial.println(WiFi.SSID());//Telluswhatnetworkwe'reconnectedtoSerial.print("IPaddress:\t");Serial.println(WiFi.localIP());//SendtheIPaddressoftheESP8266tothecomputer

if(MDNS.begin("esp8266")){//StartthemDNSresponderforesp8266.localSerial.println("mDNSresponderstarted");}else{Serial.println("ErrorsettingupMDNSresponder!");}

server.on("/",HTTP_GET,handleRoot);//Callthe'handleRoot'functionwhenaclientrequestsURI"/"server.on("/LED",HTTP_POST,handleLED);//Callthe'handleLED'functionwhenaPOSTrequestismadetoURI"/LED"server.onNotFound(handleNotFound);//WhenaclientrequestsanunknownURI(i.e.somethingotherthan"/"),callfunction"handleNotFound"

server.begin();//ActuallystarttheserverSerial.println("HTTPserverstarted");}

voidloop(void){server.handleClient();//ListenforHTTPrequestsfromclients}

voidhandleRoot(){//WhenURI/isrequested,sendawebpagewithabuttontotoggletheLEDserver.send(200,"text/html","<formaction=\"/LED\"method=\"POST\"><inputtype=\"submit\"value=\"ToggleLED\"></form>");}

voidhandleLED(){//IfaPOSTrequestismadetoURI/LEDdigitalWrite(led,!digitalRead(led));//ChangethestateoftheLEDserver.sendHeader("Location","/");//Addaheadertorespondwithanewlocationforthebrowsertogotothehomepageagainserver.send(303);//SenditbacktothebrowserwithanHTTPstatus303(SeeOther)toredirect}

voidhandleNotFound(){server.send(404,"text/plain","404:Notfound");//SendHTTPstatus404(NotFound)whenthere'snohandlerfortheURIintherequest}

Asyoucansee,theserver.onfunctionnowtakesthreeparameters:theURI,therequestmethod(GETorPOST)andthefunctiontoexecute.

ConnectanLEDtoGPIO2,anduploadthesketch.Thengotohttp://esp8266.local/andclickthebuttontoturntheLEDonoroff.

YoucanopenthedeveloperoptionsinChrome(F12)tochecktheHTTPrequestthataremadewhenyouclickthebutton:you'llseethatitfirstsendaPOSTrequest,andthenreceivesa303(SeeOther)HTTPstatusasaresponse.TheresponsealsohasaLocationheadercontainingtheURI"/",sothebrowserwillsendaGETrequesttotheURIofthisnewlocation:

Page 28: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

Ifyoucheckthepagesource(CTRL+U),youcanseethesimpleHTMLformthat'sused:

<formaction="/LED"method="POST"><inputtype="submit"value="ToggleLED"></form>

SendingdatatotheESPusingHTTPPOSTInthepreviousexample,wesentanemptyPOSTrequesttotheESP8266.Inthepreviouschapterhowever,Iexplainedthatit'spossibletosendallkindsofdatainthebodyofthePOSTrequest.

Inthisexample,I'llshowyouhowtosendausernameandapasswordtotheESP.TheESPwillthencheckiftheyarecorrect,andrespondtotherequestwiththeappropriatepage.

#include<ESP8266WiFi.h>#include<WiFiClient.h>#include<ESP8266WiFiMulti.h>#include<ESP8266mDNS.h>#include<ESP8266WebServer.h>

ESP8266WiFiMultiwifiMulti;//CreateaninstanceoftheESP8266WiFiMulticlass,called'wifiMulti'

ESP8266WebServerserver(80);//CreateawebserverobjectthatlistensforHTTPrequestonport80

voidhandleRoot();//functionprototypesforHTTPhandlersvoidhandleLogin();voidhandleNotFound();

voidsetup(void){Serial.begin(115200);//StarttheSerialcommunicationtosendmessagestothecomputerdelay(10);Serial.println('\n');

wifiMulti.addAP("ssid_from_AP_1","your_password_for_AP_1");//addWi-FinetworksyouwanttoconnecttowifiMulti.addAP("ssid_from_AP_2","your_password_for_AP_2");wifiMulti.addAP("ssid_from_AP_3","your_password_for_AP_3");

Serial.println("Connecting...");inti=0;while(wifiMulti.run()!=WL_CONNECTED){//WaitfortheWi-Fitoconnect:scanforWi-Finetworks,andconnecttothestrongestofthenetworksabovedelay(250);Serial.print('.');}Serial.println('\n');Serial.print("Connectedto");Serial.println(WiFi.SSID());//Telluswhatnetworkwe'reconnectedtoSerial.print("IPaddress:\t");

Page 29: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

Serial.println(WiFi.localIP());//SendtheIPaddressoftheESP8266tothecomputer

if(MDNS.begin("esp8266")){//StartthemDNSresponderforesp8266.localSerial.println("mDNSresponderstarted");}else{Serial.println("ErrorsettingupMDNSresponder!");}

server.on("/",HTTP_GET,handleRoot);//Callthe'handleRoot'functionwhenaclientrequestsURI"/"server.on("/login",HTTP_POST,handleLogin);//Callthe'handleLogin'functionwhenaPOSTrequestismadetoURI"/login"server.onNotFound(handleNotFound);//WhenaclientrequestsanunknownURI(i.e.somethingotherthan"/"),callfunction"handleNotFound"

server.begin();//ActuallystarttheserverSerial.println("HTTPserverstarted");}

voidloop(void){server.handleClient();//ListenforHTTPrequestsfromclients}

voidhandleRoot(){//WhenURI/isrequested,sendawebpagewithabuttontotoggletheLEDserver.send(200,"text/html","<formaction=\"/login\"method=\"POST\"><inputtype=\"text\"name=\"username\"placeholder=\"Username\"></br><inputtype=\"password\"name=\"password\"placeholder=\"Password\"></br><inputtype=\"submit\"value=\"Login\"></form><p>Try'JohnDoe'and'password123'...</p>");}

voidhandleLogin(){//IfaPOSTrequestismadetoURI/loginif(!server.hasArg("username")||!server.hasArg("password")||server.arg("username")==NULL||server.arg("password")==NULL){//IfthePOSTrequestdoesn'thaveusernameandpassworddataserver.send(400,"text/plain","400:InvalidRequest");//Therequestisinvalid,sosendHTTPstatus400return;}if(server.arg("username")=="JohnDoe"&&server.arg("password")=="password123"){//Ifboththeusernameandthepasswordarecorrectserver.send(200,"text/html","<h1>Welcome,"+server.arg("username")+"!</h1><p>Loginsuccessful</p>");}else{//Usernameandpassworddon'tmatchserver.send(401,"text/plain","401:Unauthorized");}}

voidhandleNotFound(){server.send(404,"text/plain","404:Notfound");//SendHTTPstatus404(NotFound)whenthere'snohandlerfortheURIintherequest}

TheHTMLinhandleRootis:

<formaction="/login"method="POST"><inputtype="text"name="username"placeholder="Username"></br><inputtype="password"name="password"placeholder="Password"></br><inputtype="submit"value="Login"></form><p>Try'JohnDoe'and'password123'...</p>

Uploadthesketchandgotohttp://esp8266.local/,thentype'JohnDoe'intotheusernamefield,and'password123'intothepasswordfield,andclick'Login'.Youshouldgetawelcomescreen.Ifyouleaveonorbothofthefieldsblank,youshouldgeta400(BadRequest)error.Ifyouenterawrongusernameorpassword,youshouldgeta401(Unauthorized)error.

ThedataofthePOSTbodycanbeaccessedusingserver.arg("key"),andyoucancheckifaspecifickeyexistsusingserver.hasArg("key").ThekeynameontheESP8266correspondstothenameargumentintheHTMLformonthewebpage.

WhenwegetaPOSTrequest,wefirstcheckifthenecessaryarguments(usernameandpassword)arepresent.Ifthat'snotthecase,wesenda400(InvalidRequest)status.Thenwecheckifthecredentialsmatch'JohnDoe'&'password123'.Ifthat'sthecase,werespondwithastatus200(Ok)andawelcomepage.Iftheusernameand/orpassworddoesn'tmatch,wesenda401(Unauthorized)status.

InlinefunctionsInthepreviousexamples,wepassedhandleRootandhandleNotFoundtotheserver.onfunctionasaparameter(callbackfunction).Insomecaseshowever,it'smorereadabletojustwritethedefinitionofthefunctioninline,likeso:

voidsetup(){//...server.onNotFound([](){server.send(404,"text/plain","404:Notfound");});}

Page 30: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

SPIFlashFileSystemUpuntilnow,we'vealwaysincludedtheHTMLforourwebpagesasstringliteralsinoursketch.Thismakesourcodeveryhardtoread,andyou'llrunoutofmemoryratherquickly.Ifyouremembertheintroduction,ImentionedtheSerialPeripheralInterfaceFlashFileSystem,orSPIFFSforshort.It'salight-weightfilesystemformicrocontrollerswithanSPIflashchip.Theon-boardflashchipoftheESP8266hasplentyofspaceforyourwebpages,especiallyifyouhavethe1MB,2MBor4MBversion.

SPIFFSlet'syouaccesstheflashmemoryasifitwasanormalfilesystemliketheoneonyourcomputer(butmuchsimplerofcourse):youcanreadandwritefiles,createfolders...

TheeasiestwaytolearnhowtouseSPIFFSistolookatsomeexamples.Butafileserverwithnofilestoserveisprettypointless,soI'llexplainhowtouploadfilestotheSPIFFSfirst.

UploadingfilestoSPIFFSToselecttherightfilestoupload,youhavetoplacetheminafoldercalleddata,insidethesketchfolderofyourproject:OpenyoursketchintheArduinoIDE,andhitCTRL+K.Waitforafileexplorerwindowtoopen,andcreateanewfoldernameddata.Copyyourfilesovertothisfolder.(Onlyusesmallfilesliketextfilesoricons.There'snotenoughspaceforlargephotosorvideos.)Next,selectallfilesinthefolder(CTRL+A)andcheckthesizeofallfilescombined(don'tforgetsubfolders).GototheArduinoIDEagain,andunderTools>FlashSize,selectanoptionwiththerightflashsizeforyourboard,andaSPIFFSsizethatislargerthanthesizeofyourdatafolder.Thenuploadthesketch.Whenthat'sfinished,makesurethattheSerialMonitorisclosed,thenopentheToolsmenu,andclickESP8266sketchdataupload.IfyourESPhasauto-resetandauto-program,itshouldworkautomatically,ifyoudon'thaveauto-program,youhavetomanuallyenterprogrammodebeforeuploadingthedatatoSPIFFS.Theprocedureisexactlythesameasenteringprogrammodebeforeuploadingasketch.

IfyougetanerrorsayingSPIFFS_writeerror(-10001):Filesystemisfull,thismeansthatyourfilesaretoolargetofitintotheSPIFFSmemory.SelectalargerSPIFFSsizeunderTools>FlashSize,ordeletesomefiles.EvenifyourcomputersaysthatthefilesaresmallerthantheselectedSPIFFSsize,youcanstillgetthiserror:thishastodowithblocksizes,andmetadatalikefileandfoldernamesthattakeupspaceaswell.

IfyouchangetheSPIFFSsize,youhavetoreuploadyoursketch,becausewhenyouchangetheSPIFFSsize,thememorylocationwillbedifferent.TheprogramhastoknowtheupdatedSPIFFSaddressoffsettobeabletoreadthefiles.

SPIFFSFileServer

Thefollowingexampleisaverybasicfileserver:itjusttakestheURIoftheHTTPrequest,checksiftheURIpointstoafileintheSPIFFS,andifitfindsthefile,itsendsitasaresponse.

#include<ESP8266WiFi.h>#include<WiFiClient.h>#include<ESP8266WiFiMulti.h>#include<ESP8266mDNS.h>#include<ESP8266WebServer.h>#include<FS.h>//IncludetheSPIFFSlibrary

ESP8266WiFiMultiwifiMulti;//CreateaninstanceoftheESP8266WiFiMulticlass,called'wifiMulti'

ESP8266WebServerserver(80);//CreateawebserverobjectthatlistensforHTTPrequestonport80

StringgetContentType(Stringfilename);//convertthefileextensiontotheMIMEtypeboolhandleFileRead(Stringpath);//sendtherightfiletotheclient(ifitexists)

voidsetup(){Serial.begin(115200);//StarttheSerialcommunicationtosendmessagestothecomputerdelay(10);Serial.println('\n');

wifiMulti.addAP("ssid_from_AP_1","your_password_for_AP_1");//addWi-FinetworksyouwanttoconnecttowifiMulti.addAP("ssid_from_AP_2","your_password_for_AP_2");wifiMulti.addAP("ssid_from_AP_3","your_password_for_AP_3");

Serial.println("Connecting...");inti=0;while(wifiMulti.run()!=WL_CONNECTED){//WaitfortheWi-Fitoconnectdelay(250);Serial.print('.');}Serial.println('\n');Serial.print("Connectedto");Serial.println(WiFi.SSID());//Telluswhatnetworkwe'reconnectedtoSerial.print("IPaddress:\t");Serial.println(WiFi.localIP());//SendtheIPaddressoftheESP8266tothecomputer

if(MDNS.begin("esp8266")){//StartthemDNSresponderforesp8266.localSerial.println("mDNSresponderstarted");}else{Serial.println("ErrorsettingupMDNSresponder!");}

SPIFFS.begin();//StarttheSPIFlashFilesSystemserver.onNotFound([](){//IftheclientrequestsanyURIif(!handleFileRead(server.uri()))//senditifitexistsserver.send(404,"text/plain","404:NotFound");//otherwise,respondwitha404(NotFound)error});

server.begin();//ActuallystarttheserverSerial.println("HTTPserverstarted");}

voidloop(void){server.handleClient();}

Page 31: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

StringgetContentType(Stringfilename){//convertthefileextensiontotheMIMEtypeif(filename.endsWith(".html"))return"text/html";elseif(filename.endsWith(".css"))return"text/css";elseif(filename.endsWith(".js"))return"application/javascript";elseif(filename.endsWith(".ico"))return"image/x-icon";return"text/plain";}

boolhandleFileRead(Stringpath){//sendtherightfiletotheclient(ifitexists)Serial.println("handleFileRead:"+path);if(path.endsWith("/"))path+="index.html";//Ifafolderisrequested,sendtheindexfileStringcontentType=getContentType(path);//GettheMIMEtypeif(SPIFFS.exists(path)){//IfthefileexistsFilefile=SPIFFS.open(path,"r");//Openitsize_tsent=server.streamFile(file,contentType);//Andsendittotheclientfile.close();//Thenclosethefileagainreturntrue;}Serial.println("\tFileNotFound");returnfalse;//Ifthefiledoesn'texist,returnfalse}

Asyoucansee,wedon'tuseserver.oninthisexample.Instead,weuseserver.onNotFound:thiswillmatchanyURI,sincewedidn'tdeclareanyspecificURIhandlerslikeinthepreviousserverexamples.WhenaURIisrequested,wecallthefunctionhandleFileRead.ThisfunctionchecksiftheURIoftheHTTPrequestisthepathtoanexistingfileintheSPIFFS.Ifthat'sthecase,itsendsthefilebacktotheclient.Ifthepathdoesn'texist,itreturnsfalse,anda404(NotFound)HTTPstatuswillbesent.

TheMIMEtypeforthedifferentfilesisbasedonthefileextension.Youcouldaddotherfiletypesaswell.Forinstance:

StringgetContentType(Stringfilename){if(filename.endsWith(".htm"))return"text/html";elseif(filename.endsWith(".html"))return"text/html";elseif(filename.endsWith(".css"))return"text/css";elseif(filename.endsWith(".js"))return"application/javascript";elseif(filename.endsWith(".png"))return"image/png";elseif(filename.endsWith(".gif"))return"image/gif";elseif(filename.endsWith(".jpg"))return"image/jpeg";elseif(filename.endsWith(".ico"))return"image/x-icon";elseif(filename.endsWith(".xml"))return"text/xml";elseif(filename.endsWith(".pdf"))return"application/x-pdf";elseif(filename.endsWith(".zip"))return"application/x-zip";elseif(filename.endsWith(".gz"))return"application/x-gzip";return"text/plain";}

ThisexampleisadaptedfromtheFSBrowserexamplebyHristoGochkov.

CompressingfilesTheESP8266'sflashmemoryisn'thuge,andmosttextfiles,likehtml,cssetc.canbecompressedbyquitealargefactor.Modernwebbrowsersacceptcompressedfilesasaresponse,sowe'lltakeadvantageofthisbyuploadingcompressedversionsofourhtmlandiconfilestotheSPIFFS,inordertosavespaceandbandwidth.

Todothis,weneedtoaddtheGNUzipfiletypetoourlistofMIMEtypes:

StringgetContentType(Stringfilename){if(filename.endsWith(".html"))return"text/html";elseif(filename.endsWith(".css"))return"text/css";elseif(filename.endsWith(".js"))return"application/javascript";elseif(filename.endsWith(".ico"))return"image/x-icon";elseif(filename.endsWith(".gz"))return"application/x-gzip";return"text/plain";}

AndweneedtochangeourhandleFileReadfunctionaswell:

boolhandleFileRead(Stringpath){//sendtherightfiletotheclient(ifitexists)Serial.println("handleFileRead:"+path);if(path.endsWith("/"))path+="index.html";//Ifafolderisrequested,sendtheindexfileStringcontentType=getContentType(path);//GettheMIMEtypeStringpathWithGz=path+".gz";if(SPIFFS.exists(pathWithGz)||SPIFFS.exists(path)){//Ifthefileexists,eitherasacompressedarchive,ornormalif(SPIFFS.exists(pathWithGz))//Ifthere'sacompressedversionavailablepath+=".gz";//UsethecompressedversionFilefile=SPIFFS.open(path,"r");//Openthefilesize_tsent=server.streamFile(file,contentType);//Sendittotheclientfile.close();//ClosethefileagainSerial.println(String("\tSentfile:")+path);returntrue;}Serial.println(String("\tFileNotFound:")+path);returnfalse;//Ifthefiledoesn'texist,returnfalse}

Now,trycompressingsomeofthefilestotheGNUzipformat(.gz),anduploadingthemtoSPIFFS.Oryoucanjustdownloadthenewdatafolder(unzipitfirst).Everytimeaclientrequestsacertainfile,theESPwillcheckifacompressedversionisavailable.Ifso,itwillusethatinsteadoftheuncompressedfile.TheoutputintheSerialMonitorshouldlooksomethinglikethis:

handleFileRead:/ Sentfile:/index.html.gzhandleFileRead:/main.css Sentfile:/main.csshandleFileRead:/JavaScript.js Sentfile:/JavaScript.jshandleFileRead:/folder/JavaScript.js Sentfile:/folder/JavaScript.jshandleFileRead:/favicon.ico Sentfile:/favicon.ico.gz

Page 32: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

Itautomaticallydetectedthatithadtosendthecompressedversionsofindex.htmlandfavicon.ico.

Page 33: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

UploadingfilestotheserverTherearescenarioswhereyoumaywanttouploadnewfilestotheserverfromwithinabrowser,withouthavingtoconnecttotheESP8266overUSBinordertoflashanewSPIFFSimage.Inthischapter,I'llshowyouhowtouseHTMLformsandPOSTrequeststouploadoreditfilestoourlittleESPserver.

Client:HTMLformTheeasiestwaytouploadfilesisbyusinganHTMLform,justlikeinthefirstserverexamples,whereweusedformstoturnon/offLEDs,andtosendthelogincredentialsbacktotheserver.Ifyouchooseafileinput,youautomaticallygetafilepicker,andthebrowserwillsendtherightPOSTrequesttotheserver,withthefileattached.

<formmethod="post"enctype="multipart/form-data"><inputtype="file"name="name"><inputclass="button"type="submit"value="Upload"></form>

Server

IntheESPcode,wehavetoaddahandlertoourserverthathandlesPOSTrequeststothe/uploadURI.WhenitreceivesaPOSTrequest,itsendsastatus200(OK)backtotheclienttostartreceivingthefile,andthenwriteittotheSPIFFS.Whenthefileisuploadedsuccessfully,itredirectstheclienttoasuccesspage.TherelevantnewcodeisfoundinthesetupandthehandleFileUploadfunction.

#include<ESP8266WiFi.h>#include<WiFiClient.h>#include<ESP8266WiFiMulti.h>#include<ESP8266mDNS.h>#include<ESP8266WebServer.h>#include<FS.h>//IncludetheSPIFFSlibrary

ESP8266WiFiMultiwifiMulti;//CreateaninstanceoftheESP8266WiFiMulticlass,called'wifiMulti'

ESP8266WebServerserver(80);//CreateawebserverobjectthatlistensforHTTPrequestonport80

FilefsUploadFile;//aFileobjecttotemporarilystorethereceivedfile

StringgetContentType(Stringfilename);//convertthefileextensiontotheMIMEtypeboolhandleFileRead(Stringpath);//sendtherightfiletotheclient(ifitexists)voidhandleFileUpload();//uploadanewfiletotheSPIFFS

voidsetup(){Serial.begin(115200);//StarttheSerialcommunicationtosendmessagestothecomputerdelay(10);Serial.println('\n');

wifiMulti.addAP("ssid_from_AP_1","your_password_for_AP_1");//addWi-FinetworksyouwanttoconnecttowifiMulti.addAP("ssid_from_AP_2","your_password_for_AP_2");wifiMulti.addAP("ssid_from_AP_3","your_password_for_AP_3");

Serial.println("Connecting...");inti=0;while(wifiMulti.run()!=WL_CONNECTED){//WaitfortheWi-Fitoconnectdelay(1000);Serial.print(++i);Serial.print('');}Serial.println('\n');Serial.print("Connectedto");Serial.println(WiFi.SSID());//Telluswhatnetworkwe'reconnectedtoSerial.print("IPaddress:\t");Serial.println(WiFi.localIP());//SendtheIPaddressoftheESP8266tothecomputer

if(!MDNS.begin("esp8266")){//StartthemDNSresponderforesp8266.localSerial.println("ErrorsettingupMDNSresponder!");}Serial.println("mDNSresponderstarted");

SPIFFS.begin();//StarttheSPIFlashFilesSystem

server.on("/upload",HTTP_GET,[](){//iftheclientrequeststheuploadpageif(!handleFileRead("/upload.html"))//senditifitexistsserver.send(404,"text/plain","404:NotFound");//otherwise,respondwitha404(NotFound)error});

server.on("/upload",HTTP_POST,//iftheclientpoststotheuploadpage[](){server.send(200);},//Sendstatus200(OK)totelltheclientwearereadytoreceivehandleFileUpload//Receiveandsavethefile);

server.onNotFound([](){//IftheclientrequestsanyURIif(!handleFileRead(server.uri()))//senditifitexistsserver.send(404,"text/plain","404:NotFound");//otherwise,respondwitha404(NotFound)error});

server.begin();//ActuallystarttheserverSerial.println("HTTPserverstarted");}

voidloop(){server.handleClient();}

StringgetContentType(Stringfilename){//convertthefileextensiontotheMIMEtypeif(filename.endsWith(".html"))return"text/html";elseif(filename.endsWith(".css"))return"text/css";elseif(filename.endsWith(".js"))return"application/javascript";elseif(filename.endsWith(".ico"))return"image/x-icon";elseif(filename.endsWith(".gz"))return"application/x-gzip";return"text/plain";}

Page 34: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

boolhandleFileRead(Stringpath){//sendtherightfiletotheclient(ifitexists)Serial.println("handleFileRead:"+path);if(path.endsWith("/"))path+="index.html";//Ifafolderisrequested,sendtheindexfileStringcontentType=getContentType(path);//GettheMIMEtypeStringpathWithGz=path+".gz";if(SPIFFS.exists(pathWithGz)||SPIFFS.exists(path)){//Ifthefileexists,eitherasacompressedarchive,ornormalif(SPIFFS.exists(pathWithGz))//Ifthere'sacompressedversionavailablepath+=".gz";//UsethecompressedverionFilefile=SPIFFS.open(path,"r");//Openthefilesize_tsent=server.streamFile(file,contentType);//Sendittotheclientfile.close();//ClosethefileagainSerial.println(String("\tSentfile:")+path);returntrue;}Serial.println(String("\tFileNotFound:")+path);//Ifthefiledoesn'texist,returnfalsereturnfalse;}

voidhandleFileUpload(){//uploadanewfiletotheSPIFFSHTTPUpload&upload=server.upload();if(upload.status==UPLOAD_FILE_START){Stringfilename=upload.filename;if(!filename.startsWith("/"))filename="/"+filename;Serial.print("handleFileUploadName:");Serial.println(filename);fsUploadFile=SPIFFS.open(filename,"w");//OpenthefileforwritinginSPIFFS(createifitdoesn'texist)filename=String();}elseif(upload.status==UPLOAD_FILE_WRITE){if(fsUploadFile)fsUploadFile.write(upload.buf,upload.currentSize);//Writethereceivedbytestothefile}elseif(upload.status==UPLOAD_FILE_END){if(fsUploadFile){//IfthefilewassuccessfullycreatedfsUploadFile.close();//ClosethefileagainSerial.print("handleFileUploadSize:");Serial.println(upload.totalSize);server.sendHeader("Location","/success.html");//Redirecttheclienttothesuccesspageserver.send(303);}else{server.send(500,"text/plain","500:couldn'tcreatefile");}}}

ThehandleFileUploadfunctionjustwritesthefileattachedtothePOSTrequesttoSPIFFS.

Ifyouwantouseotherfiletypesaswell,youcanjustaddthemtothegetContentTypefunction.

UploadingfilesTouploadanewfiletotheESP,ortoupdateanexistingfile,justgotohttp://esp8266.local/upload,clicktheChooseFilebutton,selectthefileyouwishtoupload,andclickUpload.YoucannowentertheURLintotheURLbar,andopenthenewfile.

Anoteonsafety

Thisexampleisn'tverysecure(obviously).EveryonethatcanconnecttotheESPcanuploadnewfiles,oredittheexistingfilesandinsertXSScode,forexample.There'salsonotalotoferrorchecking/handling,likecheckingifthere'senoughspaceintheSPIFFStouploadanewfile,etc.

AdvancedexampleThecodefortheseSPIFFSserverexamplescomes(forthemostpart)fromanexamplewrittenbyHristoGochkov.YoucanfinditunderFile>Examples>ESP8266WebServer>FSBrowser.Ithasawebinterfaceforbrowsingandeditingfilesinyourbrowser,andhassomeothernicefeaturesaswell.

Page 35: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

OverTheAirUpdatesUploadingoverSerialisfineduringdevelopment,whenyouhaveaccesstotheSerialpinsandtheUSBport.Butonceyourprojectisfinished,andyouputitinsideanenclosure,itnotthateasytouploadupdateswithbugfixesornewfeatures.AsolutiontothisproblemisOverTheAirupdating,orOTAforshort.Asthenameimplies,thistechnologyallowsyoutouploadnewcodeoverWi-Fi,insteadofSerial.Theonlydisadvantageisthatyouhavetoexplicitlyaddthecodeforittoeverysketchyouupload.Youalsoneedaflashchipthatistwicethesizeofyoursketch,soitwon'tworkfor512kBboards.(Ithastodownloadthenewsketchwhilestillrunningtheoldcode.)Let'stakealookatanexample...

BlinkOTAThefollowingexampleisbasicallyBlinkWithoutDelay,butwiththenecessaryOTAandWi-Ficodeaddedaswell.

#include<ESP8266WiFi.h>#include<ESP8266WiFiMulti.h>#include<ArduinoOTA.h>

ESP8266WiFiMultiwifiMulti;//CreateaninstanceoftheESP8266WiFiMulticlass,called'wifiMulti'

constbyteled=13;

voidsetup(){Serial.begin(115200);//StarttheSerialcommunicationtosendmessagestothecomputerdelay(10);Serial.println('\n');

wifiMulti.addAP("ssid_from_AP_1","your_password_for_AP_1");//addWi-FinetworksyouwanttoconnecttowifiMulti.addAP("ssid_from_AP_2","your_password_for_AP_2");wifiMulti.addAP("ssid_from_AP_3","your_password_for_AP_3");

Serial.println("Connecting...");inti=0;while(wifiMulti.run()!=WL_CONNECTED){//WaitfortheWi-Fitoconnectdelay(250);Serial.print('.');}Serial.println('\n');Serial.print("Connectedto");Serial.println(WiFi.SSID());//Telluswhatnetworkwe'reconnectedtoSerial.print("IPaddress:\t");Serial.println(WiFi.localIP());//SendtheIPaddressoftheESP8266tothecomputerArduinoOTA.setHostname("ESP8266");ArduinoOTA.setPassword("esp8266");

ArduinoOTA.onStart([](){Serial.println("Start");});ArduinoOTA.onEnd([](){Serial.println("\nEnd");});ArduinoOTA.onProgress([](unsignedintprogress,unsignedinttotal){Serial.printf("Progress:%u%%\r",(progress/(total/100)));});ArduinoOTA.onError([](ota_error_terror){Serial.printf("Error[%u]:",error);if(error==OTA_AUTH_ERROR)Serial.println("AuthFailed");elseif(error==OTA_BEGIN_ERROR)Serial.println("BeginFailed");elseif(error==OTA_CONNECT_ERROR)Serial.println("ConnectFailed");elseif(error==OTA_RECEIVE_ERROR)Serial.println("ReceiveFailed");elseif(error==OTA_END_ERROR)Serial.println("EndFailed");});ArduinoOTA.begin();Serial.println("OTAready");

pinMode(led,OUTPUT);digitalWrite(led,1);}

unsignedlongpreviousTime=millis();

constunsignedlonginterval=1000;

voidloop(){ArduinoOTA.handle();unsignedlongdiff=millis()-previousTime;if(diff>interval){digitalWrite(led,!digitalRead(led));//ChangethestateoftheLEDpreviousTime+=diff;}}

AddyourWi-Ficredentials,anduploadthesketchoverSerial.ConnectanLED(+resistor)topin13.ThenrestarttheIDE(youhavetocloseallwindows).GotoTools>Port,andyoushouldgetanewoption:NetworkPorts:ESP8266at192.168.1.x.Selectit.

Page 36: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

Next,changetheintervalonline59from1000to500milliseconds,andclickupload.Youshouldgetapasswordprompt:enter"esp8266".Thispasswordissetonline31,soyoucanchangeitifyouwantto.Youcanalsodeleteline31altogethertouseitwithoutapassword,butit'snotrecommended-forobvioussecurityreasons.

Thesketchshoulduploadjustfine,andoncetheESPhasresetitself,theLEDshouldblinktwiceasfast.

Onceinawhile,youmightgetanerrorsaying[ERROR]:NoAnswer.Ifthishappens,justenterthepassword,andtryagain.

SerialMonitorOTAUsingtheSerialMonitoroverWi-Fiisnotpossible(yet?).Whenyoutrytoopenit,you'llbepromptedapassword,enteringthepasswordwon'twork,becausethereisnoSSHsupporttoaccesstheESP'sconsole.

YoucanuseadifferentprogramtogetdebugoutputfromthephysicalSerialport.OnWindows,youcantryPortmon.OnLinux,youcantryGTKTerm(sudoapt-getinstallgtkterm)orScreen(sudoapt-getinstallscreentoinstall,andscreen/dev/ttyUSB0115200orscreen/dev/ttyACM0115200torun;CTRL+A,CTRL+Dtoexit).

Page 37: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

WebSocketcommunicationUpuntilnow,we'vealwaysusedlinks(GET)andHTMLforms(POST)togetdatafromtheESP,ortosenddatatoit.Thisalwaysresultedinabrowsernavigationaction.TherearemanysituationswhereyouwanttosenddatatotheESPwithoutrefreshingthepage.

OnewaytodothisisbyusingAJAXandXMLHTTPrequests.ThedisadvantageisthatyouhavetoestablishanewTCPconnectionforeverymessageyousend.Thisaddsaloadoflatency.WebSocketisatechnologythatkeepstheTCPconnectionopen,soyoucanconstantlysenddatabackandforthbetweentheESPandtheclient,withlowlatency.Andsinceit'sTCP,you'resurethatthepacketswillarriveintact.

ControllingRGBLEDsfromawebinterfaceusingWebSocketTolearnhowtouseWebSockets,Icreatedthiscomprehensiveexample,itusesprettymucheverythingwe'vecoveredsofar.

TheESPhostsawebpagewiththreesliderstosetthered,greenandbluelevelsofanRGBLED(orLEDstrip).There'salsoabuttontoturnonarainboweffectthatcyclesthroughtheentirecolorwheel.ColordataistransmittedfromthebrowsertotheESPviaaWebSocketconnection.YoucanconnecttotheESPdirectly,usingitasanAP,orlettheESPconnecttoadifferentAP.YoucanusemDNStoopenthewebpage,bybrowsingtohttp://esp8266.local.AllfilesarestoredintheESP'sSPIFFS,andyoucanuploadnewfiles,orupdatefilesviaawebinterface.YoucanalsousetheOTAservicetouploadnewfirmware(sketches)overWi-Fi.

Improvingreadability

Whendealingwithlargeandcomplicatedprograms,it'sagoodideatomakeabstractionofsomethings,andcreatefunctionswithadescriptivenameinsteadofendlesslinesofmeaninglesscode.

Evenifyouhavelotsofcommentsinyourcode,it'llbeveryhardtopreserveanoverview.Usingfunctionswillgreatlyimprovethereadabilityofyourcode.Sojustsplitupthecodeintodifferentpartsandmoveallpiecestofunctionsatthebottomofyoursketch,oreventodifferentfiles.

Inthefollowingexample,thesetupwasverylongandcluttered,soIsplititupintoseveraldifferentfunctions:onetoconnecttotheWi-Fi,onetostarttheOTAupdateservice,onetostarttheSPIFFS...andsoon.

DownloadingWebSocketsforArduino

We'llbeusingthearduinoWebSocketslibrarybyLinks2004.DownloaditfromGitHubandinstallit.(Sketch>IncludeLibrary>Add.ZIPLibrary...)

Libraries,constantsandglobals

Atthetopofthesketchwe'llincludethenecessarylibraries,createsomeglobalserverandfileobjectslikeinthepreviousexamples,andsomeconstantsforthehostname,APssid,passwords,LEDpins...

#include<ESP8266WiFi.h>#include<ESP8266WiFiMulti.h>#include<ArduinoOTA.h>#include<ESP8266WebServer.h>#include<ESP8266mDNS.h>#include<FS.h>#include<WebSocketsServer.h>

ESP8266WiFiMultiwifiMulti;//CreateaninstanceoftheESP8266WiFiMulticlass,called'wifiMulti'

ESP8266WebServerserver=ESP8266WebServer(80);//createawebserveronport80WebSocketsServerwebSocket=WebSocketsServer(81);//createawebsocketserveronport81

FilefsUploadFile;//aFilevariabletotemporarilystorethereceivedfile

constchar*ssid="ESP8266AccessPoint";//ThenameoftheWi-Finetworkthatwillbecreatedconstchar*password="thereisnospoon";//Thepasswordrequiredtoconnecttoit,leaveblankforanopennetwork

constchar*OTAName="ESP8266";//AnameandapasswordfortheOTAserviceconstchar*OTAPassword="esp8266";

#defineLED_RED15//specifythepinswithanRGBLEDconnected#defineLED_GREEN12#defineLED_BLUE13

constchar*mdnsName="esp8266";//DomainnameforthemDNSresponder

Youshouldalreadybefamiliarwithmostofthiscode.TheonlynewpartistheWebSocketserverlibrarythatisincluded,andtheWebSocketserverobject,butthisshouldn'tbeaproblem.

Setup

voidsetup(){pinMode(LED_RED,OUTPUT);//thepinswithLEDsconnectedareoutputspinMode(LED_GREEN,OUTPUT);pinMode(LED_BLUE,OUTPUT);

Serial.begin(115200);//StarttheSerialcommunicationtosendmessagestothecomputerdelay(10);Serial.println("\r\n");

startWiFi();//StartaWi-Fiaccesspoint,andtrytoconnecttosomegivenaccesspoints.ThenwaitforeitheranAPorSTAconnectionstartOTA();//StarttheOTAservice

Page 38: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

startSPIFFS();//StarttheSPIFFSandlistallcontents

startWebSocket();//StartaWebSocketserverstartMDNS();//StartthemDNSresponder

startServer();//StartaHTTPserverwithafilereadhandlerandanuploadhandler}

Asyoucansee,thesetupisnowmuchmorecondensedandgivesamuchbetteroverviewofwhatit'sdoing.Tounderstandtheprogram,youdon'thavetoknoweachindividualstepthatisrequiredtoconnecttoaWi-Finetwork,it'senoughtoknowthatitwillconnecttoaWi-Finetwork,becausethat'swhatthestartWiFifunctiondoes.

Loop

boolrainbow=false;//Therainboweffectisturnedoffonstartup

unsignedlongprevMillis=millis();inthue=0;

voidloop(){webSocket.loop();//constantlycheckforwebsocketeventsserver.handleClient();//runtheserverArduinoOTA.handle();//listenforOTAevents

if(rainbow){//iftherainboweffectisturnedonif(millis()>prevMillis+32){if(++hue==360)//Cyclethroughthecolorwheel(incrementbyonedegreeevery32ms)hue=0;setHue(hue);//SettheRGBLEDtotherightcolorprevMillis=millis();}}}

Samegoesfortheloop:mostoftheworkisdonebythefirstthreefunctionsthathandletheWebSocketcommunication,HTTPrequestsandOTAupdates.Whensuchaneventhappens,theappropriatehandlerfunctionswillbeexecuted.Thesearedefinedelsewhere.

Thesecondpartistherainboweffect.Ifitisturnedon,itcyclesthroughthecolorwheelandsetsthecolortotheRGBLED.Ifyoudon'tunderstandwhyIusemillis(),youcantakealookattheBlinkWithoutDelayexample.

Setupfunctions

voidstartWiFi(){//StartaWi-Fiaccesspoint,andtrytoconnecttosomegivenaccesspoints.ThenwaitforeitheranAPorSTAconnectionWiFi.softAP(ssid,password);//StarttheaccesspointSerial.print("AccessPoint\"");Serial.print(ssid);Serial.println("\"started\r\n");

wifiMulti.addAP("ssid_from_AP_1","your_password_for_AP_1");//addWi-FinetworksyouwanttoconnecttowifiMulti.addAP("ssid_from_AP_2","your_password_for_AP_2");wifiMulti.addAP("ssid_from_AP_3","your_password_for_AP_3");

Serial.println("Connecting");while(wifiMulti.run()!=WL_CONNECTED&&WiFi.softAPgetStationNum()<1){//WaitfortheWi-Fitoconnectdelay(250);Serial.print('.');}Serial.println("\r\n");if(WiFi.softAPgetStationNum()==0){//IftheESPisconnectedtoanAPSerial.print("Connectedto");Serial.println(WiFi.SSID());//Telluswhatnetworkwe'reconnectedtoSerial.print("IPaddress:\t");Serial.print(WiFi.localIP());//SendtheIPaddressoftheESP8266tothecomputer}else{//IfastationisconnectedtotheESPSoftAPSerial.print("StationconnectedtoESP8266AP");}Serial.println("\r\n");}

voidstartOTA(){//StarttheOTAserviceArduinoOTA.setHostname(OTAName);ArduinoOTA.setPassword(OTAPassword);

ArduinoOTA.onStart([](){Serial.println("Start");digitalWrite(LED_RED,0);//turnofftheLEDsdigitalWrite(LED_GREEN,0);digitalWrite(LED_BLUE,0);});ArduinoOTA.onEnd([](){Serial.println("\r\nEnd");});ArduinoOTA.onProgress([](unsignedintprogress,unsignedinttotal){Serial.printf("Progress:%u%%\r",(progress/(total/100)));});ArduinoOTA.onError([](ota_error_terror){Serial.printf("Error[%u]:",error);if(error==OTA_AUTH_ERROR)Serial.println("AuthFailed");elseif(error==OTA_BEGIN_ERROR)Serial.println("BeginFailed");elseif(error==OTA_CONNECT_ERROR)Serial.println("ConnectFailed");elseif(error==OTA_RECEIVE_ERROR)Serial.println("ReceiveFailed");elseif(error==OTA_END_ERROR)Serial.println("EndFailed");});ArduinoOTA.begin();Serial.println("OTAready\r\n");}

voidstartSPIFFS(){//StarttheSPIFFSandlistallcontentsSPIFFS.begin();//StarttheSPIFlashFileSystem(SPIFFS)Serial.println("SPIFFSstarted.Contents:");{Dirdir=SPIFFS.openDir("/");

Page 39: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

while(dir.next()){//ListthefilesystemcontentsStringfileName=dir.fileName();size_tfileSize=dir.fileSize();Serial.printf("\tFSFile:%s,size:%s\r\n",fileName.c_str(),formatBytes(fileSize).c_str());}Serial.printf("\n");}}

voidstartWebSocket(){//StartaWebSocketserverwebSocket.begin();//startthewebsocketserverwebSocket.onEvent(webSocketEvent);//ifthere'sanincommingwebsocketmessage,gotofunction'webSocketEvent'Serial.println("WebSocketserverstarted.");}

voidstartMDNS(){//StartthemDNSresponderMDNS.begin(mdnsName);//startthemulticastdomainnameserverSerial.print("mDNSresponderstarted:http://");Serial.print(mdnsName);Serial.println(".local");}

voidstartServer(){//StartaHTTPserverwithafilereadhandlerandanuploadhandlerserver.on("/edit.html",HTTP_POST,[](){//IfaPOSTrequestissenttothe/edit.htmladdress,server.send(200,"text/plain","");},handleFileUpload);//goto'handleFileUpload'

server.onNotFound(handleNotFound);//ifsomeonerequestsanyotherfileorpage,gotofunction'handleNotFound'//andcheckifthefileexists

server.begin();//starttheHTTPserverSerial.println("HTTPserverstarted.");}

Thesearethefunctiondefinitionsofthefunctionsusedinthesetup.Nothingnewhere,apartfromthestartWebSocketfunction.YoujusthavetostarttheWebSocketserverusingthebeginmethod,andthengiveitacallbackfunctionthatisexecutedwhentheESPreceivesaWebSocketmessage.

Serverhandlers

Thisisthecodethatisexecutedoncertainserver-relatedevents,likewhenanHTTPrequestisreceived,whenafileisbeinguploaded,whenthere'sanincomingWebSocketmessage...etc.

voidhandleNotFound(){//iftherequestedfileorpagedoesn'texist,returna404notfounderrorif(!handleFileRead(server.uri())){//checkifthefileexistsintheflashmemory(SPIFFS),ifso,senditserver.send(404,"text/plain","404:FileNotFound");}}

boolhandleFileRead(Stringpath){//sendtherightfiletotheclient(ifitexists)Serial.println("handleFileRead:"+path);if(path.endsWith("/"))path+="index.html";//Ifafolderisrequested,sendtheindexfileStringcontentType=getContentType(path);//GettheMIMEtypeStringpathWithGz=path+".gz";if(SPIFFS.exists(pathWithGz)||SPIFFS.exists(path)){//Ifthefileexists,eitherasacompressedarchive,ornormalif(SPIFFS.exists(pathWithGz))//Ifthere'sacompressedversionavailablepath+=".gz";//UsethecompressedverionFilefile=SPIFFS.open(path,"r");//Openthefilesize_tsent=server.streamFile(file,contentType);//Sendittotheclientfile.close();//ClosethefileagainSerial.println(String("\tSentfile:")+path);returntrue;}Serial.println(String("\tFileNotFound:")+path);//Ifthefiledoesn'texist,returnfalsereturnfalse;}

voidhandleFileUpload(){//uploadanewfiletotheSPIFFSHTTPUpload&upload=server.upload();Stringpath;if(upload.status==UPLOAD_FILE_START){path=upload.filename;if(!path.startsWith("/"))path="/"+path;if(!path.endsWith(".gz")){//ThefileserveralwaysprefersacompressedversionofafileStringpathWithGz=path+".gz";//Soifanuploadedfileisnotcompressed,theexistingcompressedif(SPIFFS.exists(pathWithGz))//versionofthatfilemustbedeleted(ifitexists)SPIFFS.remove(pathWithGz);}Serial.print("handleFileUploadName:");Serial.println(path);fsUploadFile=SPIFFS.open(path,"w");//OpenthefileforwritinginSPIFFS(createifitdoesn'texist)path=String();}elseif(upload.status==UPLOAD_FILE_WRITE){if(fsUploadFile)fsUploadFile.write(upload.buf,upload.currentSize);//Writethereceivedbytestothefile}elseif(upload.status==UPLOAD_FILE_END){if(fsUploadFile){//IfthefilewassuccessfullycreatedfsUploadFile.close();//ClosethefileagainSerial.print("handleFileUploadSize:");Serial.println(upload.totalSize);server.sendHeader("Location","/success.html");//Redirecttheclienttothesuccesspageserver.send(303);}else{server.send(500,"text/plain","500:couldn'tcreatefile");}}}

voidwebSocketEvent(uint8_tnum,WStype_ttype,uint8_t*payload,size_tlenght){//WhenaWebSocketmessageisreceivedswitch(type){caseWStype_DISCONNECTED://ifthewebsocketisdisconnectedSerial.printf("[%u]Disconnected!\n",num);break;caseWStype_CONNECTED:{//ifanewwebsocketconnectionisestablishedIPAddressip=webSocket.remoteIP(num);Serial.printf("[%u]Connectedfrom%d.%d.%d.%durl:%s\n",num,ip[0],ip[1],ip[2],ip[3],payload);rainbow=false;//Turnrainbowoffwhenanewconnectionisestablished}break;caseWStype_TEXT://ifnewtextdataisreceivedSerial.printf("[%u]getText:%s\n",num,payload);if(payload[0]=='#'){//wegetRGBdata

Page 40: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

uint32_trgb=(uint32_t)strtol((constchar*)&payload[1],NULL,16);//decodergbdataintr=((rgb>>20)&0x3FF);//10bitspercolor,soR:bits20-29intg=((rgb>>10)&0x3FF);//G:bits10-19intb=rgb&0x3FF;//B:bits0-9

analogWrite(LED_RED,r);//writeittotheLEDoutputpinsanalogWrite(LED_GREEN,g);analogWrite(LED_BLUE,b);}elseif(payload[0]=='R'){//thebrowsersendsanRwhentherainboweffectisenabledrainbow=true;}elseif(payload[0]=='N'){//thebrowsersendsanNwhentherainboweffectisdisabledrainbow=false;}break;}}

Again,mostofthecodeisadaptedfromthepreviousexamples,onlytheWebSocketpartisnew.

TherearedifferenttypesofWebSocketmessages,butwe'reonlyinterestedinthetexttype,becausetheJavaScriptcodeattheclientsidesendsthecolordataintextformat,asahexadecimalnumber,startingwitha'#'sign.Eachcolorisa10-bitnumber,sointotal,itgivesusa30-bitnumberfortheRGBvalue.

Whentherainbowfunctionisenabled,JavaScriptsendsan'R'character,andwhenit'sdisabled,itsendsa'N'character.

Let'stakealookattheHTMLandJavaScriptcodeaswell:

HTML

<!DOCTYPEhtml><html><head><title>LEDControl</title><linkhref='https://fonts.googleapis.com/css?family=Roboto:300'rel='stylesheet'type='text/css'><linkhref='main.css'rel='stylesheet'type='text/css'><linkrel="apple-touch-icon"sizes="180x180"href="/apple-touch-icon-180x180.png"><linkrel="icon"type="image/png"sizes="144x144"href="/favicon-144x144.png"><linkrel="icon"type="image/png"sizes="48x48"href="/favicon.ico"><linkrel="manifest"href="/manifest.json"><metaname="theme-color"content="#00878f"><metacontent='width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0'name='viewport'><scriptsrc="WebSocket.js"type="text/javascript"></script></head>

<body><center><header><h1>LEDControl</h1></header><div><table><tr><tdstyle="width:14.4px;text-align:right">R:</td><td><inputclass="enabled"id="r"type="range"min="0"max="1023"step="1"oninput="sendRGB();"value="0"></td></tr><tr><tdstyle="width:14.4px;text-align:right">G:</td><td><inputclass="enabled"id="g"type="range"min="0"max="1023"step="1"oninput="sendRGB();"value="0"></td></tr><tr><tdstyle="width:14.4px;text-align:right">B:</td><td><inputclass="enabled"id="b"type="range"min="0"max="1023"step="1"oninput="sendRGB();"value="0"></td></tr></table><pstyle="margin:8px0px"><buttonid="rainbow"class="button"style="background-color:#999"onclick="rainbowEffect();">Rainbow</button></p></div></center></body></html>

There'sreallynotmuchtoit,just3slidersandabuttonlinkedtoJavaScriptfunctions.

JavaScript

varrainbowEnable=false;varconnection=newWebSocket('ws://'+location.hostname+':81/',['arduino']);connection.onopen=function(){connection.send('Connect'+newDate());};connection.onerror=function(error){console.log('WebSocketError',error);};connection.onmessage=function(e){console.log('Server:',e.data);};connection.onclose=function(){console.log('WebSocketconnectionclosed');};

functionsendRGB(){varr=document.getElementById('r').value**2/1023;varg=document.getElementById('g').value**2/1023;varb=document.getElementById('b').value**2/1023;

varrgb=r<<20|g<<10|b;varrgbstr='#'+rgb.toString(16);console.log('RGB:'+rgbstr);connection.send(rgbstr);}

functionrainbowEffect(){rainbowEnable=!rainbowEnable;if(rainbowEnable){

Page 41: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

connection.send("R");document.getElementById('rainbow').style.backgroundColor='#00878F';document.getElementById('r').className='disabled';document.getElementById('g').className='disabled';document.getElementById('b').className='disabled';document.getElementById('r').disabled=true;document.getElementById('g').disabled=true;document.getElementById('b').disabled=true;}else{connection.send("N");document.getElementById('rainbow').style.backgroundColor='#999';document.getElementById('r').className='enabled';document.getElementById('g').className='enabled';document.getElementById('b').className='enabled';document.getElementById('r').disabled=false;document.getElementById('g').disabled=false;document.getElementById('b').disabled=false;sendRGB();}}

WejustcreateaWebSocketconnectionobjecttosenddatatotheESP.Theneverytimeasliderismoved,wetakethevaluesofthethreeslidersandwesquarethecolorvaluestogetasmootherandmorenaturalcurve.Wethencombinethemintoa30-bitnumber(10bitspercolor).Finally,theRGBvaluegetsconvertedtoahexadecimalstring,a'#'isadded,andit'ssenttotheESP.Whentherainbowbuttonispressed,theslidersaredisabled,andan'R'issenttotheESP.Whentherainbowbuttonispressedagain,theslidersareenabled,andan'N'issent.

Helperfunctions

BacktotheESP8266Arduinocodeagain.Weneedsomeotherfunctionsaswell,toconvertbytestoKBandMB,todeterminefiletypesbasedonfileextensionsandtoconvertahueangletoRGBvalues.

StringformatBytes(size_tbytes){//convertsizesinbytestoKBandMBif(bytes<1024){returnString(bytes)+"B";}elseif(bytes<(1024*1024)){returnString(bytes/1024.0)+"KB";}elseif(bytes<(1024*1024*1024)){returnString(bytes/1024.0/1024.0)+"MB";}}

StringgetContentType(Stringfilename){//determinethefiletypeofagivenfilename,basedontheextensionif(filename.endsWith(".html"))return"text/html";elseif(filename.endsWith(".css"))return"text/css";elseif(filename.endsWith(".js"))return"application/javascript";elseif(filename.endsWith(".ico"))return"image/x-icon";elseif(filename.endsWith(".gz"))return"application/x-gzip";return"text/plain";}

voidsetHue(inthue){//SettheRGBLEDtoagivenhue(color)(0°=Red,120°=Green,240°=Blue)hue%=360;//hueisananglebetween0and359°floatradH=hue*3.142/180;//Convertdegreestoradiansfloatrf,gf,bf;if(hue>=0&&hue<120){//ConvertfromHSIcolorspacetoRGBrf=cos(radH*3/4);gf=sin(radH*3/4);bf=0;}elseif(hue>=120&&hue<240){radH-=2.09439;gf=cos(radH*3/4);bf=sin(radH*3/4);rf=0;}elseif(hue>=240&&hue<360){radH-=4.188787;bf=cos(radH*3/4);rf=sin(radH*3/4);gf=0;}intr=rf*rf*1023;intg=gf*gf*1023;intb=bf*bf*1023;analogWrite(LED_RED,r);//WritetherightcolortotheLEDoutputpinsanalogWrite(LED_GREEN,g);analogWrite(LED_BLUE,b);}

ToconvertfromhuetoRGB,weusesinesandcosines,becausethesumoftheirsquaresisalwaysone,sothetotalintensitywillalwaysbemoreorlessthesame.

ThisresultsinthefollowingRGBcurves:

Page 42: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

UsingtheexampleDownloadtheexamplefromGitHubandopenitintheArduinoIDE.ThenaddyourWi-Ficredentials(lines83-85).ConnectanRGBLEDwithredtopin15,greentopin12andbluetopin13.Don'tforgetthecurrentlimitingresistors!SelecttheSPIFFSsize(64KBshouldbeenough,butifyouwanttouploadmorefileslater,youshouldsetithigher).UploadthesketchoverSerial,andthenuploadtheSPIFFSfilesusingTools>ESP8266SketchDataUpload.

WaitforittoconnecttoaWi-Finetwork,orconnecttotheESP8266AccessPointusingthepassword'thereisnospoon',andgotohttp://esp8266.local.Youshouldgetapagethatlookslikethis:

UsethesliderstoadjustthecolorlevelsoftheLED,andpresstheRainbowbuttontoenabletherainboweffect.

Ifyougotohttp://esp8266.local/edit.html,youcanuploadorupdatefiles:

Page 43: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

NetworkTimeProtocolTherearemanyapplicationswhereyouwanttoknowthetime.InanormalArduinoproject,youwouldhavetogetaRTCmodule,settherighttime,sacrificesomeArduinopinsforcommunication...AndwhentheRTCbatteryrunsout,youhavetoreplaceit.

OntheESP8266,allyouneedisanInternetconnection:youcanjustaskatimeserverwhattimeitis.Todothis,theNetworkTimeProtocol(NTP)isused.

Inthepreviousexamples(HTTP,WebSockets)we'veonlyusedTCPconnections,butNTPisbasedonUDP.Thereareacoupleofdifferences,butit'sreallyeasytouse,thankstothegreatlibrariesthatcomewiththeESP8266ArduinoCore.

ThemaindifferencebetweenTCPandUDPisthatTCPneedsaconnectiontosendmessages:Firstahandshakeissentbytheclient,theserverresponds,andaconnectionisestablished,andtheclientcansenditsmessages.Aftertheclienthasreceivedtheresponseoftheserver,theconnectionisclosed(exceptwhenusingWebSockets).Tosendanewmessage,theclienthastoopenanewconnectiontotheserverfirst.Thisintroduceslatencyandoverhead.

UDPdoesn'tuseaconnection,aclientcanjustsendamessagetotheserverdirectly,andtheservercanjustsendaresponsemessagebacktotheclientwhenithasfinishedprocessing.Thereis,however,noguaranteethatthemessageswillarriveattheirdestination,andthere'snowaytoknowwhethertheyarrivedornot(withoutsendinganacknowledgement,ofcourse).Thismeansthatwecan'thalttheprogramtowaitforaresponse,becausetherequestorresponsepacketcouldhavebeenlostontheInternet,andtheESP8266willenteraninfiniteloop.

Insteadofwaitingforaresponse,wejustsendmultiplerequests,withafixedintervalbetweentworequests,andjustregularlycheckifaresponsehasbeenreceived.

GettingthetimeLet'stakealookatanexamplethatusesUDPtorequestthetimefromaNTPserver.

Libraries,constantsandglobals

#include<ESP8266WiFi.h>#include<ESP8266WiFiMulti.h>#include<WiFiUdp.h>

ESP8266WiFiMultiwifiMulti;//CreateaninstanceoftheESP8266WiFiMulticlass,called'wifiMulti'

WiFiUDPUDP;//CreateaninstanceoftheWiFiUDPclasstosendandreceive

IPAddresstimeServerIP;//time.nist.govNTPserveraddressconstchar*NTPServerName="time.nist.gov";

constintNTP_PACKET_SIZE=48;//NTPtimestampisinthefirst48bytesofthemessage

byteNTPBuffer[NTP_PACKET_SIZE];//buffertoholdincomingandoutgoingpackets

TouseUDP,wehavetoincludetheWiFiUdplibrary,andcreateaUDPobject.We'llalsoneedtoallocatememoryforabuffertostoretheUDPpackets.ForNTP,weneedabufferof48byteslong.ToknowwheretosendtheUDPpacketsto,weneedthehostnameoftheNTPserver,thisistime.nist.gov.

Setup

voidsetup(){Serial.begin(115200);//StarttheSerialcommunicationtosendmessagestothecomputerdelay(10);Serial.println("\r\n");

startWiFi();//Trytoconnecttosomegivenaccesspoints.Thenwaitforaconnection

startUDP();

if(!WiFi.hostByName(NTPServerName,timeServerIP)){//GettheIPaddressoftheNTPserverSerial.println("DNSlookupfailed.Rebooting.");Serial.flush();ESP.reset();}Serial.print("TimeserverIP:\t");Serial.println(timeServerIP);Serial.println("\r\nSendingNTPrequest...");sendNTPpacket(timeServerIP);}

Inthesetup,wejuststartourSerialandWi-Fi,asusual,andwestartUDPaswell.We'lllookattheimplementationofthisfunctionlater.WeneedtheIPaddressoftheNTPserver,soweperformaDNSlookupwiththeserver'shostname.There'snotmuchwecandowithouttheIPaddressofthetimeserver,soifthelookupfails,reboottheESP.IfwedogetanIP,sendthefirstNTPrequest,andentertheloop.

Loop

unsignedlongintervalNTP=60000;//RequestNTPtimeeveryminuteunsignedlongprevNTP=0;unsignedlonglastNTPResponse=millis();uint32_ttimeUNIX=0;

unsignedlongprevActualTime=0;

voidloop(){unsignedlongcurrentMillis=millis();

if(currentMillis-prevNTP>intervalNTP){//IfaminutehaspassedsincelastNTPrequest

Page 44: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

prevNTP=currentMillis;Serial.println("\r\nSendingNTPrequest...");sendNTPpacket(timeServerIP);//SendanNTPrequest}

uint32_ttime=getTime();//CheckifanNTPresponsehasarrivedandgetthe(UNIX)timeif(time){//IfanewtimestamphasbeenreceivedtimeUNIX=time;Serial.print("NTPresponse:\t");Serial.println(timeUNIX);lastNTPResponse=currentMillis;}elseif((currentMillis-lastNTPResponse)>3600000){Serial.println("Morethan1hoursincelastNTPresponse.Rebooting.");Serial.flush();ESP.reset();}

uint32_tactualTime=timeUNIX+(currentMillis-lastNTPResponse)/1000;if(actualTime!=prevActualTime&&timeUNIX!=0){//IfasecondhaspassedsincelastprintprevActualTime=actualTime;Serial.printf("\rUTCtime:\t%d:%d:%d",getHours(actualTime),getMinutes(actualTime),getSeconds(actualTime));}}

ThefirstpartoftheloopsendsanewNTPrequesttothetimeservereveryminute.ThisisbasedonBlinkWithoutDelay.ThenwecallthegetTimefunctiontocheckifwe'vegotanewresponsefromtheserver.Ifthisisthecase,weupdatethetimeUNIXvariablewiththenewtimestampfromtheserver.Ifwedon'tgetanyresponsesforanhour,thenthere'ssomethingwrong,sowereboottheESP.Thelastpartprintstheactualtime.TheactualtimeisjustthelastNTPtimeplusthetimesincewereceivedthatNTPmessage.

Setupfunctions

Nothingspecialhere,justafunctiontoconnecttoWi-Fi,andanewfunctiontostartlisteningforUDPmessagesonport123.

voidstartWiFi(){//Trytoconnecttosomegivenaccesspoints.ThenwaitforaconnectionwifiMulti.addAP("ssid_from_AP_1","your_password_for_AP_1");//addWi-FinetworksyouwanttoconnecttowifiMulti.addAP("ssid_from_AP_2","your_password_for_AP_2");wifiMulti.addAP("ssid_from_AP_3","your_password_for_AP_3");

Serial.println("Connecting");while(wifiMulti.run()!=WL_CONNECTED){//WaitfortheWi-Fitoconnectdelay(250);Serial.print('.');}Serial.println("\r\n");Serial.print("Connectedto");Serial.println(WiFi.SSID());//Telluswhatnetworkwe'reconnectedtoSerial.print("IPaddress:\t");Serial.print(WiFi.localIP());//SendtheIPaddressoftheESP8266tothecomputerSerial.println("\r\n");}

voidstartUDP(){Serial.println("StartingUDP");UDP.begin(123);//StartlisteningforUDPmessagesonport123Serial.print("Localport:\t");Serial.println(UDP.localPort());Serial.println();}

Helperfunctions

uint32_tgetTime(){if(UDP.parsePacket()==0){//Ifthere'snoresponse(yet)return0;}UDP.read(NTPBuffer,NTP_PACKET_SIZE);//readthepacketintothebuffer//Combinethe4timestampbytesintoone32-bitnumberuint32_tNTPTime=(NTPBuffer[40]<<24)|(NTPBuffer[41]<<16)|(NTPBuffer[42]<<8)|NTPBuffer[43];//ConvertNTPtimetoaUNIXtimestamp://UnixtimestartsonJan11970.That's2208988800secondsinNTPtime:constuint32_tseventyYears=2208988800UL;//subtractseventyyears:uint32_tUNIXTime=NTPTime-seventyYears;returnUNIXTime;}

voidsendNTPpacket(IPAddress&address){memset(NTPBuffer,0,NTP_PACKET_SIZE);//setallbytesinthebufferto0//InitializevaluesneededtoformNTPrequestNTPBuffer[0]=0b11100011;//LI,Version,Mode//sendapacketrequestingatimestamp:UDP.beginPacket(address,123);//NTPrequestsaretoport123UDP.write(NTPBuffer,NTP_PACKET_SIZE);UDP.endPacket();}

inlineintgetSeconds(uint32_tUNIXTime){returnUNIXTime%60;}

inlineintgetMinutes(uint32_tUNIXTime){returnUNIXTime/60%60;}

inlineintgetHours(uint32_tUNIXTime){returnUNIXTime/3600%24;}

InthegetTimefunction,wefirsttrytoparsetheUDPpacket.Ifthere'snopacketavailable,thefunctionjustreturns0.IfthereisaUDPpacketavailablehowever,readitintothebuffer.TheNTPtimestampis32bitsor4byteswide,sowecombinethesebytesintoonelongnumber.ThisnumberisthenumberofsecondssinceJan1,1900,00:00:00,butmostapplicationsuseUNIXtime,thenumberofsecondssinceJan1,1970,00:00:00(UNIXepoch).ToconvertfromNTPtimetoUNIXtime,wejustsubtract70yearsworthofseconds.

Page 45: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

TorequestthetimefromtheNTPserver,youhavetosendacertainsequenceof48bytes.Wedon'tneedanyfancyfeatures,sojustsetthefirstbytetorequestthetime,andleaveallother47byteszero.Toactuallysendthepacket,youhavetostartthepacket,specifyingtheIPaddressoftheserver,andtheNTPportnumber,port123.Thenjustwritethebuffertothepacket,andsenditwithendPacket.

Thelastthreefunctionsarejustsomesimplemathtoconvertsecondstohours,minutesandseconds.

Usingtheexample

EnteryourWi-Ficredentialsonlines79-81,andhitupload.IfyouhaveaworkingInternetconnection,youshouldgetanoutputthatlookslikethis:

Connecting.........

ConnectedtoWi-FiSSIDIPaddress: 192.168.1.2

StartingUDPLocalport: 123

TimeserverIP:216.229.0.179

SendingNTPrequest...NTPresponse: 1488378061UTCtime: 14:21:53SendingNTPrequest...NTPresponse: 1488378114UTCtime: 14:22:53SendingNTPrequest...NTPresponse: 1488378174UTCtime: 14:23:53SendingNTPrequest...NTPresponse: 1488378234UTCtime: 14:24:53SendingNTPrequest...NTPresponse: 1488378294UTCtime: 14:25:53...

Youshouldseethetimeupdateeverysecond,andSendingNTPrequest...shouldshowupeveryminute.Ifyoudon'thaveanInternetconnection,theDNSlookupofthetimeserverwillfail:

Connecting.........

ConnectedtoWi-FiSSIDIPaddress: 192.168.1.2

StartingUDPLocalport: 123

DNSlookupfailed.Rebooting.

etsJan82013,rstcause:2,bootmode:(3,6)

Ifyourconnectionisnotreliable,orifthere'sheavytraffic,youmightencountersomedroppedpackets:

SendingNTPrequest...NTPresponse: 1488378780UTCtime: 14:33:54SendingNTPrequest...UTCtime: 14:34:54SendingNTPrequest...NTPresponse: 1488378895UTCtime: 14:35:0

Asyoucansee,theESPneverreceivedaresponsetothesecondNTPrequest.That'snotreallyanissue,aslongasatleastsomepacketsmakeitthrough.

Localtimeanddaylightsavings

AnNTPserverreturnstheUTCtime.Ifyouwantlocaltime,youhavetocompensateforyourtimezoneanddaylightsavings.Forexample,ifyouwantCET(CentralEuropeanTime),youhavetoadd3600totheUNIXtimeduringwinter,(3600s=1h),and7200duringsummer(DST).

Page 46: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

DataloggingAcommonuseforIoTdevicesliketheESP8266ismonitoringsensors.Usingthecodeinthepreviousexample,wecanrequestthetime,andsavesomesensorvaluestoafile.Ifwerunaserveraswell,wecanshowthisdatainaprettygraphinawebpage.

TemperatureloggerInthefollowingexample,we'lluseaDS18S20temperaturesensortologthetemperatureovertimeandsaveittotheSPIFFS.Itcanthenbedisplayedinagraphinthebrowser.

Installinglibraries

First,downloadtheDallasTemperaturelibrarybyMilesBurtonandtheOneWirelibrarybyJimStudt:GotoSketch>IncludeLibrary...>ManageLibrariesandsearchfor'DallasTemperature'and'OneWire'(makesureyoudownloadthecorrectversion).

Hardware

ConnectthegroundoftheDS18S20temperaturesensor(pin1)tothegroundoftheESP,connectthedatapin(pin2)toGPIO5,andVCC(pin3)tothe3.3VoftheESP.Finally,connecta4k7ΩresistorbetweenthedatapinandVCC.

Libraries,constantsandglobals

#include<OneWire.h>#include<DallasTemperature.h>#include<ESP8266WiFi.h>#include<ESP8266WiFiMulti.h>#include<WiFiUdp.h>#include<ArduinoOTA.h>#include<ESP8266WebServer.h>#include<ESP8266mDNS.h>#include<FS.h>

#defineONE_HOUR3600000UL

#defineTEMP_SENSOR_PIN5

OneWireoneWire(TEMP_SENSOR_PIN);//SetupaOneWireinstancetocommunicatewithOneWiredevices

DallasTemperaturetempSensors(&oneWire);//Createaninstanceofthetemperaturesensorclass

ESP8266WebServerserver=ESP8266WebServer(80);//createawebserveronport80

FilefsUploadFile;//aFilevariabletotemporarilystorethereceivedfile

ESP8266WiFiMultiwifiMulti;//CreateaninstanceoftheESP8266WiFiMulticlass,called'wifiMulti'

constchar*OTAName="ESP8266";//AnameandapasswordfortheOTAserviceconstchar*OTAPassword="esp8266";

constchar*mdnsName="esp8266";//DomainnameforthemDNSresponder

WiFiUDPUDP;//CreateaninstanceoftheWiFiUDPclasstosendandreceiveUDPmessages

IPAddresstimeServerIP;//Thetime.nist.govNTPserver'sIPaddressconstchar*ntpServerName="time.nist.gov";

constintNTP_PACKET_SIZE=48;//NTPtimestampisinthefirst48bytesofthemessage

bytepacketBuffer[NTP_PACKET_SIZE];//Abuffertoholdincomingandoutgoingpackets

TheonlynewthingsherearetheOneWireandDallasTemperaturelibraries,togetthetemperaturefromthesensor.

Setup

voidsetup(){Serial.begin(115200);//StarttheSerialcommunicationtosendmessagestothecomputerdelay(10);Serial.println("\r\n");

tempSensors.setWaitForConversion(false);//Don'tblocktheprogramwhilethetemperaturesensorisreadingtempSensors.begin();//Startthetemperaturesensor

if(tempSensors.getDeviceCount()==0){Serial.printf("NoDS18x20temperaturesensorfoundonpin%d.Rebooting.\r\n",TEMP_SENSOR_PIN);Serial.flush();ESP.reset();}

startWiFi();//StartaWi-Fiaccesspoint,andtrytoconnecttosomegivenaccesspoints.ThenwaitforeitheranAPorSTAconnection

startOTA();//StarttheOTAservice

startSPIFFS();//StarttheSPIFFSandlistallcontents

startMDNS();//StartthemDNSresponder

startServer();//StartaHTTPserverwithafilereadhandlerandanuploadhandler

startUDP();//StartlisteningforUDPmessagestoport123

WiFi.hostByName(ntpServerName,timeServerIP);//GettheIPaddressoftheNTPserverSerial.print("TimeserverIP:\t");Serial.println(timeServerIP);

sendNTPpacket(timeServerIP);}

Page 47: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

Inthesetup,there'snotmuchneweither,wejuststartthetemperaturesensor,andcheckifwecancommunicatewithit.Ifnotemperaturesensorisfound,theESPresets.

Gettingthetemperaturefromthesensormaytakesometime(upto750ms).Wedon'twantourlooptotakelongerthanacoupleofmilliseconds,sowecan'twait750ms.Ifwedid,theHTTPserveretc.wouldstarttomisbehave.Thesolutionistorequestthetemperaturefirst.Thesensorwillthenstartreadingtheanalogtemperature,andstoresitinitsmemory.Inthemeantime,theloopjustkeepsonrunning,theserverrefreshesetc.After750ms,wecontactthesensoragain,andreadthetemperaturefromitsmemory.Totellthelibrarythatwedon'twanttowaitfortheanalogtodigitalconversionofthesensor,weusesetWaitForConversion.

Loop

constunsignedlongintervalNTP=ONE_HOUR;//UpdatethetimeeveryhourunsignedlongprevNTP=0;unsignedlonglastNTPResponse=millis();

constunsignedlongintervalTemp=60000;//DoatemperaturemeasurementeveryminuteunsignedlongprevTemp=0;booltmpRequested=false;constunsignedlongDS_delay=750;//ReadingthetemperaturefromtheDS18x20cantakeupto750ms

uint32_ttimeUNIX=0;//Themostrecenttimestampreceivedfromthetimeserver

voidloop(){unsignedlongcurrentMillis=millis();

if(currentMillis-prevNTP>intervalNTP){//RequestthetimefromthetimeservereveryhourprevNTP=currentMillis;sendNTPpacket(timeServerIP);}

uint32_ttime=getTime();//Checkifthetimeserverhasresponded,ifso,gettheUNIXtimeif(time){timeUNIX=time;Serial.print("NTPresponse:\t");Serial.println(timeUNIX);lastNTPResponse=millis();}elseif((millis()-lastNTPResponse)>24UL*ONE_HOUR){Serial.println("Morethan24hourssincelastNTPresponse.Rebooting.");Serial.flush();ESP.reset();}

if(timeUNIX!=0){if(currentMillis-prevTemp>intervalTemp){//Everyminute,requestthetemperaturetempSensors.requestTemperatures();//Requestthetemperaturefromthesensor(ittakessometimetoreadit)tmpRequested=true;prevTemp=currentMillis;Serial.println("Temperaturerequested");}if(currentMillis-prevTemp>DS_delay&&tmpRequested){//750msafterrequestingthetemperatureuint32_tactualTime=timeUNIX+(currentMillis-lastNTPResponse)/1000;//TheactualtimeisthelastNTPtimeplusthetimethathaselapsedsincethelastNTPresponsetmpRequested=false;floattemp=tempSensors.getTempCByIndex(0);//Getthetemperaturefromthesensortemp=round(temp*100.0)/100.0;//roundtemperatureto2digits

Serial.printf("Appendingtemperaturetofile:%lu,",actualTime);Serial.println(temp);FiletempLog=SPIFFS.open("/temp.csv","a");//WritethetimeandthetemperaturetothecsvfiletempLog.print(actualTime);tempLog.print(',');tempLog.println(temp);tempLog.close();}}else{//Ifwedidn'treceiveanNTPresponseyet,sendanotherrequestsendNTPpacket(timeServerIP);delay(500);}

server.handleClient();//runtheserverArduinoOTA.handle();//listenforOTAevents}

Thelooplooksalotmorecomplex,butit'sactuallyprettysimple.It'sallbasedonBlinkWithoutDelay.There'stwothingsgoingon:

1. Everyhour,theESPrequeststhetimefromanNTPserver.Thenitconstantlychecksforaresponse,andupdatesthetimeifitgetsanNTPresponse.Ifithasn'treceivedanyresponsesforover24hours,there'ssomethingwrong,andtheESPresetsitself.

2. Everyminute,theESPrequeststhetemperaturefromtheDS18x20sensor,andsetsthe'tmpRequested'flag.Thesensorwillstarttheanalogtodigitalconversion.750msaftertherequest,whentheconversionshouldbefinished,theESPreadsthetemperaturefromthesensor,andresetstheflag(otherwise,itwouldkeeponreadingthesametemperatureoverandoveragain).ThenitwritesthetimeandthetemperaturetoafileinSPIFFS.BysavingitasaCSVfileinthefilesystem,wecaneasilydownloadittotheclient(usingthewebserverthatisrunning),andit'seasytoparsewithJavaScript.

IfwemissthefirstNTPresponse,timeUNIXwillbezero.Ifthat'sthecase,wesendanotherNTPrequest(otherwise,thenextrequestwouldbeanhourlater,andthetemperatureloggingonlystartswhenthetimeisknown).

WealsoneedtoruntheserverandOTAfunctionstohandleHTTPandOTArequests.

Setupfunctions,serverhandlersandhelperfunctions

Thesefunctionshaven'tchangesincethepreviousexample,sothere'snoneedtocoverthemhere.Youdoneedthemtogettheprogramrunning,though.DownloadtheZIParchivewithexamplesforthefullsketch.

HTMLandJavaScript

There'ssomeHTMLandJavaScriptfilestoplotthetemperatureusingGoogleGraphs.Iwon'tcoverithere,butifyouwan'ttoknow

Page 48: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

howitworks,youcanfindthefilesintheZIParchive.

Usingtheexample

SettheSPIFFSsizeto64KBorlargerifyouplantouseitforprolongedperiodsoftime.(Youcouldalsoincreasetheloggingintervalonline80tosavespace.)EnteryourWi-Ficredentialsonlines138-140,andhitupload.ThenuploadthewebpagesandscriptstoSPIFFSusingTools>ESP8266SketchDataUpload.Makesureyouhavethetemperaturesensorconnected,asdescribedatthetopofthispage.Openaterminaltoseeifitworks.Youshouldseesomethinglikethis:

Connecting..........

ConnectedtoSSIDIPaddress: 192.168.1.2

OTAready

SPIFFSstarted.Contents: FSFile:/favicon-144x144.png,size:2.81KB FSFile:/temperatureGraph.js.gz,size:1.17KB FSFile:/temp.csv,size:42.50KB FSFile:/success.html.gz,size:456B FSFile:/edit.html.gz,size:700B FSFile:/main.css.gz,size:349B FSFile:/index.html.gz,size:795B FSFile:/manifest.json,size:169B FSFile:/favicon.ico.gz,size:1.91KB

mDNSresponderstarted:http://esp8266.localHTTPserverstarted.StartingUDPLocalport: 123TimeserverIP:216.229.0.179SendingNTPrequestNTPresponse: 1488666586TemperaturerequestedAppendingtemperaturetofile:1488666627,20.00TemperaturerequestedAppendingtemperaturetofile:1488666687,19.94Temperaturerequested...

Letitrunforacoupleofminutes,togathersometemperaturedata.Thenopenawebbrowser,andgotohttp://esp8266.local/.Youshouldgetagraphshowingthetemperaturecurve.Youcanusethearrowbuttonstotravelthroughtime,andthe+and-buttonstozoominorout.Theresetbuttonresetsthezoom,andjumpsbacktothepresent.Refreshrequeststhelatesttemperaturedata.

Ifyouwant,youcanstillgotohttp://esp8266.local/edit.htmltouploadnewfiles.

Thewebinterfaceshouldlooklikethis:

ItworksonWindows,LinuxandAndroid,butiOSseemstohavesomeproblemsrenderingthegraph(inbothChromeandSafari).

Page 49: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

EmailnotifierAnothergreatuseforIoTdevicesisdisplayingthingsliketrafficinformation,weatherforecast,socialmediaupdates...ThisrequiresustosendanHTTPGETrequesttotheserveroftheservicewe'dliketoaccess.MostpopularserviceshaveAPI(ApplicationProgrammingInterface)documentsthatexplainthatexplainhowyoucanretrievecertaininformation,andwhatformatthatinformationisin.Inthefollowingexample,we'lllookatGmailspecifically,butthecodeshouldbesimilarforotherservices.

ShowingthenumberofunreademailsTocommunicatewithGoogle'sGmailservers,wehavetoestablishasecureconnectiontotheserverandsendasecureHTTPSrequestwithouremailaddressandpassword.GmailwillthenrespondwithanXMLdocumentcontainingallkindsofinformation,like(partsof)yourmostrecentmessagesandthenumberofunreademails.

Tomakesurewedon'tsendourGooglepasswordtoamaliciousserver,wehavetochecktheserver'sidentity,usingtheSHA-1fingerprintoftheSSLcertificate.Thisisauniquesequenceofhexadecimalcharactersthatidentifiestheserver.

Allowingaccesstotheemailfeed

Theonlyway(Iknowof)togetemailinformationfromGoogleontheESPcurrentlyistheGoogleAtomFeed.Thisisanoldermethod,soyouhavetochangeyourGmailsettingstoallowaccesstothefeed.Gotohttps://www.google.com/settings/security/lesssecureappstoenableaccessfor"lesssecureapps":

Page 50: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to
Page 51: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

Untilthere'ssupportforthenewOAuth2protocolontheESP,we'llhavetousetheold,lesssecuremethod.

Hardware

ConnectanLED(+resistor)topin13,asanunreademailindicator.

TheCode

#include<WiFiClientSecure.h>//IncludetheHTTPSlibrary#include<ESP8266WiFi.h>//IncludetheWi-Filibrary#include<ESP8266WiFiMulti.h>//IncludetheWi-Fi-Multilibrary

ESP8266WiFiMultiwifiMulti;//CreateaninstanceoftheESP8266WiFiMulticlass,called'wifiMulti'

constchar*host="mail.google.com";//theGmailserverconstchar*url="/mail/feed/atom";//theGmailfeedurlconstinthttpsPort=443;//theporttoconnecttotheemailserver

//TheSHA-1fingerprintoftheSSLcertificatefortheGmailserver(seebelow)constchar*fingerprint="D390FC8207E60DC2CEF99D797FECF6E63ECB8BB3";

//TheBase64encodedversionofyourGmaillogincredentials(seebelow)constchar*credentials="ZW1haWwuYWRkcmVzc0BnbWFpbC5jb206cGFzc3dvcmQ=";

constbyteled=13;

voidsetup(){Serial.begin(115200);//StarttheSerialcommunicationtosendmessagestothecomputerdelay(10);Serial.println('\n');

pinMode(led,OUTPUT);

wifiMulti.addAP("ssid_from_AP_1","your_password_for_AP_1");//addWi-FinetworksyouwanttoconnecttowifiMulti.addAP("ssid_from_AP_2","your_password_for_AP_2");wifiMulti.addAP("ssid_from_AP_3","your_password_for_AP_3");

Serial.println("Connecting...");inti=0;while(wifiMulti.run()!=WL_CONNECTED){//WaitfortheWi-Fitoconnect:scanforWi-Finetworks,andconnecttothestrongestofthenetworksabovedelay(250);Serial.print('.');}Serial.println('\n');Serial.print("Connectedto");Serial.println(WiFi.SSID());//Telluswhatnetworkwe'reconnectedtoSerial.print("IPaddress:\t");Serial.println(WiFi.localIP());//SendtheIPaddressoftheESP8266tothecomputerSerial.println('\n');}

voidloop(){intunread=getUnread();if(unread==0){Serial.println("\r\nYou'vegotnounreademails");digitalWrite(led,LOW);}elseif(unread>0){Serial.printf("\r\nYou'vegot%dnewmessages\r\n",unread);digitalWrite(led,HIGH);}else{Serial.println("Couldnotgetunreadmails");}Serial.println('\n');delay(5000);}

intgetUnread(){//afunctiontogetthenumberofunreademailsinyourGmailinboxWiFiClientSecureclient;//UseWiFiClientSecureclasstocreateTLS(HTTPS)connectionSerial.printf("Connectingto%s:%d...\r\n",host,httpsPort);if(!client.connect(host,httpsPort)){//ConnecttotheGmailserver,onport443Serial.println("Connectionfailed");//Iftheconnectionfails,stopandreturnreturn-1;}

if(client.verify(fingerprint,host)){//ChecktheSHA-1fingerprintoftheSSLcertificateSerial.println("Certificatematches");

Page 52: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

}else{//ifitdoesn'tmatch,it'snotsafetocontinueSerial.println("Certificatedoesn'tmatch");return-1;}

Serial.print("RequestingURL:");Serial.println(url);

client.print(String("GET")+url+"HTTP/1.1\r\n"+"Host:"+host+"\r\n"+"Authorization:Basic"+credentials+"\r\n"+"User-Agent:ESP8266\r\n"+"Connection:close\r\n\r\n");//SendtheHTTPrequestheaders

Serial.println("Requestsent");

intunread=-1;

while(client.connected()){//Waitfortheresponse.TheresponseisinXMLformatclient.readStringUntil('<');//readuntilthefirstXMLtagStringtagname=client.readStringUntil('>');//readuntiltheendofthistagtogetthetagnameif(tagname=="fullcount"){//ifthetagis<fullcount>,thenextstringwillbethenumberofunreademailsStringunreadStr=client.readStringUntil('<');//readuntiltheclosingtag(</fullcount>)unread=unreadStr.toInt();//convertfromStringtointbreak;//stopreading}//ifthetagisnot<fullcount>,repeatandreadthenexttag}Serial.println("Connectionclosed");

returnunread;//Returnthenumberofunreademails}

Howitworks

Thesetupshouldbeprettyfamiliarbynow.TheonlynewthingisthegetUnread()function:First,itstartsanHTTPSconnectiontotheGmailserveronport443.Thenitchecksifthefingerprintofthecertificatematches,soitknowsthatit'stherealGoogleserver,andnotsomehacker.Ifthecertificatedoesn'tmatch,it'snotsafetosendthecredentialstotheserver.

Ifitmatches,wesendaHTTPGETrequesttotheserver:

GET/mail/feed/atomHTTP/1.1\r\nHost:mail.google.com\r\nAuthorization:BasicaVeryLongStringOfBase64EncodedCharacters=\r\nUser-Agent:ESP8266\r\nConnection:close\r\n\r\n

TherequestcontainstheURIwewanttoaccess(inthiscasethisistheAtomfeedURL),thehost(whichismail.google.com),andthebase64-encodedversionofyourlogincredentials.Asyoucansee,thedifferentlinesoftheheaderareseparatedbyaCRLF(CarriageReturn+LineFeed,\r\n).TwoCRLF'smarktheendoftheheader.TheGmailserverwillprocessourrequest,andsendthefeedasaresponseoverthesameHTTPSconnection.ThisresponseisanXMLdocument,thatconsistsoftagswithangledbrackets,justlikeHTML.Ifyouneedalotofdata,it'srecommendedtouseaproperXMLparserlibrary,butweonlyneedonetag,sowecanjustskimthroughtheresponsetextuntilwefindthe<fullcount>x</fullcount>tag.Thenumberinsidethistagisthenumberofunreademailsintheinbox.Wecanjustconvertittoaninteger,andstopreading.

ThisistheformatoftheXMLfeed,youcanseethefullcounttagonline5:

<?xmlversion="1.0"encoding="UTF-8"?><feedxmlns="http://purl.org/atom/ns#"version="0.3"><title>[email protected]</title><tagline>NewmessagesinyourGmailInbox</tagline><fullcount>5</fullcount><linkrel="alternate"href="https://mail.google.com/mail"type="text/html"/><modified>2017-03-05T15:54:06Z</modified><entry><title>Newsign-infromFirefoxonLinux</title><summary>Newsign-infromFirefoxonLinuxHiESP8266,YourGoogleAccountesp8266.test.mail@gmail.comwasjustusedtosigninfromFirefoxonLinux.ESP8266Testesp8266.test.mail@gmail.comLinuxSunday,</summary><linkrel="alternate"href="https://mail.google.com/[email protected]&amp;message_id=123456789&amp;view=conv&amp;extsrc=atom"type="text/html"/><modified>2017-03-05T15:52:45Z</modified><issued>2017-03-05T15:52:45Z</issued><id>tag:gmail.google.com,2004:123456789123456789</id><author><name>Google</name><email>[email protected]</email></author></entry>

...

</feed>

Theloopjustprintsthenumberofunreademails,andturnsonanLEDifyouhaveunreadmessages.

GettingthefingerprintoftheGmailserver

LikeImentionedbefore,weneedafingerprinttochecktheidentityoftheserver.Togetthisfingerprint,executethefollowingcommandinaterminal(Linux&Mac):

openssls_client-connectmail.google.com:443</dev/null2>/dev/null|opensslx509-fingerprint-noout-in/dev/stdin|sed's/://g'

Copythehexadecimalfingerprintstringandpasteitintothesketchonline12.Forexample:

constchar*fingerprint="D390FC8207E60DC2CEF99D797FECF6E63ECB8BB3";

Page 53: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

Encodingyourlogincredentials

Togetaccesstothefeed,youhavetoenteryouremailaddressandpassword.Youcan'tsendthemasplaintext,youhavetoencodethemtobase64first.Usethefollowingcommandinaterminal(Linux&Mac):

echo-n"[email protected]:password"|base64

Thenaddittoline15ofthesketch.Forexample:

constchar*credentials="ZW1haWwuYWRkcmVzc0BnbWFpbC5jb206cGFzc3dvcmQ=";

OtherAPIs

ManyservicessendtheirdatainJSONformat.Ifyoujustneedonepieceofinformation,youmaybeabletousethesameapproachofscanningtheentireJSONtextforacertainword,butit'smucheasiertouseaJSONparser,liketheArduinoJsonlibrary.ItwilldeserializetheJSONtext,andcreateaJSONobject,youcouldcompareittoanassociativearray.Youcanbrowsetheentiretreestructure,andeasilyfindthedatayou'relookingfor.Thedownsideisthatitusesmorememory.

Page 54: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

AdvancedDNSCaptivePortal

WhenusingtheESP8266inaccesspointmode,youprobablywanttoredirectuserstotherightpage.Youcandothisbycreatingacaptiveportal,usingDNS.It'sbasicallyjustaDNSserverthatwillconvertallhostnamestotheESP'sownIPaddress.ThistechniqueisalsousedbyopenWi-Finetworksthatredirectyoutoaloginpagebeforeyoucanstartbrowsingtheinternet.

Wi-Ficonfiguration

IfyouwanttobeabletochangetheWi-Ficonnectionsettingswithoutre-uploadingthecode,youcouldtakealookattheWiFiManagerlibrarybytzapu.Thiswilltrytoconnecttoknownnetworks,butifitfails,itwillstartaWi-Fiaccesspoint.Youcanthenconnecttothisaccesspoint,openthebrowser,andpickanetworktoconnectto.Thenewconfigurationissaved.TheWiFiManagerlibraryusesacaptiveportaltopresentyouwiththerightWi-Fisettingspage.YoucouldalsoimplementaWi-Fimanageryourself,oryoucanjustcheckouttheexamplethatcomeswiththeESP8266ArduinoCore(Examples>DNSServer>CaptivePortalAdvanced).

I²STheESP8266hasanI²SbusontheRXDpin.Itcanrunat80MHz,andhasDMA(directmemoryaccess),soit'sreallyfast.ItsmainpurposeistoconnectanI²SDAC(DigitaltoAnalogConverter)tohaveanaudiooutput,butyoucanuseitforotherthingsaswell.Forexample,CNLohrmanagedtotransmitanalogtelevision,byconnectinganantennawiretotheI²Spin.YoucanalsouseittocontrolWS2812BsLEDs.YoucanevenuseittocommunicateoverEthernet(notreallyuseful,anddefinitelynotrecommended,butitworks).AnothergreatusefortheI²Sbusisoutputtingdatatoshiftregisters.Thisgivesyouextraoutputsthatarereasonablyfast,forthingslikeLEDsorsteppermotors.

Otherexamples

YoucanfindlotsofotherexamplesintheArduinoIDE,I'drecommendtocheckthoseoutaswell.

YouTubeThere'ssomegreatchannelsonYouTubethatdoamazingthingswiththeESP8266.Here'sashortlistoftheonesI'mcurrentlyfollowing.Ifyou'vegotmorerecommendation,justleaveacomment!

AndreasSpiessCNLohrAcroboticMiikaKurkela

Page 55: Pieter P, 08-03-2017 A Beginner's Guide to the ESP8266 · A Beginner's Guide to the ESP8266 Pieter P, 08-03-2017 Some time ago, I wrote a Beginner's Guide to Arduino that seems to

Inconclusion...Congratulations,you'vereachedtheendofthisratherlongarticleonthebasicsoftheESP8266.Ihopethiswasinterestingtoyou,andthatyou'llusethisknowledgeforyourownDIYprojects.

Ifyouhaveanyremarksorifyouwanttohelpimprovethisguide,don'thesitatetoleaveacommentortosendmeamessage.

Thankyouforreading!Pieter,8-3-2017