使用BLE的MCU,要想尽量减小电能消耗,必然要使用低功耗模式。因为BLE的无线收发电路工作电流是最大的,但是一般在应用时候工作的时间很短,其余时候处于关闭状态。于是当CPU不需要活动的时候,就要尽可能减小CPU、总线、RAM等常规部件的电流,主要通过关闭相关的时钟。然后,当需要无线功能工作的时候,由定时器将系统唤醒。
RSL10有两种低功耗模式:Standby 和 Sleep. 注意!这跟常见的MCU比如STM32里面的用词不一样(对于STM32,Sleep模式指CPU用WFE/WFI指令进入空闲状态;Standby模式是只有极少数模块能活动的模式)。对于RSL10, ARM Cortex-m3 CPU用WFI指令的空闲状态并没有给出特定名称,这是默认就使用了的。Standby模式和Sleep模式都要使用 BLE_Power_Mode_Enter() 函数来进入,当系统有事件触发时,将被唤醒然后继续执行。Standby 模式下RSL10工作电流大约是 30uA. 而 Sleep 模式下就只有不到一个uA了。Sleep 模式才是RSL10最省电的模式。
大赛提供的 QFN EVB (有Arduino接口那个) 有单独的电流测试跳线,可以测出RSL10实际的电流。SENSE-GEVB 小圆板,因为上面带了很多传感器,所有传感器的待机电流就大约20uA了,会拖累整个系统的功耗。COIN-GEVB 小圆板,带了一个温度传感器,其待机电流在 2uA 左右,也比 RSL10 的最低电流大。
如果要保持 BLE 连接(处于CONNECTED状态下),或者持续广播(ADVERTISING状态),Standby模式和Sleep模式都需要靠 baseband timer 唤醒——这个是自动设置的,我们写(或改)程序也不用管。此外,还可以用 Kernel 分配的 Timer 来指定一个时间之后唤醒,做任何想做的事情;还可以用某些GPIO引脚唤醒功能,借助外部电路唤醒。
Sleep 模式虽然电流可以降到最低,但是因为绝大部分硬件都掉电了,唤醒之后要重新初始化,所以延迟大;初始化时候也要消耗电力,是额外开销。
因为唤醒后短时的电流会比较大,特别是无线部分工作的时候,没有专门的工具是不好测量这个电流的。我为了测试平均电流,就用了一只2200uF的电解电容并联在板子(COIN-GEVB)的电源端,然后电源经过串接数字万用表(uA档)和电阻(可以接电压表、示波器)接上去。经过电容储能,将短时的大电流分散,万用表就能测得差不多了。
以下是 COIN-GEVB 板子,3.3V电源,Sleep 模式电流测试,包含了温度传感器的2uA贡献。
实测,COIN-GEVB 在 1.5秒的间隔下广播,平均工作电流 8.8uA. 比想象的高一点儿。
作为从设备,在连接状态下,连接间隔 0.5秒时,平均工作电流 13.3uA.
使用了 400ms 的 Kernel Timer 间歇唤醒之后,1.5秒广播模式和0.5秒间隔的连接模式,平均电流分别是 15.1uA 和 20.9uA. 因为唤醒多了,电流消耗增加。
我的项目要使用加速度传感器做连续的运动检测,原先设想的是直接用 SENSE-GEVB,现成的BHI160. 然而这货太高级了,自己带CPU,耗电也大(测demo就知道了)。我后来就放弃它了,用了 COIN 板子,外接了一个从废手环上拆的 ROHM KX023, I2C接口。按照 50Hz 的数据转换速率(不能再低了),因为KX023内部最多缓存41个采样,必须最长每隔0.8秒访问一次加速度计,把数据取走。KX023 在 50Hz 数据率下电流大约 11uA. 和 RSL10 是在同一个量级。
在 1.5秒间隔广播模式下,并且每 400ms 唤醒读取 KX023 的数据,整个系统电流达到了 40.5uA. 对比前值,增加部分除了 KX023 本身的电流,还有 I2C 访问期间系统的电力消耗。因为 I2C 读写时候,RSL10 需要等待,故提高 I2C 的频率以缩短操作时间是可以节省电力的。因为 KX023 是支持 3.4MHz I2C 的,应当支持1MHz 的 Fast-mode plus. 我把 SCL 频率从 500kHz 提升到 1.05MHz,系统电流改善到了 32.8uA.
厉害了,要求着实严格,我的手表预想平均电流1mA就差不多了,你这还是uA级别的!厉害厉害!