Introduction: ESP8266 Based Web Configurable Wifi General Purpose Control (Part II)

NOTE: A ready to go board can be purchased here

On Part II I will go over how to program the ESP8266 so a USB to serial module and a terminal is not necessary: it will all be done via web. Also, I will explain how to drive a binary counter and control 4 relays (multi on/multi off) using GPIO0 as control and GPIO2 as reset. This way the ESP8266 really turns into a powerful device that can be added to any automation project and its easy to program on site.

You can get more details on my projects at Horacio Bouzas Web site

The control firmware

The firmware needs to be able to allow the user to connect to the module and set the SSID and password of the network the module will be connected to. The steps to design the firmware are as follows:

1. set the module to server (AP) mode

2. set a name and password

3. create a server

4. listen on port 80

5. module address is 192.168.4.1

6. present a web page asking for SSID and password

7. switch to Station mode and set SSID and password

8. connect to network

9. start listening for events coming on the ip address assigned by the network and port 9999

Here is the code to do it:

file.open("init.lua","w")

file.writeline([[print("WIFI control")]])

-- put module in AP mode

file.writeline([[wifi.setmode(wifi.SOFTAP)]])

file.writeline([[print("ESP8266 mode is: " .. wifi.getmode())]])

file.writeline([[cfg={}]])

-- Set the SSID of the module in AP mode and access password

file.writeline([[cfg.ssid="ESP_STATION"]])

file.writeline([[cfg.pwd="the_ESP8266_WIFI_password"]])

file.writeline([[if ssid and password then]])

file.writeline([[print("ESP8266 SSID is: " .. cfg.ssid .. " and PASSWORD is: " .. cfg.password)]])

file.writeline([[end]])

-- Now you should see an SSID wireless router named ESP_STATION when you scan for available WIFI networks

-- Lets connect to the module from a computer of mobile device. So, find the SSID and connect using the password selected

file.writeline([[wifi.ap.config(cfg)]])

file.writeline([[ap_mac = wifi.ap.getmac()]])

-- create a server on port 80 and wait for a connection, when a connection is coming in function c will be executed

file.writeline([[sv=net.createServer(net.TCP,30)]])

file.writeline([[sv:listen(80,function(c)]])

file.writeline([[c:on("receive", function(c, pl)]])

-- print the payload pl received from the connection

file.writeline([[print(pl)]])

file.writeline([[print(string.len(pl))]])

-- wait until SSID comes back and parse the SSID and the password

file.writeline([[print(string.match(pl,"GET"))]])

file.writeline([[ssid_start,ssid_end=string.find(pl,"SSID=")]])

file.writeline([[if ssid_start and ssid_end then]])

file.writeline([[amper1_start, amper1_end =string.find(pl,"&", ssid_end+1)]])

file.writeline([[if amper1_start and amper1_end then]])

file.writeline([[http_start, http_end =string.find(pl,"HTTP/1.1", ssid_end+1)]])

file.writeline([[if http_start and http_end then]])

file.writeline([[ssid=string.sub(pl,ssid_end+1, amper1_start-1)]])

file.writeline([[password=string.sub(pl,amper1_end+10, http_start-2)]])

file.writeline([[print("ESP8266 connecting to SSID: " .. ssid .. " with PASSWORD: " .. password)]])

file.writeline([[if ssid and password then]])

file.writeline([[sv:close()]])

-- close the server and set the module to STATION mode

file.writeline([[wifi.setmode(wifi.STATIONAP)]])

file.writeline([[print("ESP8266 mode now is: " .. wifi.getmode())]])

-- configure the module wso it can connect to the network using the received SSID and password

file.writeline([[wifi.sta.config(ssid,password)]])

file.writeline([[print("Setting up ESP8266 for station mode…Please wait.")]])

file.writeline([[tmr.delay(10000000)]])

file.writeline([[print("ESP8266 STATION IP now is: " .. wifi.sta.getip())]])

file.writeline([[print("ESP8266 AP IP now is: " .. wifi.ap.getip())]])

-- now the module is configured and connected to the network so lets start setting things up for the control logic

file.writeline([[gpio.mode(8,gpio.OUTPUT)]])

file.writeline([[gpio.mode(9,gpio.OUTPUT)]])

file.writeline([[tmr.delay(10) ]])

file.writeline([[gpio.write(8,gpio.HIGH)]])

file.writeline([[tmr.delay(10)]])

file.writeline([[gpio.write(8,gpio.LOW)]])

file.writeline([[sv=net.createServer(net.TCP, 30) ]])

file.writeline([[sv:listen(9999,function(c)]])

file.writeline([[c:on("receive", function(c, pl)]])

file.writeline([[if tonumber(pl) ~= nil then]])

file.writeline([[if tonumber(pl) >= 1 and tonumber(pl) <= 16 then]])

file.writeline([[print(tonumber(pl))]])

file.writeline([[tmr.delay(10)]])

file.writeline([[gpio.write(8,gpio.HIGH)]])

file.writeline([[tmr.delay(10)]])

file.writeline([[gpio.write(8,gpio.LOW)]])

file.writeline([[for count =1,tonumber(pl) do]])

file.writeline([[ print(count)]])

file.writeline([[tmr.delay(10) ]])

file.writeline([[ gpio.write(9,gpio.LOW)]])

file.writeline([[tmr.delay(10)]])

file.writeline([[gpio.write(9,gpio.HIGH)]])

file.writeline([[c:send("Sequence finished") ]])

file.writeline([[end]])

file.writeline([[end]])

file.writeline([[end]])

file.writeline([[print("ESP8266 STATION IP now is: " .. new_ip)]])

file.writeline([[c:send("ESP8266 STATION IP now is: " .. new_ip) ]])

file.writeline([[c:send("Action completed") ]])

file.writeline([[end)]])

file.writeline([[end)]])

file.writeline([[end]])

file.writeline([[end]])

file.writeline([[end]])

file.writeline([[end]])

-- this is the web page that requests the SSID and password from the user

file.writeline([[c:send(" ")]])

file.writeline([[c:send(" ")]])

file.writeline([[c:send(" ")]])

file.writeline([[c:send("ESP8266 Wireless control setup")]])

file.writeline([[mac_mess1 = "The module MAC address is: " .. ap_mac]])

file.writeline([[mac_mess2 = "You will need this MAC address to find the IP address of the module, please take note of it."]])

file.writeline([[c:send("" .. mac_mess1 .. "")]])

file.writeline([[c:send("" .. mac_mess2 .. "")]])

file.writeline([[c:send("Enter SSID and Password for your WIFI router")]])

file.writeline([[c:send("

")]])

file.writeline([[c:send("

")]])

file.writeline([[c:send("SSID:")]])

file.writeline([[c:send("")]])

file.writeline([[c:send("
")]])

file.writeline([[c:send("Password:")]])

file.writeline([[c:send("")]])

file.writeline([[c:send("")]])

file.writeline([[end)]])

file.writeline([[end)]])

file.close()

Step 1: Loading the Firmware and Testing

Loading the firmware and testing

Load the file with the code written above as explained in Part I. Once the file is sent to the module you should do a node.restart() and will see that the ESP8266 is now in mode 2 or AP mode, server.

OK. The module is now in AP mode so it is like a WIFI router and you should see ESP_STATION on your list of WIFI networks.

Now connect to ESP_STATION using the password that you have programmed into the firmware, "the_ESP8266_WIFI_password" above. Now connect to 192.168.4.1 from a browser. You should see the webpage below. Enter SSID and password of your WIFI network so the ESP8266 can connect to it.

After a few seconds of waiting you should receive a message on the web browser with the IP address assigned to the module by your router; if you get a 0.0.0.0, just refresh the browser pointing to 192.168.4.1 and you should get the new IP address. Since for this test we are monitoring the ESP8266 through a serial terminal, lets check what the output was:

On your browser you should see a message showing the module IP address after connecting to your WIFI network

Now the ESP8266 is connected to our WIFI network and has IP address 192.168.1.49. However, if you don;t get the browser to show the IP address, you can always refer to the MAC address of the ESP8266 shown on the SSID/Password entry page and the user will have to find the IP address by going into the router setup, depending on what kind of router that is. I will in the future figure out how to ensure that IP address is always posted back to the browser.

Summary

On Part II we saw how to configure the ESP8266 directly from a web browser and bypassing the USB to serial. Now we are getting closer to something that can be commercialized. On Part III (yes, sorry, I chopped it into 3 parts) I will show how to connect the GPIO0 and GPIO2 signals to some binary counters and driver to drive relays or any other device.

Comments

author
Dante8799 (author)2016-12-10

Can you please send the full code?

author
rishi5678 (author)2016-06-21

Hey can you please send the full code.

Its not working properly.

Thank you

author
b4surani (author)2016-02-01

can you provide script?

author
TimothyG20 (author)2016-01-10

Code is incomplete. This will not work at all until the author finishes this instructable.

author
BamboK (author)2015-11-08

Great! I was confusion cause I dont know much about HTML, change a little bit and its kicking! thanks so much Horacio.

Bambo: ex halliburton worker ;) casing shotter.

author
Divinity83 (author)2015-09-27

init.lua:80: unfinished string near '"'

Also, the code posted here is not the actual code used by the poster. So errors are to be expected.

author
siddhc (author)2015-09-21

Hi, nice article. Thanks

While reading on the net, I came across this line - "The wifi.setmode(wifi.STATION) statement should be done only if we are using a static IP ? It should not be used if we use a dynamic IP (i.e. in a DHCP environment)."

Hi, is this statement true ? Please let me know what is the reason behind it ?

author
manoelps (author)2015-09-10

After I recorded the code, my ESP8266 is restarting and is not allowing run any command, need to rewrite the firmware. It just keep restarting every seconds.

here is output:

NodeMCU 0.9.5 build 20150318 powered by Moon 5.1.4
bÊÊf¾ø? jrüóÆ? ªÄrF! úAÊöø

NodeMCU 0.9.5 build 20150318 powered by Moon 5.1.4
7! THE! G, ÿ? EB "û? Ev0] It?) ³O

NodeMCU 0.9.5 build 20150318 powered by Moon 5.1.4
"ʃ
? þ: 6 ®? ùAÂH | ?? ³O

Someone who had managed to solve this problem?

author
jimoconnell (author)2015-08-05

As I was using the ESPlorer IDE, I created a file that was compatible with that program:

https://gist.github.com/jimoconnell/39ea6673aa25e0...

I commented out a few lines that tried to print the IP address, as concatenating a NIL caused my device to crash. I also changed the SSID and password to:

cfg.ssid="ESP8266";cfg.pwd="passwordpassword";

(They were easier to type on my phone, which I was using to test and config.)

author
msw101144 (author)jimoconnell2015-08-09

I loaded this and am getting reset -reset etc. I think it may be WDT , I'm using NodeMCU 5.1.4.

How do you reset the WDT or increase it's value

author
jimoconnell (author)msw101144 2015-08-09

I haven't run into that.

There is a function 'ets_wdt_disable()' mentioned here:
http://www.esp8266.com/viewtopic.php?f=14&t=537

I wish I could offer more help, but I am new to this.

author
msw101144 (author)jimoconnell2015-08-11

Jim, I Will try your referenced FW...thx Mike I apparently don't understand how all this works. step 3,4 -open server and listen port 80 , I would think the next code would be send the web page,,but that code is at the bottom , How does this code know where the code for the webpage is ,, I'm confused,,,

The 0.9.6 FW gets reset after open client - trying to concatenate a nil value

getIP(), I think

author
msw101144 (author)jimoconnell2015-08-09

Loads with 0.9.6 integer or float with NodeMCU Loader ,, I'm getting insufficent memory with ESPlorer... 0.9.5 just gives reset -reset

author
ubuntoscar (author)2015-06-16

Finally i got it!!!, thanks a lot for push me to find the solution Mr HoracioBouzas

author
ubuntoscar (author)2015-06-04

Thanks a lot for share your knowledge, but...can you share the whole code, i mean:

c:send("<!DOCTYPE html> ")

c:send("<html> ")

c:send("<body> ")

c:send("<h1>ESP8266 Wireless control setup</h1>")

mac_mess1 = "The module MAC address is: " .. ap_mac

mac_mess2 = "You will need this MAC address to find the IP address of the module, please take note of it."

c:send("<h2>" .. mac_mess1 .. "</h2>")

c:send("<h2>" .. mac_mess2 .. "</h2>")

c:send("<h2>Enter SSID and Password for your WIFI router</h2>")

c:send("</form> </html>")

c:send("<form action='' method='get'>")

c:send("SSID:")

c:send("<input type='text' name='SSID' value='' maxlength='100'/>")

c:send("<br/>")

c:send("Password:")

c:send("<input type='text' name='Password' value='' maxlength='100'/>")

c:send("<input type='submit' value='Submit' />")

Or are you trying to make us a little bit more ingenious and try by ourselves get the code....

Thanks in advance :)

author
ashwini3112 (author)2015-04-28

now i am able to set the wifi mode as 3 as well as i am getting ip of my module. but when i search for the wifi network then my wifi modules network is not available in that least.

i am using nodemcu firmware

author
james.heires (author)2015-04-23

OK, I figured out how to write my lua script to my 8266 non-volatile memory, thanks to (https://github.com/4refr0nt/luatool). Next, I will use luatool to write your code to my 8266, but I have a question:

Can you share your HTML code shown in the screen shot at top of this page? There must be some interface between the web page and the lua script that enables them to communicate...

Thanks.

author

OK - I think I see your web page code in the lua source now. The screen shot must be from a slightly different web page, as there are subtle differences, and I don't see any HTML markup to control font size, etc. as shown in your web page screen shot.

author
mano1979 (author)2015-04-04

I get the same error and constant reboot. Any updates on this yet? Why does it work for the original poster and not for us?

author
james.heires (author)mano19792015-04-19

mano,

After converting the code above to straight lua commands (interactive style - removing all file operations), I, too, get a reboot partway through the command set. Here's a partial output from CoolTerm (notice the restart response at line 3). Then errors are returned on various lines, perhaps because the restart caused the 8266 to miss come characters that were being sent by CoolTerm:


>> ......print(tonumber(pl))
>> ......tmr.delay(10)
c_GORSvbFjSvfJSzfnBCNodeMcu 0.9.5 build 20150106 powered by Lua 5.1.4
lua: init.lua:80: unfinished string near '"'
> ......gpio.write(8,gpio.LOW)
>
> ......for count =1,tonumber(pl) do
>>
>> .......print(count)
>> .......tmr.delay(10)
>>
>> .......gpio.write(9,gpio.LOW)
>> .......tmr.delay(10)
>> .......gpio.write(9,gpio.HIGH)
>> .......c:send("Sequence finished")
>> ......end
stdin:1: 'for' limit must be a number
>
> .....end
stdin:1: '<eof>' expected near 'end'
>
> ....end
stdin:1: '<eof>' expected near 'end'
>
author
rannabat (author)2015-03-27

Super post. Thanks for sharing. Question: after i did everthing, my device is hard resetting itself and it is not allowing me to go to command mode and it is not accepting any commands. it just keep restarting every few seconds.

here is output

NodeMCU 0.9.5 build 20150213 powered by Lua 5.1.4

Hard Restart Friday, March 27, 2015 12:52:45

FYI: NodeMcu 0.9.5 build 20150311 is available

üÊ1

ÿ¤§1än]ô1ä”}†ÎLêá

NodeMCU 0.9.5 build 20150213 powered by Lua 5.1.4

Hard Restart Friday, March 27, 2015 12:52:49

B!F¤§Î¤)]ä1ä”}×1¤ïá

NodeMCU 0.9.5 build 20150213 powered by Lua 5.1.4

Hard Restart Friday, March 27, 2015 12:52:52

About This Instructable

72,034views

57favorites

License:

Bio: Schlumberger Open Software Technology, a software framework for developing geo-science applications. 5 patents Visit http://t.co/QW8tQhMNgW
More by HoracioBouzas:ESP8266 based web configurable wifi general purpose control (Part II)ESP8266 based web configurable wifi general purpose control (Part III)ESP8266 based web configurable wifi general purpose control (Part I)
Add instructable to: