您的位置:首页 > 其它

设计用于环境监测的无线传感网多跳数据采集、传输系统。在PC机上能显示当前测得的温/湿度、光照等环境信息。当光照超过一定阈值时,感知节点通过LED信号灯给以报警。

2020-05-05 12:20 561 查看

第一章 概述
1.1设计目的
1、使用韩伯感知节点、结合Sink节点,设计用于环境监测的无线传感网多跳数据采集、传输系统。在PC机上能显示当前测得的温/湿度、光照等环境信息。当光照超过一定阈值时,感知节点通过LED信号灯给以报警。
2、对tree路由的理解及应用。
1.2功能要求
实现题目的功能要求需要用到两类节点,这两类节点分别是感知节点和sink节点。
1.2.1 感知节点的功能
感知节点作为采集节点负责采集周围的数据,每20s采集一次光照,每100s采集一次温/湿度。感知节点要将采集到的温/湿度、照度值通过多跳转发给sink节点,转发过程中采用自适应树形路由策略转发数据。
1.2.2 sink节点的功能
Sink节点与PC相连,在PC终端上显示从感知节点接收到的温/湿度和光照的值。
1.3开发环境
PC机;
NotePad++;
cygwin;
SmartRFProg.exe;
Network Topology-Viewer。

第二章 系统整体设计
2.1整体架构组织
2.1.1 OscilloscopeSHT11的整体架构组织

OscilloscopeSHT11是实现功能一时用到的,实现在采样周期内采集温/湿度,按照题目要求把采集的数据由温/湿度变为温/湿度和照度,主要包括头文件Oscilloscope.h、配置文件OscilloscopeAppC.nc和模块文件OscilloscopeC.nc。上述框架图能够在配置文件OscilloscopeAppC.nc中体现出。 Boot接口由组件MainC提供;接口Timer由组件TimerMilliC提供;接口Read<uint16_t>由组件SensirionSht11C和组件PhotoSensor提供,在模块文件OscilloscopeC.nc中Read<uint16_t>被分别重命名为三个接口Read_Humidity,Read_Temp, Read_Photo;接口Leds由组件LedsC提供;为了串行传递Tinyos-2.x消息,需要使用SerialActiveMesssageC组件,接口AMsend、Receive、SplitControl都由组件SerialActiveMesssageC提供,其中SpliControl通过as 变更为SerialControl,进行布线,与数据有关的AMsend、Receive接口被声明为数组([AM_SOCILLOSCOPE]),区分了消息类型,为了只能在相同类型的接口间发送和接收。
2.1.2 Hanback_TestTree的整体架构组织

Hanback_TestTree是实现功能二时用到的,利用自适应树形路由将采集的温/湿度和照度通过多跳传输给网关节点,利用自适应树形路由转发策略,最后在PC机的通信终端上显示温/湿度和光照值。主要包括头文件Hanback_TestTree.h,配置文件Hanback_TestTreeAppC.nc,模块文件Hanback_TestTreeAppM.nc,头文件HanbackTreeRouting.h,配置文件Hanback_TreeRoutingC.nc,模块文件Hanback_TreeRoutingM.nc。上述框架图能够在模块文件Hanback_TestTreeAppC.nc中体现出。其中SensirionSht11C(),PhotoSensorC(),UltraredSensorC(),组件是为了控制韩伯节点上存在的传感器的组件;SCSuartDGBC组件为了将sink节点从无线收到的数据传给PC而使用的串行组件,该组件与SerialActiveMessage组件不同,可以直接串行传递自身想要的数据形式而非message_t结构体形式。

第三章 模块的设计和实现
3.1 OscilloscopeSHT11的模块设计和功能一的实现
3.1.1 OscilloscopeSHT11的模块设计
在OscilloscopeSHT11中是每隔0.5S通过SensirionSht11C组件从SHT11传感器收到温/湿度测量值后,根据#GET_HUMIDITY_DATA的值将温/湿度或湿度值串行传递给PC的程序。根据题目要求:每隔100S采集一次温/湿度,每隔20S采集一次光照,我对原文件进行了修改。
在头文件OscilloscopeSHT11.h中,我首先将采样周期DEFAULT_INTERVAL修改为20S;在该文件中定义了NREADINGS,该值范围从0-10,结构体oscilloscope_t 。 在配置文件OscilloscopeSHT11AppC.nc中,记录了要用的组件的声明及它们之间的连接的有关内容,我在该文件中增加了采集光照需要用到的组件new PhotoSensorC() 并更名为Sensor1及相应的接口绑定关系:OscilloscopeC.Read_Photo->Sensor1。
主要的文件是模块文件OscilloscopeC.nc,在该文件中:
1、首先声明了要用的接口并为部分接口更名,我再该部分增加了将接口 Read<uint16_t> 更名为Read_Photo;;
2、然后定义了一些需要使用的变量,在该部分我增加了turn的定义,用于计数过了多少个采样周期,声明了calc_SHT,并定义了利用LED来报告各种状态;
3、在Boot.booted函数中对一些变量进行了初始化,在该函数中我增加了turn 的初始化,其中将采样周期 DEFAULT_INTERVAL赋给了CurrentInterval;
4、在函数StartTimer()中,调用了Timer StartPeriodic(CurrentInterval),其中CurrentInterval为采样周期20S,然后需要调用函数StartDone()和StartDone()、Receive.receive(),在该部分未做修改;
5、在函数Timer.fired()中:
event void Timer.fired() {
turn++;
turn=turn%5;
if (reading == NREADINGS){
if (!sendbusy) {
// oscilloscope_t is cleared as the big endian type.
local.version = nx_16_t_change(CurrentVersion);
local.interval = nx_16_t_change(CurrentInterval);
local.id = nx_16_t_change(TOS_NODE_ID);
local.count = nx_16_t_change(MsgCount);
memcpy(call AMSend.getPayload(&sendbuf), &local, sizeof local);
if (call AMSend.send(AM_BROADCAST_ADDR, &sendbuf, sizeof local) == SUCCESS)
sendbusy = TRUE;
report_sent();
}
if (!sendbusy)
report_problem();
reading = 0;
MsgCount++;
}
if(turn0){
if(call Read_Temp.read() != SUCCESS)
report_problem();
if(call Read_Photo.read()!=SUCCESS)
report_problem(); //100秒时可能既测温湿度又测照度
}
else
if(call Read_Photo.read() != SUCCESS)
report_problem();
}
注释:首先增加了每过一个采样周期turn值自增1,并让turn对5取余数;当(readingNREADINGS)时,sendbusy为FAULSE,更新Oscilloscope结构体中version等信息,并report_problem,reading置0,MsgCount自增1;然后判断turn 的值是否为0,若turn的值为0,说明间隔了100S,则call Read_Temp.read()、call Read_Humidity.read()(在原来的代码中只写你了Temp而没有写Humidity,我的理解是因为温湿度的采样周期是一致的,所以采集完温度就会采集湿度,即若没有成功的采集温度说明湿度采集也不成功)和call Read_Photo.read();接着调用相应的readDone函数;若(call Read_Temp.read() != SUCCESS) ,(call Read_Photo.read()!=SUCCESS)则report_problem()(100秒时既测温/湿度又测光照);否则,即间隔为20S,只需call Read_Photo.read()和相应的readDone函数,若(call Read_Photo.read() != SUCCESS),则report_problem();
6、函数AMSend.sendDone(),发送完做相应的处理,若发送不成功,则report_problem(),并将sendbusy 置为FALSE;
7、在readDone部分我增加了函数Read_Photo.readDone():
event void Read_Photo.readDone(error_t result, uint16_t data) {
if (result!=SUCCESS){
report_problem();
data = 0xffff;
}
else
report_sent;
local.readings[reading++] = nx_16_t_change(data);
}
注释:若未成功采集到数据,则report_problem(),光照值置为16进制的全1;若成功采集到数据,则report_send(),并将采集到的数据放入相应的数组中;在函数Read_Temp.readDone()中调用了Read_Humidity.read(),即首先调用Read_Temp.read()函数,接着调用Read_Temp.readDone()函数,并在readDone函数中调用Read_Humidity.read函数,这就是为什么在Timer.fired函数中,当间隔为100S时,仅仅写了if(call Read_Temp.read() != SUCCESS)而没有写if(call Read_Humi.read() != SUCCESS);在函数Read_Humidity.readDone 中需要调用calc_SHT(T_humi, T_temp)函数,当GET_HUMIDITY_DATA的值为0时,数据为温度值,当其为1时,数据为湿度值;

3.1.2 功能一的实现
首先修改各个文件;然后运行cygwin进入到目录/opt/tinyos-2.x/contrib/cc2431/OscilloscopeSHT11中,输入make cc2431运行,如图3.1所示:

然后将编译的hex文件下载到节点中,进入SmartRFPog.exe进行下载;
为了确认通过串行连接线从已编程的节点周期性传送数据,需要运行示波器java运用程序,首先进入cygwin,进入到目录/opt/tinyos-2.x/contrib/cc2431/OscilloscopeSHT11/java,记录命令:java net.tinyos.sf.SerialForwarder –comm serial@COM6:57600(6是我的串口号,在设备管理器中可以查看)运行SerialForwarder,运行成功后如图3.2所示:

SerialForwarder运行成功后,打开新的cygwin,再次进入目录:/opt/tinyos-2.x/contrib/cc2431/OscilloscopeSHT11/java,输入./run ,执行命令。
3.2 Hanback_TestTree的模块设计和功能二的实现
3.2.1 Hanback_TestTree的模块设计
Hanback_TestTree例题是购买韩伯节点时已默认被下载的程序。Hanba
ck_TestTree例题,每隔3秒读进节点上的温度/湿度/照度/红外线传感器的检测值后,通过多跳协议—Tree路由,传给很远的Sink节点。Sink节点将从无线收到的数据传给PC,用户可以通过Windows程序—Viewer.exe确认当前无线网络的拓扑及各节点的检测数据。
根据题目要求,首先我对其采样周期进行了修改,另外,题目中并未要求采集会红外线的值,所以我将例题中的测量红外线的组件接口函数等删去,但是后来我发现删去以后在Viewer.exe中没有任何节点信息显示,后来经过询问其他人知道,头文件Hanback_TestTree.h中的内容不能修改,若随意修改将会干扰中断执行,于是在同学的建议下,我把红外线的值改为一个固定的值。
在配置文件Hanbck_TestTreeAppC.nc中,将组件UltraredSensorC删除,并删去绑定关系语句:Hanback_TestTreeAppM.Read_Ultrared -> UltraredSensorC;
主要的修改依然在模块文件Hanback_TestTreeAppM.nc中,在该文件中:
1、同样首先声明了要用的接口并为部分接口更名,我在改部分删去了interface Read<uint16_t> as Read_Ultrared;
2、然后定义了一些需要使用的变量,在该部分我增加了turn的定义并初始化为0,用于计数过了多少个采样周期,声明了calc_SHT;
3、在Boot.booted函数中,调用了SCSuartSTD.start(),为了串行组件的开始;
RControl.start(),为了路由组件的开始,SCSuartSTD,RControl的原型都是StdControl;并判断TOS_NODE_ID 是否等于 SinkAddress,若TOS_NODE_ID != SinkAddress,则调用Timer.startPeriodic(DATA_TIME),(DATA_TIME为采样周期),到达一定时间间隔后采集数据,若TOS_NODE_ID = SinkAddress,则sink节点需将数据发给PC;
4、在Timer.fired函数中:
event void Timer.fired() {
turn++; //每轮都自增1
call Leds.led2Toggle();
call Read_Photo.read(); //get sensor data as photo, temp., humi., ultrared orders
}

event void Read_Photo.readDone(error_t err, uint16_t val) {
if (err == SUCCESS)
{
myPhoto = val;
if(turn%5==0)
call Read_Temp.read();
else
post transmit_frame();
}
}
event void Read_Temp.readDone(error_t err, uint16_t val) {
if (err == SUCCESS)
Raw_Temp = val;
call Read_Humi.read();
}
event void Read_Humi.readDone(error_t err, uint16_t val) {
if (err == SUCCESS && Raw_Temp!=0xFFFF)
calc_SHT_(val, Raw_Temp);
post transmit_frame();
}

注释:首先每隔一个采样周期,turn值都自增1,并调用Read_Photo.read()函数,接着调用Read_Photo.readDone()函数,在该函数中,采集成功进行赋值后,进行判断turn%5是否为0,若为0,说明间隔为100S,则接着调用函数Read_Temp.read();Read_Temp.readDone(),并在readDone函数中调用函数Read_Humi.read();Read_Humi.readDone(),并在readDone函数中调用calc_SHT_(val, Raw_Temp)进行计算,抛出函数transmit_frame(),进行传送数据;在该部分我删除了函数Read_Ultrared.readDone(),并将post transmit_frame()提前到函数Read_Humi.readDone()中;
5、在函数中transmit_frame()中:
if(turn%5==0){
DFS.Temp = myTemp;
DFS.Humi = myHumi;
DFS.Photo = myPhoto;
DFS.Ultrared = 0xFFFF;
}
else{
DFS.Temp = 0xFFFF;
DFS.Humi = 0xFFFF;
DFS.Photo = myPhoto;
DFS.Ultrared = 0xFFFF;
}
注释:当间隔为100S时,将myTemp、myHumi、myPhoto中存储的检测值放入Application结构体中-DataFrameStruct 字段,并将DFS.Ultrared的值定为 0xFFFF;
当间隔为20S时,将myPhoto中储的检测值放入Application结构体中-DataFrameStruct 字段,并将DFS.Temp、DFS.Humi、DFS.Ultrared,即红外线的值一直定为16进制的FFFF(10进制的65535),并通过Rout_Send.send函数,下发到Tree路由组件-Hanback_TreeRouting组件中;
6、在函数Rout_Receive.receive中,首先进行判断,若TOS_NODE_ID == SinkAddress,说明sink节点需发送数据到PC,其中对收到的数据进行了CRC检测,memcpy的作用:eg.118行中是将调用函数Rout_Send.getPayload(msg)后得到的msg指向区域中的数据拷贝sizeof个到NWKF中。件HanbackTreeRouting.h,配置文件Hanback_TreeRoutingC.nc,模块文件Hanback_TreeRoutingM.nc中未做修改。

3.2.2功能二的实现
通过上述修改后,与OscilloscopeSHT11例题中类似,首先进入目录/opt/tinyos-2.x/contrib/cc2431/Hanback_TestTree中;然后输入make cc2431进行编译,编译成功界面如图3.3所示:

生成hex文件,如图3.4所示:


然后下载代码到节点中,sink节点和普通节点都需要下载。

第四章 运行测试和心得总结
4.1运行测试
4.1.1 测试中出现的问题及解决方法
1、在实现功能一运行java应用程序时,在cygwin中输入./run后,显示的java应用程序中没有任何图像,经过反复实验,发现是在需要将USB switch从 MCU移到232端时,每次总是在进入java文件夹后才记得移动,这个问题是由于个人粗心和对操作的不熟悉而导致的,重做一次就可以解决;
2、在将hex文件下载到节点时,点击Perform actions后提示错误,解决方式是把先把节点的USB switch拨到MCU端才能进行下载;
3、在实现功能二时,拓扑图中没有任何信息显示,经过询问其他同学知道,在头文件Hanback_TestTree.h中定义了两个结构体DataFrameStruct、UartFrameStruct,若删除结构体中的内容,在使用到该结构体时会出现中断而采集不到数据,解决方式是:恢复文件Hanback_TestTree.h中删除的部分,并在模块文件Hanback_TestTreeAppM.nc的函数ransmit_frame()中修改:当间隔为100S时,将myTemp、myHumi、myPhoto中存储的检测值放入Application结构体中-DataFrameStruct 字段,并将DFS.Ultrared的值定为 0xFFFF;当间隔为20S时,将myPhoto中储的检测值放入Application结构体中-DataFrameStruct 字段,并将DFS.Temp、DFS.Humi、DFS.Ultrared,即红外线的值一直定为16进制的FFFF(10进制的65535)。
4.1.2 运行结果
1、利用java应用程序显示采集的温/湿度、照度值:成功运行SerialForwarder后打开新的cygwin,再次进入目录:/opt/tinyos-2.x/contrib/cc2431/Oscilloscope
SHT11/java,输入./run ,若命令被正确执行,可以看到如图4.1所示的画面:

在图7中,图像的上面表示光照值,下面是温/湿度,温/湿度的间隔时间是光照的五倍。
2、下载hex文件到节点后,用USB连接sink节点,节点的USB switch拨到232端,其他活动节点把POWER拨到BAT即可,在Viewer中选择相应的端口号和sensor,点击Connect即可看到如图4.2所示的拓扑结构图:(我的节点时0和2,0为根节点,其他节点是其他人的)


在图8中,为间隔为20秒的结果,可以看到除了光照值,其他都是65535,即(0xFFFF)(当间隔为20S时,DFS.Temp = 0xFFFF;DFS.Humi = 0xFFFF;
DFS.Photo = myPhoto;DFS.Ultrared = 0xFFFF;)

当间隔为100秒时,结果如图4.3所示:

在图4.3中,间隔为100S时,温/湿度、照度的值发生了变化,而红外线的值任为65535(但在检查时,我首先运行的得到结果,过较长时间检查时红外线的值发生了变化,还不知道问题出在哪儿)即turn%5=0时,DFS.Temp = myTemp;
DFS.Humi = myHumi;DFS.Photo = myPhoto; DFS.Ultrared = 0xFFFF。
在检查的时候老师问到一个问题,为什么在2与7和1节点间的连线一直在切换,经过仔细思考,我认为是因为在用自适应树形路由进行转发时,节点会自适应的选择下一跳节点。
4.2心得总结
在刚开始做课设时,我比较迷茫,不知道如何下手,在老师的指导下,我首先仔细分析题目,根据我的优势选择了第二题,然后我开始分析老师给的例题,经过仔细分析,我发现要实现功能一其实并不难,在老师所给的两个例题Oscilloscope和OscilloscopeSht11中,分别采集的是光照和温/湿度的值,所以对于功能一我有了大体思路,需要将两个例题结合起来,因为OscilloscopeSHT11中采集了两种数据,在其上做改动会更加容易,因此,我的思路是在OscilloscopeSHT11的对应配置文件中加上测量光照值所需要的组件及对应的接口,在模块文件中加入相应的函数。那么接下来的关键问题就是,在原来的例题中是间隔一个采样周期后开始采集数据,而根据题目要求,需要在两个采样周期内分别采集数据,经过对程序逻辑结构的仔细分析,我决定在定时器上做改动。实现功能一有了大体思路后,我开始分析实现功能二需要用到的洪泛、自适应树形路由多跳转发策略。后来根据分析结果并结合之前的实验,我决定使用自适应树形路由多跳转发策略。
在做好决定后,我开始入手做第一题,按照之前的思路,我首先在配置文件OscilloscopeAppC.nc中加入了测量光照所需的组件及接口(参考Oscilloscope例题中的配置文件),然后再头文件Oscilloscope.h中,将采样周期修改为20S即20000ms,在模块文件OscilloscopeC.nc中增加一个变量turn,用于计数采样周期,然后利用turn的值来控制时间间隔,在Timer.fired()中做修改。编译成功后,为了确认通过串行连接线从已编程的节点周期性传送数据,运行了示波器java运用程序。在实现了功能一的基础上,实现功能二就顺畅了很多,我在Hanback_TestTree中做修改,由于一开始删除了Hanback_TestTree.h中与采集红外线有关的部分,一直不能的出结果,后来经过询问同学知道原因,在头文件Hanback_TestTree.h中定义了两个结构体DataFrameStruct、UartFrameStruct,若删除结构体中的内容,在使用到该结构体时会出现中断而采集不到数据,最终完成了实验。
在这次课程设计中,虽然最后结果不尽人意,但我有了很大的收获,通过对代码的反复分析,我对OscilloscopeSHT11和Hanback_TestTree中涉及的大部分代码有了更深的理解和掌握。对于洪泛和自适应树形路由转发策略,我都进行了分析,最后选择自适应树形路由是因为之前做过类似实验,会更加熟悉。在课设中,我的自学能力、解决问题的能力、动手能力有了很大的提高。在遇到问题时,我首先会选择自己动手解决,当自己不能解决时与同学探讨解决,增加了和其他同学的交流在;通过不断分析程序,我知道了当在程序中遇到一个不知道的函数或变量时如何进行分析,面对一个问题是应该如何入手来分析,将一个大的问题逐步分解为一个个小的部分。

参考文献:
[1] 宋瑞晗。基于无线传感器网络的温度监控系统。哈尔滨工程大学,2009,TP212.11。
[2] 李鑫华。基于无线传感器网络的环境监测技术研究。沈阳理工大学,2011,
TN929.5;TP212.9;TP274,未知。
[3] 李春林。无线传感器网络温湿度采集系统。西安电子科技大学,2014,TP274;TN929.5;TP212.9。
[4]夏飞。基于无线传感器网络的楼宇监控平台设计与实现。 电子科技大学,2010,TP277。
[5] 刘晓锡。无线传感器网络监测平台的设计与研究。 东北林业大学。2013,TP212.9;TN929.5。
[6] 郭水英。WSN数据采集与分析系统设计与实现。 南昌航空大学。2015,TP212.9;TN929.5。
[7] 刘长勇。基于无线传感器网络的农业温湿度环境监测系统研究与实现。 黑龙江大学。2012,TP212.9;TN929.5;X84。
[8] 李斌。基于无线传感器网络在汽车温测系统中的应用研究。 东南大学。未知,U467.41;U463.6。
[9] 侯贵升。无线传感器网络数据路由及移动Sink路径优化问题研究。 南京理工大学。2008,未知。
[10] 尚德重, 周猛, 余晟, 胡晓彦, 张宝贤。基于可控局部洪泛的移动无线传感网路由更新方法。中国科学院大学。2014,CN104244357A

qq_43216427 原创文章 3获赞 0访问量 505 关注 私信
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐