NodeMcu簡(jiǎn)單應(yīng)用及拓展學(xué)習(xí)
前言
之所以想要學(xué)習(xí)使用NodeMcu,就是想要將其用在現(xiàn)實(shí)生活中,想要實(shí)現(xiàn)智能物聯(lián),將一些家用電氣(比如簡(jiǎn)單的燈)可用通過(guò)手機(jī)或電腦進(jìn)行簡(jiǎn)單的控制。當(dāng)然有人會(huì)認(rèn)為現(xiàn)在已經(jīng)有很對(duì)智能產(chǎn)品痰催,支持這些功能了,那還要花時(shí)間折騰做什么呢迎瞧?我的想法是夸溶,這些智能電器,或多或少存在各自的局限性夹攒,要么只能自己顧自己無(wú)法聯(lián)動(dòng)蜘醋,要么功能簡(jiǎn)單無(wú)法實(shí)現(xiàn)復(fù)雜場(chǎng)景應(yīng)用胁塞,而且用這些產(chǎn)品咏尝,往往需要在自己的手機(jī)上安裝各自的app,控制的東西越多啸罢,需要安裝的東西也越多编检,反而違背了使用的初衷,我學(xué)習(xí)NodeMcu的目的扰才,就是希望能實(shí)現(xiàn)各種產(chǎn)品的聯(lián)動(dòng)允懂,同時(shí)簡(jiǎn)化自己的操作,讓機(jī)器替我們思考甚至做決定衩匣,以及滿足自己的個(gè)性化定制需要蕾总。
我的目標(biāo)可能會(huì)比較難實(shí)現(xiàn)粥航,我愿意一步一步學(xué)習(xí)實(shí)踐吧。
這里我將從最基礎(chǔ)開(kāi)始學(xué)習(xí)生百,慢慢深入應(yīng)用場(chǎng)景递雀,希望通過(guò)這一過(guò)程,從易到難蚀浆,逐漸掌握需要的技能缀程。下面要寫的東西可能比較啰嗦,慢慢來(lái)吧市俊。
1杨凑、從應(yīng)用著手
學(xué)習(xí)一項(xiàng)技能,最好是從自己實(shí)際需要的著手摆昧,先提出自己的需要:遠(yuǎn)程控制燈的開(kāi)關(guān)(最簡(jiǎn)單的智能燈)撩满,當(dāng)然只要買個(gè)智能燈或是智能插座配合亦或是用433Hz配合智能遙控,都能實(shí)現(xiàn)绅你,這里我們用NodeMcu試試鹦牛。
首先從NodeMcu的點(diǎn)燈程序開(kāi)始吧:
1.1 NodeMcu的點(diǎn)燈程序
最簡(jiǎn)單的點(diǎn)亮板上的LED程序,之前文章提到過(guò)
gpio.mode(0,gpio.OUTPUT)
--開(kāi)啟gpio16端口--
gpio.write(0,gpio.LOW)
--置端口輸出低電位勇吊,燈亮--
gpio.write(0,gpio.HIGH)
--置端口輸出高電位曼追,燈滅--
相關(guān)電路原理見(jiàn)2.NodeMcu上手準(zhǔn)備中點(diǎn)燈原理圖.png。
就可以看到靠近USB口的LED點(diǎn)亮汉规。
1.2 遠(yuǎn)程點(diǎn)亮LED
1.2.1 連接WIFI
遠(yuǎn)程點(diǎn)亮礼殊,肯定需要NodeMcu連上WIFI了,根據(jù)官方教程連接路由
print(wifi.sta.getip())
--打印wifi連接端口针史,此時(shí)未連接晶伦,輸出nil--
wifi.setmode(wifi.STATION)
--置NodeMcu為wifi為STATION工作模式--
wifi.sta.config("SSID","password")
--設(shè)置所連接wifi的參數(shù),SSID為路由名稱啄枕,password為路由密碼(自己設(shè)置需替換自己的路由)--
print(wifi.sta.getip())
--輸出連接上wifi后nodeMcu的地址--
當(dāng)然也可以這么寫
SSID="你的路由名"
password="你的路由密碼"
print(wifi.sta.getip())
wifi.setmode(wifi.STATION)
wifi.sta.config(SSID,password)
print(wifi.sta.getip())
注意不要把注釋也放到ESplorer中運(yùn)行婚陪,我就這樣出錯(cuò)了
這里很奇怪,為什么結(jié)果里是先出IP地址再出nil频祝,歡迎網(wǎng)友解答泌参。
1.2.2 建立服務(wù)器
接著需要設(shè)置nodeMcu為服務(wù)器,還是參照官方教程常空,這里復(fù)制官網(wǎng)的代碼:
srv=net.createServer(net.TCP)
--創(chuàng)建一個(gè)server
srv:listen(80,function(conn)
conn:on("receive",function(conn,payload)
print(payload)
conn:send("<h1> Hello, NodeMcu.</h1>")
end)
end)
這部分語(yǔ)法這里稍微解釋:
srv=net.createServer(net.TCP)
這是創(chuàng)建一個(gè)server
后面是2部分組成沽一,第一部分是net.server 子模塊,相關(guān)語(yǔ)法是
listen()
描述
偵聽(tīng)指定ip地址的端口漓糙。
語(yǔ)法
net.server.listen(port,[ip],function(net.socket))
參數(shù)
port: 端口號(hào)
ip:ip地址字符串铣缠,可以省略
function(net.socket): 連接創(chuàng)建成功的回調(diào)函數(shù),可以作為參數(shù)傳給調(diào)用函數(shù)。
返回值
nil
第二部分是net.socket 子模塊
on()
描述
向事件注冊(cè)回調(diào)函數(shù)蝗蛙。
語(yǔ)法
on(event, function cb())
參數(shù)
event: 字符串蝇庭,取值為: "connection", "reconnection", "disconnection", "receive", "sent"
function cb(net.socket, [string]): 回調(diào)函數(shù)。第一個(gè)參數(shù)是socket.
如果事件是"receive", 第二個(gè)參數(shù)則為接收到的字符串捡硅。
返回值
nil
send()
描述
通過(guò)連接向遠(yuǎn)端發(fā)送數(shù)據(jù)遗契。
語(yǔ)法
send(string, function(sent))
參數(shù)
string: 待發(fā)送的字符串
function(sent): 發(fā)送字符串后的回調(diào)函數(shù)。
返回值
nil
這里解釋一下"srv:listen()"病曾,"conn:on()"牍蜂,"conn:send()",這里用冒號(hào)等價(jià)"srv.listen(self)"泰涂,"conn.on(self)"鲫竞,"conn.send(self)",這樣對(duì)里面提到的語(yǔ)法就能比較好理解逼蒙,其中self代表conn自己从绘。"end"是對(duì)"function()"的結(jié)束。
conn:send("<h1> Hello, NodeMcu.</h1>")
這部分是服務(wù)器發(fā)送"<h1> Hello, NodeMcu.</h1>"
給接收者是牢,這部分是可以用html代碼寫的僵井,如果寫得復(fù)雜些,可以用更漂亮的網(wǎng)頁(yè)展示驳棱,但nodeMcu內(nèi)存較小批什,每次只能發(fā)送1460byte,需要對(duì)網(wǎng)頁(yè)代碼進(jìn)行分段傳送社搅。(如何分段,可以看下面幾個(gè)作者的文章)
這部分代碼如果還是不太好理解形葬,可以參看@qq_32543253寫得NODEMCU調(diào)試心得6 - 關(guān)于網(wǎng)絡(luò)協(xié)議HTTP合呐,也可以看看@謝mingmin寫的9、nodeMCU學(xué)習(xí)筆記--net模塊笙以,對(duì)于相關(guān)的教程可以參看官方的教程中關(guān)于net部分教程淌实。
還需要再解釋一下,代碼中conn或是srv可以用其它字符串替代猖腕,它是繼承了net相關(guān)模塊的功能拆祈。
1.2.3 使用服務(wù)器
合并連接WIFI和建立服務(wù)器兩部分代碼
SSID="你的路由名"
password="你的路由密碼"
print(wifi.sta.getip())
wifi.setmode(wifi.STATION)
wifi.sta.config(SSID,password)
print(wifi.sta.getip())
srv=net.createServer(net.TCP)
--創(chuàng)建一個(gè)server
srv:listen(80,function(conn)
conn:on("receive",function(conn,payload)
print(payload)
conn:send("<h1> Hello, NodeMcu.</h1>")
end)
end)
運(yùn)行
這時(shí)NodeMcu已經(jīng)作為一個(gè)http服務(wù)器開(kāi)始運(yùn)行了。用在同一局域網(wǎng)的電腦的瀏覽器打開(kāi)對(duì)應(yīng)http服務(wù)器的地址:192.168.8.145谈息,就可以看到如下圖結(jié)果
1.2.4 利用服務(wù)器點(diǎn)燈
直接上代碼
SSID="你的路由名"
password="你的路由密碼"
print(wifi.sta.getip())
wifi.setmode(wifi.STATION)
wifi.sta.config(SSID,password)
print(wifi.sta.getip())
srv=net.createServer(net.TCP)
--創(chuàng)建一個(gè)server
srv:listen(80,function(conn)
conn:on("receive",function(conn,payload)
print(payload)
gpio.mode(0,gpio.OUTPUT)
gpio.write(0,gpio.LOW)
conn:send("<h1> Hello, NodeMcu.</h1>")
end)
end)
就增加了點(diǎn)燈的2行代碼缘屹,記得按一下nodeMcu板上的RST,再在ESPlorer中的run點(diǎn)一下侠仇,再寫入代碼,重新Save to Esp,這時(shí)代碼才更新好逻炊。這時(shí)重新打開(kāi)瀏覽器輸入http服務(wù)器的地址:192.168.8.145互亮,就可以看到NodeMcu上的LED燈點(diǎn)亮了。print(payload)
是可以在ESPlorer打印從瀏覽器客戶端收到的payload信息余素,可以刪去豹休。
1.2.5 能點(diǎn)燈還需要關(guān)燈
上面只是簡(jiǎn)單實(shí)現(xiàn)了點(diǎn)燈,但要實(shí)現(xiàn)控制隨時(shí)點(diǎn)亮熄滅桨吊,還不行威根,所以還要改進(jìn)。
SSID="路由器名稱"
password="路由器密碼"
print(wifi.sta.getip())
wifi.setmode(wifi.STATION)
wifi.sta.config(SSID,password)
print(wifi.sta.getip())
--連接路由器
pin=0
gpio.mode(pin,gpio.OUTPUT)
gpio.write(pin,gpio.HIGH)
--開(kāi)啟gpio16端口
srv=net.createServer(net.TCP)
--創(chuàng)建一個(gè)server
srv:listen(80,function(conn)
conn:on("receive",function(conn,payload)
print(payload)
--打印從瀏覽器客戶端收到的payload信息
local _, _, method, vars = string.find(payload, "([A-Z]+) /(.+) HTTP")
if(vars == "off")then
gpio.write(pin, gpio.HIGH)
--滅燈
conn:send("<h1> Light OFF.</h1>")
--傳送給客戶端 Light OFF.的頁(yè)面
elseif(vars == "on")then
gpio.write(pin, gpio.LOW)
--開(kāi)燈
conn:send("<h1> Light ON.</h1>")
--傳送給客戶端 Light ON.的頁(yè)面
end
end)
end)
上述代碼视乐,如果復(fù)制洛搀,請(qǐng)刪掉注釋再運(yùn)行!S拥怼留美!
這個(gè)代碼實(shí)現(xiàn)使,在同一局域網(wǎng)客戶端(手機(jī)瀏覽器或電腦瀏覽器)輸入http://192.168.8.145/off
熄滅板上的LED燈伸刃,輸入http://192.168.8.145/on
開(kāi)啟板上的LED燈谎砾。
這里解釋一下local _, _, method, vars = string.find(payload, "([A-Z]+) /(.+) HTTP")
,這個(gè)我也開(kāi)始學(xué)也弄不太懂捧颅,參看@qq_32543253的教程景图,明白了。其實(shí)就是Lua中的string.find()
語(yǔ)法的應(yīng)用碉哑。具體這里不展開(kāi)了症歇,大家可以百度。這里的應(yīng)用使采用string.find()
匹配payload
中的字符谭梗,提取出對(duì)應(yīng)([A-Z]+)
和(.+)
的字符忘晤,賦值給method
, vars
,前面2個(gè)_,
是虛變量激捏,我們簡(jiǎn)化一下這個(gè)代碼
payload="GET /on HTTP/1.1"
local a, b, method, vars = string.find(payload, "([A-Z]+) /(.+) HTTP")
print(a,b,method,vars)
可以看到此時(shí)a=1设塔,b=12,method="GET"远舅,vars="on"闰蛔,a和b對(duì)應(yīng)匹配字符的起始1和結(jié)束12(注意不要忽略空格)。
再看一下http://192.168.8.145/on
中on
作用图柏,回到之前的程序序六,當(dāng)我們輸入http://192.168.8.145/on
print(payload)
可以看到第1行是GET /on HTTP/1.1
,說(shuō)明網(wǎng)址中的on
被傳送過(guò)去了蚤吹,程序就是這個(gè)被網(wǎng)址傳送過(guò)去的字符進(jìn)行了判斷控制例诀。當(dāng)然我們可以用其它字符随抠,其它判斷來(lái)實(shí)現(xiàn)更復(fù)雜的控制。
如果html寫得好繁涂,可以通過(guò)編制html按鈕拱她,來(lái)進(jìn)行信息傳送,原理是一樣的扔罪。但個(gè)人覺(jué)得由于nodeMcu的機(jī)能限制秉沼,不太適合太復(fù)雜太精美的html再進(jìn)行復(fù)雜控制,不如就用這樣簡(jiǎn)單的網(wǎng)址字符輸入控制(其實(shí)是我自己html還不會(huì))矿酵。
我們可以選擇更精美的UI和更優(yōu)秀的硬件做服務(wù)器唬复,而NodeMcu就做控制。這時(shí)后話了全肮,下一節(jié)我們?cè)囋嘾omoticz遠(yuǎn)程控制NodeMcu敞咧。
1.2.6 程序隨NodeMcu啟動(dòng)而運(yùn)行
前面的控制,都是在線調(diào)試而成倔矾,如何使自己的程序成為初始化程序妄均,即NodeMcu啟動(dòng)后就能直接運(yùn)行,不用點(diǎn)ESPlorer中的run哪自。這里就需要用到init.lua
丰包,它就是NodeMcu開(kāi)機(jī)啟動(dòng)項(xiàng)。
方案1
這里我們可以把之前寫的服務(wù)器代碼用另存為 init.lua
寫入板子壤巷。然后重啟邑彪,把NodeMcu插在移動(dòng)電源上或5V的充電器,再試試用同局域網(wǎng)的手機(jī)或電腦輸入控制網(wǎng)址http://192.168.8.145/on
胧华,看看板上LED是不是已經(jīng)點(diǎn)亮了寄症。
方案2
或者還可以這么調(diào)用
dofile("之前服務(wù)器程序文件名(包括后綴)")
比如
dofile("server20170316.lua")
存儲(chǔ)為init.lua
,然后將服務(wù)器程序?qū)懭刖囟賹懭?code>init.lua有巧。再重啟把NodeMcu插在移動(dòng)電源上或5V的充電器試試。是不是也成功悲没。
結(jié)尾
這一章寫了很多篮迎,比較啰嗦瑣碎,但我想盡可能仔細(xì)示姿,把一些東西解釋清楚甜橱,這即加深了自己的學(xué)習(xí)理解,同時(shí)方便大家實(shí)踐栈戳。如果這里點(diǎn)燈實(shí)踐不成功岂傲,歡迎討論。
總結(jié)一些吧子檀,本節(jié)從點(diǎn)亮LED開(kāi)始镊掖,再討論NodeMcu的WIFi連接乃戈,服務(wù)器的建立,再到簡(jiǎn)單的命令控制堰乔,最終實(shí)現(xiàn)了遠(yuǎn)程LED的點(diǎn)亮控制偏化。
這種網(wǎng)上教程比較多脐恩,大家也可以多多借鑒镐侯。
參考
官方教程:http://www.nodemcu.com/index_cn.html
@qq_32543253的博客:http://blog.csdn.net/qq_32543253/article/details/53240851
@謝mingmin的簡(jiǎn)書(shū):http://www.reibang.com/p/2535d6374a2b
官方的net教程:https://nodemcu.readthedocs.io/en/master/en/modules/net/