1. 前言
在无线传感器网络中,网络节点的功耗是一个很重要的问题。通常情况下,为了节省能量,传感器节点会关闭射频接收器,这些射频接收器仅仅在接收来自其他节点(例如,邻居节点)的数据包时打开。这个方法的原理是,当传感器节点无需接收数据时,能量消耗是最少的。然而,在某些应用中,这个方法很可能是无效或者干脆不能被使用。
在Contiki中,MAC 和 RDC(Radio Duty Cycling)在通信协议栈中的地位非常重要,因为它们会直接影响传感器节点的总功耗。
Contiki中集成了多种RDC驱动,例如:ContikiMAC、X-MAC、LPP 以及 NullRDC。RDC 驱动会尽可能的关闭射频接收器以降低节点功耗。另外,它会周期性检查是否需要接收数据。默认检查频率为 8Hz。
- Contiki MAC:适用于802.15.4
- X-MAC:短序文协议
- LPP:由接收者发起传输的RDC协议
- NullRDC:从不会关闭射频接收器(测试用)
Contiki有两种类型的 MAC: nullmac 以及 csma。
- nullmac:简单的“通过型”协议
- csma:实现了寻址、序列号以及重传
2. 设置 RDC 驱动
若要启动RDC驱动,需要在项目中包含头文件 project-conf.h
。注意,每个项目都有一个特点的配置文件。另外,为了启动 RDC 配置,必须在项目的 Makefile 中添加以下内容:
1
CFLAGS += DPROJECT_CONF_H="projectconf.h"
完整的 Makefile 文件看起来像这样:
1
2
3
CONTIKI = /home/user/contiki
CFLAGS += DPROJECT_CONF_H=\"project.conf.h\"
include $(CONTIKI)/Makefile.include
配置文件用于重写 Contiki 的一项或多项默认配置。为了启用 RDC,需要在项目配置文件中重写 RDC 层驱动的配置信息。
首先,添加以下内容,以修改RDC通道的检查频率(Hz):
1
#define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 16
接下来,指定 RDC 驱动:
1
#define NETSTACK_CONF_RDC nullrdc_driver
最后,指定MAC驱动的类型:
1
#define NETSTACK_CONF_MAC nullmac_driver
设置完成后,建议通过以下命令清除项目文件夹中已经存在的依赖(如果之前编译过该项目的话。使用需要部署的节点的类型替换[platform],例如“cc2530dk”。):
1
make TARGET=[platform] clean
接下来,编译即可:
1
make TARGET=[platform]
需要注意的是,默认情况下,Contiki协议栈各层使用的驱动如下:
- Network layer - rime_driver
- MAC layer - nullmac_driver
- RDC - nulldc_driver
- Framer - framer_nullmac
- Radio - nullradio_driver
Contiki中RDC驱动及与其对应的值
RDC驱动配置 | 值 |
---|---|
ContikiMAC | contikimac_driver |
Null_RDC | nullrdc_driver |
LPP | lpp_driver |
X-MAC | xmac_driver |
CX-MAC | cxmac_driver |
3. 功耗评估
在 Contiki 中,可以使用 Energest
模块来估计能量消耗。本例中,只关注四个方面的功耗:传输、监听、CPU 以及 LPM。
传输和监听指射频传输和接收
CPU指微控制器在没有射频传输和接收情况下的运行模式
LPM指低功耗模式(low power mode,例如,睡眠模式)
能量消耗由电压、电流以及持续时间(传感器节点为某项操作花费的时间,例如:传输、接收)相乘得出。电压和电流可以从节点的数据手册(datasheet)中获得。
需要注意的几点:Energest
模块返回的不是某项操作花费的秒数,而是CPU的时钟周期数(ticks)。因此,为了得到秒数,需要使用常量 RTIMER_SECOND 去除时钟周期数。这个常量表示每秒包含的 CPU 时钟周期数,并且随着平台的不同而不同。因此,为了减少复杂性,直接使用 Contiki 中Clock 库内的宏。
可以用下列公式来计算传感器节点的能量消耗:
1
2
3
4
5
𝐸𝑡𝑟𝑎𝑛𝑠𝑚𝑖𝑡 = 𝑡𝑡𝑟𝑎𝑛𝑠𝑚𝑖𝑡(𝑡𝑖𝑐𝑘𝑠) / 𝑡𝑖𝑚𝑒𝑟 (𝑡𝑖𝑐𝑘𝑠/𝑠𝑒𝑐𝑜𝑛𝑑) ∗ 𝐼𝑡𝑟𝑎𝑛𝑠𝑚𝑖𝑡 ∗ V
𝐸𝑡𝑟𝑎𝑛𝑠𝑚𝑖𝑡 = 𝑡𝑡𝑟𝑎𝑛𝑠𝑚𝑖𝑡(𝑡𝑖𝑐𝑘𝑠) / 𝑡𝑖𝑚𝑒𝑟 (𝑡𝑖𝑐𝑘𝑠/𝑠𝑒𝑐𝑜𝑛𝑑) ∗ 𝐼𝑡𝑟𝑎𝑛𝑠𝑚𝑖𝑡 ∗ V
𝐸𝑟𝑒𝑐𝑖𝑣𝑖𝑛𝑔 = 𝑡𝑟𝑒𝑐𝑒𝑖𝑣𝑖𝑛𝑔(𝑡𝑖𝑐𝑘𝑠) / 𝑡𝑖𝑚𝑒𝑟 (𝑡𝑖𝑐𝑘𝑠/𝑠𝑒𝑐𝑜𝑛𝑑) ∗ 𝐼𝑟𝑒𝑐𝑒𝑖𝑣𝑖𝑛𝑔 ∗ 𝑉
𝐸𝐶𝑃𝑈 = 𝑡𝐶𝑃𝑈(𝑡𝑖𝑐𝑘𝑠) / 𝑡𝑖𝑚𝑒𝑟 (𝑡𝑖𝑐𝑘𝑠/𝑠𝑒𝑐𝑜𝑛𝑑) ∗ 𝐼𝐶𝑃𝑈 ∗ 𝑉
𝐸𝐿𝑃𝑀 = 𝑡𝐿𝑃𝑀(𝑡𝑖𝑐𝑘𝑠) / 𝑡𝑖𝑚𝑒𝑟 (𝑡𝑖𝑐𝑘𝑠/𝑠𝑒𝑐𝑜𝑛𝑑) ∗ 𝐼𝐿𝑃𝑀 ∗ V
4. 示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "sys/energest.h"
…
static unsigned long rx_start_duration;
…
while(1) {
…
cpu = energest_type_time(ENERGEST_TYPE_CPU;
lpm = energest_type_time(ENERGEST_TYPE_LPM);
transmit = energest_type_time(ENERGEST_TYPE_TRANSMIT);
listen = energest_type_time(ENERGEST_TYPE_LISTEN);
time = cpu + lpm;
radio = transmit + listen;
…
}
参考
[1] Cousera Embedded Hardware and Operating Systems 课程互评作业(Energy consumption estimation)指导材料
[2] The ContikiMAC Radio Duty Cycling Protocol. Adam Dunkels. Technical report 2011.http://dunkels.com/adam/dunkels11contikimac.pdf