node system-level esp8266 nodeMCU
闲言碎语
nodeMCU的模块中,有个特别的模块,名叫node。看起来并不像是某种外设,但是和其名字有点接近。node模块看起来有点特殊。实际上,node模块提供的是一些系统级(system-level)的API。用来提供一些特别功能或者获取一些硬件信息。
模块函数
序号 | 函数名 | 参数 | 返回值 |
---|---|---|---|
1 | node.bootreason() | 空 | rawcode, reason [, exccause, epc1, epc2, epc3, excvaddr, depc ] |
2 | node.chipid() | 空 | chip ID (number) |
3 | node.compile() | filename | 空 |
4 | node.dsleep() | us, option | 空 |
5 | node.flashid() | 空 | flash ID (number) |
6 | node.flashsize() | 空 | flash 大小 (integer) |
7 | node.heap() | 空 | 剩余堆大小 (number) |
8 | node.info() | 空 | majorVer(number), minorVer, devVer, chipid, flashid, flashsize, flashmode, flashspeed |
9 | node.input() | str | 空 |
10 | node.output() | function(str), serial_debug | 空 |
11 | node.restart() | 空 | 空 |
12 | node.restore() | 空 | 空 |
13 | node.setcpufreq() | speed | frequency (number) |
14 | node.stripdebug() | ||
15 | node.osprint() | ||
16 | node.egc.setmode() | ||
17 | node.task.post() |
模块的最后4个函数,提供了一些高级功能,反正我是没弄懂的。
.chipid、.flashid、flashsize和.info可以获取一些设备信息。前三个分别是芯片ID(似乎不是唯一ID,没有找到对此的具体描述)、flash ID、flash大小。而最后一个可以获取更详细的信息,除了前面三种信息,还包括了版本号、flash的工作模式和速度。
.heap函数可以获取当前堆的大小。不过,可能因为碎片的影响,实际可用空间可能比这个值小。
.restore重置系统设置,看起来像恢复出厂值。具体什么设置文档并没有说到。重置候需要重启才能使用新配置。
setcupfreq可以用来设置CPU频率。有两种频率可选
- node.CPU80MHZ
- node.CPU160MHZ
有set函数,却没有get函数。而info却没有返回CPU频率,好像有点尴尬 o(╯□╰)o
实践一下
上面一句话介绍了几个函数的作用。剩下的几个函数不是一句话就能说完的,还需要动手实践一下才知道都有什么用。
.bootreason函数可以获取设备重启的原因。通常该函数返回两个值,都是表示重启的原因。后者比前者更详细的描述了重启的原因,文档建议使用第二个参数来获取重启的原因。如果是异常重启,则会返回更多的值。具体的重启原因有下面几个:
- 0, power-on:上电
- 1, hardware watchdog reset:硬件看门狗复位
- 2, exception reset:异常重启
- 3, software watchdog reset:软件看门狗复位
- 4, software restart:软件重启
- 5, wake from deep sleep:设备唤醒
- 6, external reset:外部重启
_, reset_reason = node.bootreason()
.restart函数可以让设备重启,也就是软重启。
在设备上电后,先使用.bootreason函数看看返回了什么值。接着使用.restart重启一下设备,再使用.bootreason看看这次返回的是什么值。在看一个尴尬的例子
tmr.alarm(0, 5000, tmr.ALARM_SINGLE, function()
_, reason = node.bootreason()
print("reason : "..reason)
if reason == 6 then
node.restart()
end
end)
这个例子需要将文件名保存为init.lua。原本以为上电后,获取复位原因会是 0 的,结果却返回了6,也就是外部复位,这就尴尬了。另外,我这个板子上面的reset键按了却一点反应都没有。
.compile函数的作用是将.lua文件编译成字节码。
=node.compile("init.lua")
在右边的命令行里输入上面的代码就可以将lua文件编译成.lc文件了。然而,编译后文件竟然比lua文件大。
接着来看node.dsleep函数,用来让设备进入休眠模式的。有两个参数,第一个是睡眠时间,单位us。第二个是关于RF重启后的状态。具体看这里。
tmr.alarm(0, 5000, tmr.ALARM_SINGLE, function()
_, reason = node.bootreason()
print("reason : "..reason)
if reason == 6 then
node.dsleep(1000000)
end
end)
使用睡眠模式,需要将GPIO16和RST连到一起。睡眠时间后将会拉低RST,使设备重启。这唤醒方式够暴力的 -_-||
最后来看两个函数,.input和.output。.input用于接收一个lua语句并执行。.output用于重定向输出执行结果。官网文档有个不错的例子,这里偷懒不自己写例子,直接搬运过来。不过,官方的s_output函数没有换行。
s=net.createServer(net.TCP)
s:listen(2323,function(c)
con_std = c
function s_output(str)
if(con_std~=nil) then
str = str..'\n'
con_std:send(str)
end
end
node.output(s_output, 0) -- re-direct output to function s_ouput.
c:on("receive",function(c,l)
node.input(l) -- works like pcall(loadstring(l)) but support multiple separate line
end)
c:on("disconnection",function(c)
con_std = nil
node.output(nil) -- un-regist the redirect output function, output goes to serial
end)
end)
这个例子需要连接wifi,wifi部分内容可以看这里。首先是创建一个server,接着创建一个监听。重映射了输出。最后绑定了两个事件回调。
文档还中提到,不要使用print(),可能会出现无限递归,导致重启。
node模块的内容就介绍到这里,后面有机会再来说说最后两个函数。用这两个函数和file模块、net模块、wifi模块结合来实现一个类似于esplorer的工具。
更多内容
↑ 点击上面的标题可用查看同文集的其它文章。