4.NodeMcu簡單應(yīng)用及拓展學(xué)習(xí)

NodeMcu簡單應(yīng)用及拓展學(xué)習(xí)

前言

之所以想要學(xué)習(xí)使用NodeMcu,就是想要將其用在現(xiàn)實生活中,想要實現(xiàn)智能物聯(lián),將一些家用電氣(比如簡單的燈)可用通過手機或電腦進(jìn)行簡單的控制。當(dāng)然有人會認(rèn)為現(xiàn)在已經(jīng)有很對智能產(chǎn)品,支持這些功能了,那還要花時間折騰做什么呢?我的想法是,這些智能電器,或多或少存在各自的局限性,要么只能自己顧自己無法聯(lián)動,要么功能簡單無法實現(xiàn)復(fù)雜場景應(yīng)用,而且用這些產(chǎn)品,往往需要在自己的手機上安裝各自的app,控制的東西越多,需要安裝的東西也越多,反而違背了使用的初衷,我學(xué)習(xí)NodeMcu的目的,就是希望能實現(xiàn)各種產(chǎn)品的聯(lián)動,同時簡化自己的操作,讓機器替我們思考甚至做決定,以及滿足自己的個性化定制需要。
我的目標(biāo)可能會比較難實現(xiàn),我愿意一步一步學(xué)習(xí)實踐吧。
這里我將從最基礎(chǔ)開始學(xué)習(xí),慢慢深入應(yīng)用場景,希望通過這一過程,從易到難,逐漸掌握需要的技能。下面要寫的東西可能比較啰嗦,慢慢來吧。

1、從應(yīng)用著手

學(xué)習(xí)一項技能,最好是從自己實際需要的著手,先提出自己的需要:遠(yuǎn)程控制燈的開關(guān)(最簡單的智能燈),當(dāng)然只要買個智能燈或是智能插座配合亦或是用433Hz配合智能遙控,都能實現(xiàn),這里我們用NodeMcu試試。
首先從NodeMcu的點燈程序開始吧:

1.1 NodeMcu的點燈程序

最簡單的點亮板上的LED程序,之前文章提到過

gpio.mode(0,gpio.OUTPUT) 
--開啟gpio16端口--
gpio.write(0,gpio.LOW)
--置端口輸出低電位,燈亮--
gpio.write(0,gpio.HIGH) 
--置端口輸出高電位,燈滅--

相關(guān)電路原理見2.NodeMcu上手準(zhǔn)備中點燈原理圖.png。

ESPlorer輸入前面2段點亮LED

就可以看到靠近USB口的LED點亮。

1.2 遠(yuǎn)程點亮LED

1.2.1 連接WIFI

遠(yuǎn)程點亮,肯定需要NodeMcu連上WIFI了,根據(jù)官方教程連接路由

print(wifi.sta.getip())
--打印wifi連接端口,此時未連接,輸出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中運行,我就這樣出錯了

運行截圖.png

這里很奇怪,為什么結(jié)果里是先出IP地址再出nil,歡迎網(wǎng)友解答。

1.2.2 建立服務(wù)器

接著需要設(shè)置nodeMcu為服務(wù)器,還是參照官方教程,這里復(fù)制官網(wǎng)的代碼:

srv=net.createServer(net.TCP) 
--創(chuàng)建一個server
srv:listen(80,function(conn) 
    conn:on("receive",function(conn,payload) 
    print(payload) 
    conn:send("<h1> Hello, NodeMcu.</h1>")
    end) 
end)

這部分語法這里稍微解釋:

srv=net.createServer(net.TCP) 

這是創(chuàng)建一個server
后面是2部分組成,第一部分是net.server 子模塊,相關(guān)語法是

listen()
描述
偵聽指定ip地址的端口。
語法
net.server.listen(port,[ip],function(net.socket))
參數(shù)
port: 端口號
ip:ip地址字符串,可以省略
function(net.socket): 連接創(chuàng)建成功的回調(diào)函數(shù),可以作為參數(shù)傳給調(diào)用函數(shù)。
返回值
nil

第二部分是net.socket 子模塊

on()
描述
向事件注冊回調(diào)函數(shù)。
語法

on(event, function cb())
參數(shù)
event: 字符串,取值為: "connection", "reconnection", "disconnection", "receive", "sent"
function cb(net.socket, [string]): 回調(diào)函數(shù)。第一個參數(shù)是socket.
如果事件是"receive", 第二個參數(shù)則為接收到的字符串。
返回值
nil

send()
描述
通過連接向遠(yuǎn)端發(fā)送數(shù)據(jù)。
語法
send(string, function(sent))
參數(shù)
string: 待發(fā)送的字符串
function(sent): 發(fā)送字符串后的回調(diào)函數(shù)。
返回值
nil

這里解釋一下"srv:listen()""conn:on()""conn:send()",這里用冒號等價"srv.listen(self)""conn.on(self)""conn.send(self)",這樣對里面提到的語法就能比較好理解,其中self代表conn自己。"end"是對"function()"的結(jié)束。
conn:send("<h1> Hello, NodeMcu.</h1>") 這部分是服務(wù)器發(fā)送"<h1> Hello, NodeMcu.</h1>"給接收者,這部分是可以用html代碼寫的,如果寫得復(fù)雜些,可以用更漂亮的網(wǎng)頁展示,但nodeMcu內(nèi)存較小,每次只能發(fā)送1460byte,需要對網(wǎng)頁代碼進(jìn)行分段傳送。(如何分段,可以看下面幾個作者的文章)
這部分代碼如果還是不太好理解,可以參看@qq_32543253寫得NODEMCU調(diào)試心得6 - 關(guān)于網(wǎng)絡(luò)協(xié)議HTTP,也可以看看@謝mingmin寫的9、nodeMCU學(xué)習(xí)筆記--net模塊,對于相關(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)建一個server
srv:listen(80,function(conn) 
    conn:on("receive",function(conn,payload) 
    print(payload) 
    conn:send("<h1> Hello, NodeMcu.</h1>")
    end) 
end)

運行

運行服務(wù)器代碼.png

這時NodeMcu已經(jīng)作為一個http服務(wù)器開始運行了。用在同一局域網(wǎng)的電腦的瀏覽器打開對應(yīng)http服務(wù)器的地址:192.168.8.145,就可以看到如下圖結(jié)果

瀏覽器返回結(jié)果.png

1.2.4 利用服務(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)建一個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)

就增加了點燈的2行代碼,記得按一下nodeMcu板上的RST,再在ESPlorer中的run點一下,再寫入代碼,重新Save to Esp,這時代碼才更新好。這時重新打開瀏覽器輸入http服務(wù)器的地址:192.168.8.145,就可以看到NodeMcu上的LED燈點亮了。print(payload)是可以在ESPlorer打印從瀏覽器客戶端收到的payload信息,可以刪去。

1.2.5 能點燈還需要關(guān)燈

上面只是簡單實現(xiàn)了點燈,但要實現(xià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)
--開啟gpio16端口
srv=net.createServer(net.TCP) 
--創(chuàng)建一個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.的頁面
           elseif(vars == "on")then
                 gpio.write(pin, gpio.LOW)
                 --開燈
                 conn:send("<h1> Light ON.</h1>")
                 --傳送給客戶端 Light ON.的頁面
           end
    
    end) 
end)

上述代碼,如果復(fù)制,請刪掉注釋再運行!!!
這個代碼實現(xiàn)使,在同一局域網(wǎng)客戶端(手機瀏覽器或電腦瀏覽器)輸入http://192.168.8.145/off熄滅板上的LED燈,輸入http://192.168.8.145/on開啟板上的LED燈。
這里解釋一下local _, _, method, vars = string.find(payload, "([A-Z]+) /(.+) HTTP"),這個我也開始學(xué)也弄不太懂,參看@qq_32543253的教程,明白了。其實就是Lua中的string.find()語法的應(yīng)用。具體這里不展開了,大家可以百度。這里的應(yīng)用使采用string.find()匹配payload中的字符,提取出對應(yīng)([A-Z]+)(.+)的字符,賦值給method, vars,前面2個_,是虛變量,我們簡化一下這個代碼

payload="GET /on HTTP/1.1"
local a, b, method, vars = string.find(payload, "([A-Z]+) /(.+) HTTP")
print(a,b,method,vars)
運行結(jié)果.png

可以看到此時a=1,b=12,method="GET",vars="on",a和b對應(yīng)匹配字符的起始1和結(jié)束12(注意不要忽略空格)。

再看一下http://192.168.8.145/onon作用,回到之前的程序,當(dāng)我們輸入http://192.168.8.145/on

on的作用.png

print(payload)可以看到第1行是GET /on HTTP/1.1,說明網(wǎng)址中的on被傳送過去了,程序就是這個被網(wǎng)址傳送過去的字符進(jìn)行了判斷控制。當(dāng)然我們可以用其它字符,其它判斷來實現(xiàn)更復(fù)雜的控制。
如果html寫得好,可以通過編制html按鈕,來進(jìn)行信息傳送,原理是一樣的。但個人覺得由于nodeMcu的機能限制,不太適合太復(fù)雜太精美的html再進(jìn)行復(fù)雜控制,不如就用這樣簡單的網(wǎng)址字符輸入控制(其實是我自己html還不會)。
我們可以選擇更精美的UI和更優(yōu)秀的硬件做服務(wù)器,而NodeMcu就做控制。這時后話了,下一節(jié)我們試試domoticz遠(yuǎn)程控制NodeMcu。

1.2.6 程序隨NodeMcu啟動而運行

前面的控制,都是在線調(diào)試而成,如何使自己的程序成為初始化程序,即NodeMcu啟動后就能直接運行,不用點ESPlorer中的run。這里就需要用到init.lua,它就是NodeMcu開機啟動項。
方案1
這里我們可以把之前寫的服務(wù)器代碼用另存為 init.lua寫入板子。然后重啟,把NodeMcu插在移動電源上或5V的充電器,再試試用同局域網(wǎng)的手機或電腦輸入控制網(wǎng)址http://192.168.8.145/on,看看板上LED是不是已經(jīng)點亮了。

方案2
或者還可以這么調(diào)用

dofile("之前服務(wù)器程序文件名(包括后綴)")

比如

dofile("server20170316.lua")

存儲為init.lua,然后將服務(wù)器程序?qū)懭耄賹懭?code>init.lua。再重啟把NodeMcu插在移動電源上或5V的充電器試試。是不是也成功。

結(jié)尾

這一章寫了很多,比較啰嗦瑣碎,但我想盡可能仔細(xì),把一些東西解釋清楚,這即加深了自己的學(xué)習(xí)理解,同時方便大家實踐。如果這里點燈實踐不成功,歡迎討論。
總結(jié)一些吧,本節(jié)從點亮LED開始,再討論NodeMcu的WIFi連接,服務(wù)器的建立,再到簡單的命令控制,最終實現(xiàn)了遠(yuǎn)程LED的點亮控制。
這種網(wǎng)上教程比較多,大家也可以多多借鑒。

參考

官方教程:http://www.nodemcu.com/index_cn.html
@qq_32543253的博客:http://blog.csdn.net/qq_32543253/article/details/53240851
@謝mingmin的簡書:http://www.lxweimin.com/p/2535d6374a2b
官方的net教程:https://nodemcu.readthedocs.io/en/master/en/modules/net/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容