4.NodeMcu简单应用及拓展学习

NodeMcu简单应用及拓展学习

前言

之所以想要学习使用NodeMcu,就是想要将其用在现实生活中,想要实现智能物联,将一些家用电气(比如简单的灯)可用通过手机或电脑进行简单的控制。当然有人会认为现在已经有很对智能产品,支持这些功能了,那还要花时间折腾做什么呢?我的想法是,这些智能电器,或多或少存在各自的局限性,要么只能自己顾自己无法联动,要么功能简单无法实现复杂场景应用,而且用这些产品,往往需要在自己的手机上安装各自的app,控制的东西越多,需要安装的东西也越多,反而违背了使用的初衷,我学习NodeMcu的目的,就是希望能实现各种产品的联动,同时简化自己的操作,让机器替我们思考甚至做决定,以及满足自己的个性化定制需要。
我的目标可能会比较难实现,我愿意一步一步学习实践吧。
这里我将从最基础开始学习,慢慢深入应用场景,希望通过这一过程,从易到难,逐渐掌握需要的技能。下面要写的东西可能比较啰嗦,慢慢来吧。

1、从应用着手

学习一项技能,最好是从自己实际需要的着手,先提出自己的需要:远程控制灯的开关(最简单的智能灯),当然只要买个智能灯或是智能插座配合亦或是用433Hz配合智能遥控,都能实现,这里我们用NodeMcu试试。
首先从NodeMcu的点灯程序开始吧:

1.1 NodeMcu的点灯程序

最简单的点亮板上的LED程序,之前文章提到过

gpio.mode(0,gpio.OUTPUT) 
--开启gpio16端口--
gpio.write(0,gpio.LOW)
--置端口输出低电位,灯亮--
gpio.write(0,gpio.HIGH) 
--置端口输出高电位,灯灭--

相关电路原理见2.NodeMcu上手准备中点灯原理图.png。

ESPlorer输入前面2段点亮LED

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

1.2 远程点亮LED

1.2.1 连接WIFI

远程点亮,肯定需要NodeMcu连上WIFI了,根据官方教程连接路由

print(wifi.sta.getip())
--打印wifi连接端口,此时未连接,输出nil--
wifi.setmode(wifi.STATION)
--置NodeMcu为wifi为STATION工作模式--
wifi.sta.config("SSID","password")
--设置所连接wifi的参数,SSID为路由名称,password为路由密码(自己设置需替换自己的路由)--
print(wifi.sta.getip())
--输出连接上wifi后nodeMcu的地址--

当然也可以这么写

SSID="你的路由名"
password="你的路由密码"
print(wifi.sta.getip())
wifi.setmode(wifi.STATION)
wifi.sta.config(SSID,password)
print(wifi.sta.getip())

注意不要把注释也放到ESplorer中运行,我就这样出错了

运行截图.png

这里很奇怪,为什么结果里是先出IP地址再出nil,欢迎网友解答。

1.2.2 建立服务器

接着需要设置nodeMcu为服务器,还是参照官方教程,这里复制官网的代码:

srv=net.createServer(net.TCP) 
--创建一个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) 

这是创建一个server
后面是2部分组成,第一部分是net.server 子模块,相关语法是

listen()
描述
侦听指定ip地址的端口。
语法
net.server.listen(port,[ip],function(net.socket))
参数
port: 端口号
ip:ip地址字符串,可以省略
function(net.socket): 连接创建成功的回调函数,可以作为参数传给调用函数。
返回值
nil

第二部分是net.socket 子模块

on()
描述
向事件注册回调函数。
语法

on(event, function cb())
参数
event: 字符串,取值为: "connection", "reconnection", "disconnection", "receive", "sent"
function cb(net.socket, [string]): 回调函数。第一个参数是socket.
如果事件是"receive", 第二个参数则为接收到的字符串。
返回值
nil

send()
描述
通过连接向远端发送数据。
语法
send(string, function(sent))
参数
string: 待发送的字符串
function(sent): 发送字符串后的回调函数。
返回值
nil

这里解释一下"srv:listen()""conn:on()""conn:send()",这里用冒号等价"srv.listen(self)""conn.on(self)""conn.send(self)",这样对里面提到的语法就能比较好理解,其中self代表conn自己。"end"是对"function()"的结束。
conn:send("<h1> Hello, NodeMcu.</h1>") 这部分是服务器发送"<h1> Hello, NodeMcu.</h1>"给接收者,这部分是可以用html代码写的,如果写得复杂些,可以用更漂亮的网页展示,但nodeMcu内存较小,每次只能发送1460byte,需要对网页代码进行分段传送。(如何分段,可以看下面几个作者的文章)
这部分代码如果还是不太好理解,可以参看@qq_32543253写得NODEMCU调试心得6 - 关于网络协议HTTP,也可以看看@谢mingmin写的9、nodeMCU学习笔记--net模块,对于相关的教程可以参看官方的教程中关于net部分教程
还需要再解释一下,代码中conn或是srv可以用其它字符串替代,它是继承了net相关模块的功能。

1.2.3 使用服务器

合并连接WIFI和建立服务器两部分代码

SSID="你的路由名"
password="你的路由密码"
print(wifi.sta.getip())
wifi.setmode(wifi.STATION)
wifi.sta.config(SSID,password)
print(wifi.sta.getip())

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

运行

运行服务器代码.png

这时NodeMcu已经作为一个http服务器开始运行了。用在同一局域网的电脑的浏览器打开对应http服务器的地址:192.168.8.145,就可以看到如下图结果

浏览器返回结果.png

1.2.4 利用服务器点灯

直接上代码

SSID="你的路由名"
password="你的路由密码"
print(wifi.sta.getip())
wifi.setmode(wifi.STATION)
wifi.sta.config(SSID,password)
print(wifi.sta.getip())

srv=net.createServer(net.TCP) 
--创建一个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服务器的地址:192.168.8.145,就可以看到NodeMcu上的LED灯点亮了。print(payload)是可以在ESPlorer打印从浏览器客户端收到的payload信息,可以删去。

1.2.5 能点灯还需要关灯

上面只是简单实现了点灯,但要实现控制随时点亮熄灭,还不行,所以还要改进。

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) 
--创建一个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)

上述代码,如果复制,请删掉注释再运行!!!
这个代码实现使,在同一局域网客户端(手机浏览器或电脑浏览器)输入http://192.168.8.145/off熄灭板上的LED灯,输入http://192.168.8.145/on开启板上的LED灯。
这里解释一下local _, _, method, vars = string.find(payload, "([A-Z]+) /(.+) HTTP"),这个我也开始学也弄不太懂,参看@qq_32543253的教程,明白了。其实就是Lua中的string.find()语法的应用。具体这里不展开了,大家可以百度。这里的应用使采用string.find()匹配payload中的字符,提取出对应([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)
运行结果.png

可以看到此时a=1,b=12,method="GET",vars="on",a和b对应匹配字符的起始1和结束12(注意不要忽略空格)。

再看一下http://192.168.8.145/onon作用,回到之前的程序,当我们输入http://192.168.8.145/on

on的作用.png

print(payload)可以看到第1行是GET /on HTTP/1.1,说明网址中的on被传送过去了,程序就是这个被网址传送过去的字符进行了判断控制。当然我们可以用其它字符,其它判断来实现更复杂的控制。
如果html写得好,可以通过编制html按钮,来进行信息传送,原理是一样的。但个人觉得由于nodeMcu的机能限制,不太适合太复杂太精美的html再进行复杂控制,不如就用这样简单的网址字符输入控制(其实是我自己html还不会)。
我们可以选择更精美的UI和更优秀的硬件做服务器,而NodeMcu就做控制。这时后话了,下一节我们试试domoticz远程控制NodeMcu。

1.2.6 程序随NodeMcu启动而运行

前面的控制,都是在线调试而成,如何使自己的程序成为初始化程序,即NodeMcu启动后就能直接运行,不用点ESPlorer中的run。这里就需要用到init.lua,它就是NodeMcu开机启动项。
方案1
这里我们可以把之前写的服务器代码用另存为 init.lua写入板子。然后重启,把NodeMcu插在移动电源上或5V的充电器,再试试用同局域网的手机或电脑输入控制网址http://192.168.8.145/on,看看板上LED是不是已经点亮了。

方案2
或者还可以这么调用

dofile("之前服务器程序文件名(包括后缀)")

比如

dofile("server20170316.lua")

存储为init.lua,然后将服务器程序写入,再写入init.lua。再重启把NodeMcu插在移动电源上或5V的充电器试试。是不是也成功。

结尾

这一章写了很多,比较啰嗦琐碎,但我想尽可能仔细,把一些东西解释清楚,这即加深了自己的学习理解,同时方便大家实践。如果这里点灯实践不成功,欢迎讨论。
总结一些吧,本节从点亮LED开始,再讨论NodeMcu的WIFi连接,服务器的建立,再到简单的命令控制,最终实现了远程LED的点亮控制。
这种网上教程比较多,大家也可以多多借鉴。

参考

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容