CC2530 OSAL进入省电模式注意事项总结
在淘宝搞了几个CC2530模块回来玩,其中比较感兴趣的是低功耗这块功能,目前测试的结果是PM2模式下,纽扣电池2.8V电压,工作电流1.1uA(FLUKE F18B),符合规格书中描述的典型值1uA,总结如下:
前言:
1. OSAL是一个不错的操作系统,不要老是想着自己进入低功耗模式,应用任务没事干了,OSAL自己会进入低功耗模式。
2. 进入PM2不困难,真正困难的是真正低功耗并且通信正常。
3. 低功耗和代码有关,和硬件也有关,必要的时候,把板子除了最小系统所需之外的期间函调,一遍排查是代码问题还是硬件设计问题。
实际操作方法:(我基于淘宝卖家的例程进行操作,每个人的例程或协议栈版本不一样可能存在一定的差异)
1. 在编译器预编译那里定义:POWER_SAVING
2. f8wConfig.cfg文件中,DPOLL_RATE\DQUEUED_POLL_RATE\DRESPONSE_POLL_RATE\DREJOIN_POLL_RATE这几个全部赋值0。
3. 在你的任务初始化中增加这么一句osal_pwrmgr_device(PWRMGR_BATTERY);否则,OS不会进入省电模式。注意所有的用户任务都必须执行这么一句,否则无法进入省电模式。
做完以上3点,恭喜你,已经可以进入省电模式了。
但是,到底是PM1或PM2或PM3,要继续往下走
4. 找到void halSetSleepMode(void)函数,PCON = halSleepPconValue;这句决定你进入哪种省电模式,找到它定义的地方,我这边赋值是PCON_IDLE,将其改成HAL_SLEEP_TIMER或CC2530_PM2,即可进入PM2模式。想进入PM3同理。
作为第4点,即可进入PM2模式,但是并不以为则真的省电,可能几百个uA也可能若干个mA甚至几十个mA和没进入PM2一样。原因是,有其他任务在不停的唤醒CPU,导致电流下不来,需要注意哪几点?
1. 键盘,如果采用扫描模式则,则不停唤醒CPU,需设置成中断模式,或加大扫描周期。
2. LED,LED也有个任务,看看你的LED是不是频繁闪烁,如果是停掉。
3. ADC,我听别人说的,有个电池检测的任务不停进行电压采样,我这里没有。
4. 协议栈、协议栈、协议栈,重要的事情说三遍。
4.1 终端上电后或者断网后,会主动查找网络,导致无法进入省电模式。解决办法:http://blog.csdn.net/shjhuang/article/details/51171369,TI论坛也有,我忘记链接了。
4.2 VV大侠的http://www.deyisupport.com/question_answer/wireless_connectivity/zigbee/f/104/t/75525.aspx 当中的第4点。
以上做完了,我就实现了1.1uA的目标。
以上如有疑问,欢迎补充。
mark! 实战好文,谢谢分享。
@huang shangjian 我用的是2.51a的协议版本,按照这种方法,1. 在编译器预编译那里定义:POWER_SAVING 我只要做这个动作感觉这个模块就不能和其他的通信了。
Sir Lee1同学:
1. 做一件事不一定是走出第一步就能马上看到效果哦。并且比之前的状况可能还要糟糕,只有做完了才能看到结果哦。
2. 不能通信有两种,1是协议栈不能通信,2是应用层不能通信。你是哪种?后者不要犯低级错误哦,进入低功耗之后,如果应用层协议处理不好,确实就不能通信了哦。
@huang shangjian:
下午好。你加我QQ吧:402732326.比较方便点。
在这两个链接 http://www.deyisupport.com/question_answer/wireless_connectivity/zigbee/f/104/t/75525.aspx
http://www.deyisupport.com/question_answer/wireless_connectivity/zigbee/f/104/t/45598.aspx?pi2132219853=1
5,如何让End Device进入低功耗状态,休眠时间是如何设定的?
在协议栈宏定义中使能POWER_SAVING后,然后在f8wConfig.cfg文件里面把-DRFD_RCVC_ALWAYS_ON=FALSE,就可以让End Device进入休眠状态。
关于休眠的时间是有OSAL操作系统的调度来决定,每次休眠时间都是按照最新会发生的一个Event Timeout作为休眠时间。具体在协议栈hal_sleep函数中有说明。
1.打开POWER_SAVING 预编译
2.f8wConfig_cfg 中的RFD_RCVC_ALWAYS_ON=FALSE
3.f8wConfig_cfg中四个DPoll_RATE设为0
4.ZGlobals.c中三个PollRate设为0
5.Onboard.c文件中,OnboardKeyIntEnable=HAL_KEY_INTERUPT_ENABLE
6.hal_drivers.c中if(!Hal_KeyIntEnable)中的语句关掉
7.osal_pwrmgr_init(void)中pwrmgr_attribute.pwrmgr_device=PWRMGR_BATTERY
在网上搜了不少方法,也参考了TI官方的文档“Power Management For The CC2530.pdf”,以及“Measuring Power Consumption of CC2530 with Z-Stack(swra292AN079).PDF”。
我是已经按照文档设置了多次,就是没有成功。你加我QQ吧:402732326,QQ聊比较方便一点。
@Huang Shangjian,
感谢分享,有两点,
1) f8wConfig.cfg文件中,DPOLL_RATE\DQUEUED_POLL_RATE\DRESPONSE_POLL_RATE\DREJOIN_POLL_RATE这几个全部赋值0。
这几个变量不设为0也是没可以的,如果为了验证低功耗的电流,那么设备0用来做测试是可以的,否则用万用表测试电流波动快,看不到休眠电流。
但是实际应用中还是根据需求来,比方说门锁的poll rate肯定不能是0,DREJOIN_POLL_RATE肯定不能是0,否则rejoin都没法成功。
2)不需要手动添加,现在的协议栈只要使能POWER_SAVING就可以了
#if defined( POWER_SAVING ) && !defined(USE_ICALL) else // Complete pass through all task events with no activity? { osal_pwrmgr_powerconserve(); // Put the processor/system into sleep } #endif
VV很能发现问题。
之前的总结是在旧版协议下得出的结论,前几天从TI官网下载了最新的协议栈,与旧版协议略有差异,发现确实如VV所述的情况,情大家也注意以上的问题。
题外话:我正在做的低功耗设备,经过测试得出相关数据并计算后,得出的结论是:电池工作寿命为5.2年;而在同样的电池容量的条件下,TI原厂设计(TIDA-00374)则可以达到10.58年,这就是差距!汗ing
@huang shangjian,大虾,你好,我设置了协议栈进入了PM2模式,可是还是有10~20uA的功耗,能否留个邮箱,让我请教你呢?邮箱1791322858@qq.com
看看有没有把没用到的IO 串口外设给关掉。关掉和不关,电流相差很大的。。即使一个灯在闪,电流也相差很大。我这边把所有外设全关掉,休眠,电流可达到小于1UA,
关键是GPIO口怎么关?我这边GPIO口和外围电路全部断开,电流很小0.4uA。但是接上外围电路后电流旧变为150uA左右了。之间对连接的GPIO口设置了输入,高阻。输出为0。都没有很明显的改善。请教一下,大侠们的GPIO口都是怎么设置的?
按照介绍实现了低功耗的模式,在PM2模式下可以通过定时唤醒发送指定的数据,在PM3模式下外部中断唤醒发送指定的数据。但是在enddevice工作一段时间后定时唤醒和中断唤醒都不成功,没有数据发送,请问这是什么原因呢。
@VV
1. 一个PM3 的设备 , 发送消息没有ACK 超出重发次数之后, 是否会开启寻网?
2. 如果寻网 是否就证明 设备根本没有进入 PM3 ?
3. 如果应用层中 调用了osal_start_timerEx() 设定了一些 一次性的事件, 事件执行后不再执行, 设备向后是进入PM2 还是PM3 ?
我的也是,请问您解决了吗?
我也是 ,应用 ZLL 协议 , 遥控器 在进入 PM3 后,待机 一个小时后 ,再 发送 数据 ,感觉好像 是发不出来。 不知道 为什么 ? 灯具或遥控器 从新上电 就好了,不知道为什么 ? 还望 TI工程师 给予 答复?
请问 osal_pwrmgr_device(PWRMGR_BATTERY);是加在什么地方?
void BlinaApp_Init( byte task_id )
{
BlinaApp_TaskID = task_id;
BlinaApp_NwkState = DEV_INIT;
BlinaApp_TransID = 0;
osal_pwrmgr_device(PWRMGR_BATTERY);
osal_pwrmgr_task_state(BlinaApp_TaskID,0);
// Device hardware initialization can be added here or in main() (Zmain.c).
// If the hardware is application specific - add it here.
// If the hardware is other parts of the device add it in main().
BlinaApp_DstAddr.addrMode = (afAddrMode_t)AddrNotPresent;
VV你好
在低功耗情况下 -DRFD_RCVC_ALWAYS_ON=FALSE ,zstack的接收(RX)在空闲状态下关闭,哪有没有什么API函数可以直接控制RX的开关?