使用724开发板测试pm(休眠管理)功能
目录名称
简介
我们在使用模块时,经常会关注到模块的功耗,这篇示例教大家如何使用724开发板来测试模块的休眠管理功能
材料准备
- EVB_Air724UG_A13开发板一套,包括直流电源,USB线,串口线,杜邦线
- 一台电脑,串口调试工具(这里使用的是sscom 5.13.1),Luatools_2.1.5
- luat开发环境:环境搭建方法
pm功能介绍
API说明
步骤
我们在这里做两个演示,第一个是看模块休眠时的电流(这个是唯一可以判断模块是否休眠的方法),第二个是看休眠对模块功能的影响
我手上所使用的开发板已经拆除了影响功耗的外围器件,如led灯,串口芯片
第一个示例
使用拆除外围器件的开发板烧录pm的demo,利用精密电源来测试模块正常联网后,休眠与唤醒时5分钟的平均功耗
将其余代码都注释掉
-
模块休眠时的功耗
烧录脚本模块启动后,等待一段时间(时间不确定),模块会自动进入休眠
可以看到图中显示,休眠后五分钟内平均功耗为2.23mA
-
模块保持唤醒状态的功耗
在testPm.lua内最后一行再加上pm.wake(tag)即可使模块保持唤醒状态
pm.wake("TEST")
5分钟内平均功耗为13.57mA
第二个示例
这个示例用以演示:休眠与唤醒对模块功能的影响,以及pm.wake(tag)与pm.sleep(tag)的应用
此demo的总体功能为:当模块的GPIO_9检测到高电平中断时,使模块唤醒,低电平中断时,使模块休眠。串口是常用到与外设进行通讯的通道,是一个会受到休眠影响的功能使用串口调试工具向模块的串口2发送含有固定字符的字符串,来控制开发板上3个led灯,观察模块休眠与唤醒时led灯的状态
因为此demo只是为了演示休眠与唤醒对模块功能的影响,所以不使用第一个示例所用的拆除外围耗电器件的开发板。使用正常的开发板进行测试
先说我们可以通过本示例观察到的现象:模块保持唤醒时,led灯循环规律亮灭;模块休眠时,led灯不定时亮灭
测试前的准备
-
设置GPIO
将GPIO_9设置为中断,GPIO_1,GPIO_4,GPIO5初始化,这三个GPIO分别对应开发板上的绿灯,蓝灯,红灯
pmd.ldoset(2,pmd.LDO_VLCD) --开启VLCD电压域,给GPIO_1与GPIO_4供电 local level = 1 local gpio_1 = pins.setup(pio.P0_1, 1) local gpio_4 = pins.setup(pio.P0_4, 1) local gpio_5 = pins.setup(pio.P0_5, 1) function gpioInt_9(msg) --GPIO_9的中断处理函数 if msg == cpu.INT_GPIO_POSEDGE then --高电平中断时唤醒 log.warn("使用了pm.wake()来使系统唤醒") pm.wake("TEST") else --低电平中断时休眠 log.warn("使用了pm.slepp()来使系统休眠") pm.sleep("TEST") end end pin9 = pins.setup(pio.P0_9, gpioInt_9) --将GPIO_9设置为中断 sys.timerStart( --因为是中断,所以开机要检测一次GPIO_9的状态,如果是高就保持唤醒 function() --如果是低则不做处理,因为模块联网后底层会自动进入休眠 if pin9() == 1 then pm.wake("TEST") end end , 500)
-
设置串口
使用串口二来进行读取任务,当匹配到相应字符串后,去控制LED灯的状态
local UART_ID = 2 --串口2 local function read() --串口收到数据时的读取函数 while true do local data = uart.read(UART_ID, "*l") if not data or string.len(data) == 0 then break end if string.match(data, "GPIO_TEST") then --如果在数据中匹配到"GPIO_TEST"字符串 level = level == 1 and 0 or 1 --则控制三个led灯的亮灭 gpio_1(level) gpio_4(level) gpio_5(level) end end end uart.on(UART_ID, "receive", read) --当串口收到数据时执行read uart.setup(UART_ID, 115200, 8, uart.PAR_NONE, uart.STOP_1) --打开串口
开始测试
使用Luatools烧录脚本,勾选“串口1打印trace”,烧录完脚本后,将USB从开发板拔出(模块在USB接入时不会休眠),使用直流电源供电,接到模块的UART2上,串口线接到UART1,如图所示
-
将GPIO_9与1V8短接,产生高电平中断,调用pm.wake(tag)来唤醒模块
- 用串口调试工具向UART2发送带有"GPIO_TEST"的数据,可以观察到led灯在循环规律亮灭,同时我们可以观察此刻直流电源所显示的瞬时电流
-
每秒发四次数据,可以看到开发板上的led灯一秒内亮灭两次
-
保持此唤醒状态,观察5分钟的平均电流
-
将1v8与GPIO_9断开,产生低电平中断,调用了pm.sleep(“TEST”)使模块休眠,串口调试助手保持1秒发送4次数据的频率
- 观察开发板上的led灯,可以看到:灯会不规律地亮灭,之所以这样,是因为模块休眠使串口接收不到或很难接收到数据
-
再保持此休眠状态,观察5分钟的平均电流,会发现相较于唤醒时的电流是很低的
当我们需要用串口来传输数据时,提前调用pm.wake(tag)唤醒模块,以保证串口能够正常收发数据;数据传输完毕后,为了省电,再调用pm.sleep(tag)来使模块休眠 -
在使用过程中,我们可以使用pm.isSleep(tag)/pm.isSleep()来查询脚本或tag的休眠状态
sys.taskInit( function() while true do print("\"TEST\"的休眠状态:",pm.isSleep("TEST"),"全局的休眠状态:",pm.isSleep())) sys.wait(1000) end end )
-
将GPIO_9与1v8短接后,脚本内调用了pm.wake(“TEST”)
日志会循环打印:"TEST"的休眠状态: false 全局的休眠状态: false
-
将GPIO_9与1v8断开后,脚本内调用了pm.sleep(“TEST”)
日志会循环打印:"TEST"的休眠状态: true 全局的休眠状态: true
-
-
如果有存在多个pm.wake(tag),模块的休眠状态是怎样的
-
例如,存在如下几个pm.wake(tag)
pm.wake("TEST_1") pm.wake("TEST_2") pm.wake("TEST_3") pm.wake("TEST_4")
这时候去使用如下代码去查询脚本的休眠状态,会得到如下返回值
print(pm.isSleep("TEST_1")) --false print(pm.isSleep("TEST_2")) --false print(pm.isSleep("TEST_3")) --false print(pm.isSleep("TEST_4")) --false print(pm.isSleep()) --false
模块保持唤醒状态,没有休眠,现在用pm.sleep(“TEST_4”)与pm.sleep(“TEST_2”)来标记TEST_4与TEST_2已经工作完毕,可以休眠,然后再次查询tag与脚本的休眠状态
pm.wake("TEST_1") pm.wake("TEST_2") pm.wake("TEST_3") pm.wake("TEST_4") pm.sleep("TEST_2") pm.sleep("TEST_4") print(pm.isSleep("TEST_1")) --false print(pm.isSleep("TEST_2")) --true print(pm.isSleep("TEST_3")) --false print(pm.isSleep("TEST_4")) --true print(pm.isSleep()) --false
通过如上返回值我们会发现,TEST_2与TEST_4已经是休眠状态了,但是TEST_1与TEST_3不是休眠状态,所以脚本全局没有进行休眠,这时候想让模块休眠就需要使用pm.sleep()来使所有的tag进行休眠,模块才会真正地进入休眠
pm.wake("TEST_1") pm.wake("TEST_2") pm.wake("TEST_3") pm.wake("TEST_4") print(pm.isSleep("TEST_1")) --false print(pm.isSleep("TEST_2")) --false print(pm.isSleep("TEST_3")) --false print(pm.isSleep("TEST_4")) --false print(pm.isSleep()) --false pm.sleep("TEST_1") pm.sleep("TEST_2") pm.sleep("TEST_3") pm.sleep("TEST_4") print(pm.isSleep("TEST_1")) --true print(pm.isSleep("TEST_2")) --true print(pm.isSleep("TEST_3")) --true print(pm.isSleep("TEST_4")) --true print(pm.isSleep()) --true
-
常见问题
为什么模块无法进入休眠
1. 查看模块是否插入USB,USB连接的状态下模块保持唤醒,无法休眠
2. 使用开发板和自己的板子烧录adc的demo进行对比,看模块是否能够进行休眠
3. 使用pm.isSleep()接口查询脚本休眠状态,看是否是调用了pm.wake(tag)后没有去调用pm.sleep(tag)
4. 屏蔽代码,看是由哪部分代码使模块无法休眠
为什么串口1在休眠状态下也能正常收发数据
uart1在core中做了特殊处理,可以实现休眠状态下接收数据不丢失