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

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

前言

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

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

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

1.1 NodeMcu的點(diǎn)燈程序

最簡單的點(diǎn)亮板上的LED程序,之前文章提到過

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

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

ESPlorer輸入前面2段點(diǎn)亮LED

就可以看到靠近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ò)了

運(yùn)行截圖.png

這里很奇怪,為什么結(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)

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

srv=net.createServer(net.TCP) 

這是創(chuàng)建一個(gè)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ù)。第一個(gè)參數(shù)是socket.
如果事件是"receive", 第二個(gè)參數(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()",這里用冒號等價(jià)"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)行分段傳送。(如何分段,可以看下面幾個(gè)作者的文章)
這部分代碼如果還是不太好理解,可以參看@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)建一個(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)行

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

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

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

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í)重新打開瀏覽器輸入http服務(wù)器的地址:192.168.8.145,就可以看到NodeMcu上的LED燈點(diǎn)亮了。print(payload)是可以在ESPlorer打印從瀏覽器客戶端收到的payload信息,可以刪去。

1.2.5 能點(diǎn)燈還需要關(guā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)
--開啟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.的頁面
           elseif(vars == "on")then
                 gpio.write(pin, gpio.LOW)
                 --開燈
                 conn:send("<h1> Light ON.</h1>")
                 --傳送給客戶端 Light ON.的頁面
           end
    
    end) 
end)

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

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

可以看到此時(shí)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被傳送過去了,程序就是這個(gè)被網(wǎng)址傳送過去的字符進(jìn)行了判斷控制。當(dāng)然我們可以用其它字符,其它判斷來實(shí)現(xiàn)更復(fù)雜的控制。
如果html寫得好,可以通過編制html按鈕,來進(jìn)行信息傳送,原理是一樣的。但個(gè)人覺得由于nodeMcu的機(jī)能限制,不太適合太復(fù)雜太精美的html再進(jìn)行復(fù)雜控制,不如就用這樣簡單的網(wǎng)址字符輸入控制(其實(shí)是我自己html還不會(huì))。
我們可以選擇更精美的UI和更優(yōu)秀的硬件做服務(wù)器,而NodeMcu就做控制。這時(shí)后話了,下一節(jié)我們試試domoticz遠(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開機(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開始,再討論NodeMcu的WIFi連接,服務(wù)器的建立,再到簡單的命令控制,最終實(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的簡書:http://www.lxweimin.com/p/2535d6374a2b
官方的net教程:https://nodemcu.readthedocs.io/en/master/en/modules/net/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,963評論 6 542
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,348評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,083評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,706評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,442評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,802評論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,795評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,983評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,542評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,287評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,486評論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,030評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,710評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,116評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,412評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,224評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,462評論 2 378

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