定时器(timer)
一、简介
定时器(timer)是一项基础且关键的服务。它允许开发者在特定的时间点或周期性地执行代码段,为物联网设备的运行提供了精确的时间控制。定时器在多种应用场景中都发挥着重要作用,如定时发送数据、周期性检查传感器状态等。
二、演示功能概述
本教程教你如何用 Air724 开发板,演示定时器功能,并且通过日志观察实验结果。
三、准备硬件环境
3.1 开发板准备
使用 EVB_Air724 开发板,如下图所示:
淘宝购买链接:Air724UG-NFM 开发板淘宝购买链接 ;
此开发板的详细使用说明参考:Air724UG 产品手册 中的《EVB_Air724UG_AXX 开发板使用说明》,写这篇文章时最新版本的使用说明为:《EVB_Air724UG_A14 开发板使用说明》;开发板使用过程中遇到任何问题,可以直接参考这份使用说明文档。
api:https://ask.openluat.com/wiki/21?wiki_page_id=2295
3.2 数据通信线
USB 数据线一根(micro USB)。
3.3 PC 电脑
WIN7 以及以上版本的 WINDOWS 系统。
3.4 SIM 卡
中国大陆环境下,可以上网的 SIM 卡。一般来说,使用移动,电信,联通的物联网卡或者手机卡都行。
3.5 组装硬件环境
USB 数据线插入 USB 口,另一端与电脑相连,拨码开关全部拨到 ON,串口切换开关选择 UART1,USB 供电的 4V 对应开关拨至 ON 档,SIM 卡放到 SIM 卡槽中锁紧,如下图所示。
四、准备软件环境
4.1 下载调试工具
使用说明参考:Luatools 下载和详细使用
4.2 源码及固件
1.底层 core 下载
下载底层固件,并解压
链接:https://docs.openluat.com/air724ug/luatos/firmware/
如下图所示,红框的是我们要使用到的。
2.本教程使用的 demo:
4.3 下载固件和脚本到开发板中
打开 Luatools,开发板上电开机,如开机成功 Luatools 会打印如下信息。
点击项目管理测试选项。
进入管理界面,如下图所示。
- 点击选择文件,选择底层固件,我的文件放在 D:\luatOS\Air724 路径中。
- 点击增加脚本或资源文件,选择 之前下载的程序源码,如下图所示。
- 点击下载底层和脚本,下载完成如下图所示。
五、代码示例介绍
5.1 API 说明
本文用到的接口函数不做详细介绍,可通过点击右侧链接查看具体介绍:sys API
5.2 timer.lua 代码
系统启动后创建了一个 sys.wait(4000),延时 4s 后再进行当前协程。避免开机后程序跑太快,我们看不清日志输出。开始后,创建了一个单次定时器且只有收到消息id才会执行 sys.waitUntil(“MSG_ID”),这个定时器又会将当前协程停下来,它需要等待一个指令才肯放行("MSG_ID"这个消息 ID)。还记得上面循环定时器里那个 sys.publish(“MSG_ID”)嘛,每隔 5s 就会发送 sys.waitUntil(“MSG_ID”)需要的消息 ID。
module(...,package.seeall)
--循环定时器打印函数
local function log1()
log.info("log","每5s打印一次,循环定时器的作用")
sys.publish("MSG_ID")
end
--循环定时器,5s执行一次log1函数
sys.timerLoopStart(log1,5000)
--第二个task的调用函数,给第一个task判断定时器是否激活用的。
local a
local function timer_2()
a=sys.timerStart(function ()
log.info("log", "我的用途就是给下面的sys.timerIsActive判断死活用的")
end,20000)
end
--第一个task的执行函数
local function timer_1()
--sys.wait(ms),单次定时器且只能用在task中,或者被task的主函数直接或者间接调用。
sys.wait(4000)
log.info("log", "开始!")
--sys.waitUntil(),单次定时器且只有收到消息id才会执行。有超时参数时:如果时间到达没有等到消息ID也会会执行。没有超时参数时:死等
sys.waitUntil("MSG_ID")
log.info("log", "接收到\"MSG_ID\"消息")
--判断timer_2里定时器的激活状态,如果激活则执行。
if sys.timerIsActive(a) then
sys.timerStart(function ()
log.info("log", "循环定时器活着,我是有timerStart定时器执行的")
end,1000)
end
--等待10s后开始执行rtos.sleep(6000),让lua虚拟机挂起6s。
sys.wait(10000)
log.info("log", "先睡6s")
--rtos.sleep(6000)
end
sys.taskInit(timer_2)
sys.taskInit(timer_1)
5.3 main.lua 代码
本代码为主程序脚本,系统启动后首先会对 4G 网络进行配置,等待网络连接成功,然后加载测试模块。
--必须在这个位置定义PROJECT和VERSION变量
--PROJECT:ascii string类型,可以随便定义,只要不使用,就行
--VERSION:ascii string类型,如果使用Luat物联云平台固件升级的功能,必须按照"X.X.X"定义,X表示1位数字;否则可随便定义
PROJECT = "TIME_SYNC"
VERSION = "2.0.0"
--加载日志功能模块,并且设置日志输出等级
--如果关闭调用log模块接口输出的日志,等级设置为log.LOG_SILENT即可
require "log"
LOG_LEVEL = log.LOGLEVEL_TRACE
--[[
如果使用UART输出日志,打开这行注释的代码"--log.openTrace(true,1,115200)"即可,根据自己的需求修改此接口的参数
如果要彻底关闭脚本中的输出日志(包括调用log模块接口和Lua标准print接口输出的日志),执行log.openTrace(false,第二个参数跟调用openTrace接口打开日志的第二个参数相同),例如:
1、没有调用过sys.opntrace配置日志输出端口或者最后一次是调用log.openTrace(true,nil,921600)配置日志输出端口,此时要关闭输出日志,直接调用log.openTrace(false)即可
2、最后一次是调用log.openTrace(true,1,115200)配置日志输出端口,此时要关闭输出日志,直接调用log.openTrace(false,1)即可
]]
--log.openTrace(true,1,115200)
require "sys"
require "net"
--每1分钟查询一次GSM信号强度
--每1分钟查询一次基站信息
net.startQueryAll(60000, 60000)
--此处关闭RNDIS网卡功能
--否则,模块通过USB连接电脑后,会在电脑的网络适配器中枚举一个RNDIS网卡,电脑默认使用此网卡上网,导致模块使用的sim卡流量流失
--如果项目中需要打开此功能,把ril.request("AT+RNDISCALL=0,1")修改为ril.request("AT+RNDISCALL=1,1")即可
--注意:core固件:V0030以及之后的版本、V3028以及之后的版本,才以稳定地支持此功能
ril.request("AT+RNDISCALL=0,1")
--加载控制台调试功能模块(此处代码配置的是uart2,波特率115200)
--此功能模块不是必须的,根据项目需求决定是否加载
--使用时注意:控制台使用的uart不要和其他功能使用的uart冲突
--使用说明参考demo/console下的《console功能使用说明.docx》
--require "console"
--console.setup(2, 115200)
--加载网络指示灯和LTE指示灯功能模块
--根据自己的项目需求和硬件配置决定:1、是否加载此功能模块;2、配置指示灯引脚
--合宙官方出售的Air720U开发板上的网络指示灯引脚为pio.P0_1,LTE指示灯引脚为pio.P0_4
require "netLed"
pmd.ldoset(2,pmd.LDO_VLCD)
netLed.setup(true,pio.P0_1,pio.P0_4)
--网络指示灯功能模块中,默认配置了各种工作状态下指示灯的闪烁规律,参考netLed.lua中ledBlinkTime配置的默认值
--如果默认值满足不了需求,此处调用netLed.updateBlinkTime去配置闪烁时长
--LTE指示灯功能模块中,配置的是注册上4G网络,灯就常亮,其余任何状态灯都会熄灭
--加载错误日志管理功能模块【强烈建议打开此功能】
--如下2行代码,只是简单的演示如何使用errDump功能,详情参考errDump的api
require "errDump"
errDump.request("udp://dev_msg1.openluat.com:12425", nil, true)
--加载远程升级功能模块【强烈建议打开此功能,如果使用了阿里云的OTA功能,可以不打开此功能】
--如下3行代码,只是简单的演示如何使用update功能,详情参考update的api以及demo/update
--PRODUCT_KEY = "v32xEAKsGTIEQxtqgwCldp5aPlcnPs3K"
--require "update"
--update.request()
--加载时间同步功能测试模块
require "timer"
--启动系统框架
sys.init(0, 0)
sys.run()
六、开机调试
6.1 开发板开机
连接好硬件并下载固件后,启动 Luatools 软件,系统运行信息将显示在界面中。红框中为开发板连接到 PC 机后正常打印的信息,如下图所示。
6.2 功能调试
定时器启动后创建了一个单次定时器 sys.waitUntil(“MSG_ID”),这个定时器又会将当前协程停下来,它需要等待一个指令才肯放行("MSG_ID"这个消息 ID)。sys.waitUntil未传入超时参数的时候,不涉及定时器,就是单纯的将当前task挂起,等收到指定的消息才会继续向下运行。
七、常见问题
7.1 使用定时器 sys.wait()或者 sys.waitUntil(),程序出错。
sys.wait()和 sys.waitUntil()只能用于 task 中。
7.2 定时器精度问题
LuatOS 开发最小仅支持 5 毫秒的定时器,超时时间最小 1ms(实际支持的最小时间是 5ms,小于 5ms 的时间都被转化为 5ms) 超时间最大 0x7FFFFFFF(24.85 天)。 另外毫秒级的定时器的误差较大,原因可参考 LuatOS 运行框架。