无线传感器网络是按照轮数来运行的,在网络的运行过程中,包括网络建立节点和节点稳定工作阶段两部分,如图1所示。
图1 网络运行轮次示意图
在网络建立阶段,对整个无线传感器网络进行分簇,节点按照某一概率成功获选成为簇头,然后向其邻居节点发送邀请加入簇结构的消息,而邻居节点通过信号的强弱来判断,就近的加入簇结构中并且按照TDMA时间片的传送数据给簇首。然后簇内中的节点进入稳定工作阶段,簇首节点和其他普通节点稳定工作,每个簇内节点将对监测区域覆盖感进行数据采集和数据融合,最后转发给簇首节点,而冗余节点是休眠的,不消耗能量。图2是一个无线传感器网络中一个簇结构的节点状态图,图中的簇首节点、休眠节点以及普通节点分别表示为C H CHCH节点、白色节点和黑色节点。
图2 无线传感器网络部分示意图
对整个无线传感器网络进行簇首的选取,首先节点会随机生成( 0 , 1 ) (0,1)(0,1)之间的一个随机值,若预先设定的阈值是大于该随机值的,则它成功获选为簇首节点,然后将其成功获选为簇首的消息广播给周围其他节点。T ( n ) T(n)T(n)的计算公式如下:
在公式(1)中,p pp为簇首节点占整个网络节点的比列,E 0 E_0E0为节点初始能量,E r e s i d u a l E_{residual}Eresidual为节点的剩余能量,n nn为当前的轮数,G GG为竞选簇首失败的节点集合。由公式(1)可知,节点剩余能量越多,其阈值就越大,因此就更容易获选成为簇首节点。
当簇首节点向其他节点广播已当选簇首的消息后,那么其他的周围邻居节点将根据簇首广播消息的信号强弱来决定加入距离相对比较近的簇结构中,并向簇首发消息确认。当簇首节点收到请求加入消息后,采用 TDMA 方法将传送数据的时间片分配传送至簇结构中的每一个节点,簇的建立完成。
在每一轮簇结构形成后,处于激活状态的所有簇内节点将依次按照自己的I D IDID大小来进行一个覆盖冗余的判定,判定冗余覆盖节点的条件为:
① 如果簇内节点的感知覆盖区域内的邻居节点数是小于四个的,那么此节点将继续处于活跃状态,进行工作;
② 如果簇内节点的感知覆盖区域内的邻居节点数是大于或等于四个并且满足如图3中覆盖条件,即该节点的感知覆盖区域被其邻居节点所完全覆盖,那么该节点就为冗余覆盖节点,它所感知到的数据都是邻居节点所感知到的,则使该节点在此轮中进行休眠,下一轮从新进行判定。
图3 冗余节点O覆盖范围内的节点分布图
NDSCT算法流程图如图4所示。
图4 NDSCT算法流程图
通过M a t l a b MatlabMatlab作为实验仿真平台来对分簇拓扑节点休眠调度算法进行仿真实验,将仿真结果与LEACH算法比较。所有传感器节点在100 m × 100 m 100m×100m100m×100m的目标监测区域范围内是随机分布的,汇聚节点即基站是处于整个网络的中间位置,传感器节点的总数取值为100,传感器的通信半径为感知半径的两倍即 R c = 2 R s Rc=2RsRc=2Rs,R c RcRc为30m,R s RsRs为15m。实验的参数设置与文献[1]相同。
NDSCT算法每轮休眠节点数量如图5所示。
图5 NDSCT算法每轮休眠节点数
NDSCT和LEACH算法每轮存活节点数量如图6所示。
图6 存活节点数
NDSCT和LEACH算法每轮网络剩余总能量如图7所示。
图6 网络剩余总能量
NDSCT和LEACH算法每轮节点消耗总能量如图8所示。
图8 节点消耗总能量
%% 清空环境变量 clear; clc; %% 初始化参数 xm = 100; % x轴范围 ym = 100; % y轴范围 sink.x = 50; % 基站x轴 50 sink.y = 50; % 基站y轴 50 n = 100; % 节点总数 p = 0.05; % 簇头概率 Rs = 15; % 感知半径 Rc = 2*Rs; % 通信半径 Eelec = 50*10^(-9); Efs=10*10^(-12); Emp=0.0013*10^(-12); ED=5*10^(-9); d0 = sqrt(Efs/Emp); E0 = 0.5; % 初始能量 packetLength = 4000; ctrPacketLength = 100; rmax = 6000; figure; %% 节点随机分布 for i = 1:n Node(i).xd = rand(1,1)*xm; Node(i).yd = rand(1,1)*ym; % 随机产生100个点 Node(i).type = 'N'; % 进行选举簇头前先将所有节点设为普通节点 Node(i).E = E0; % 初始能量 Node(i).CH = 0; % 保存普通节点的簇头节点,-1代表自己是簇头 Node(i).d = sqrt((Node(i).xd-sink.x)^2+(Node(i).yd-sink.y)^2); Node(i).G = 0; % 候选集标志 Node(i).Nbr = zeros(n, 1); % 邻居节点集 Node(i).NumNbr = 0; % 邻居节点个数 Node(i).status = 1; % 节点的状态:1 激活状态;0 休眠状态 plot(Node(i).xd, Node(i).yd, 'o', sink.x, sink.y, 'p', 'LineWidth', 2); hold on; end legend('节点', '基站'); xlabel 'x'; ylabel 'y'; title 'WSN分布图'; save data1; %%%%%%%%%%%%%%%%%NDSCT%%%%%%%%%%%%%%% alive_ndsct = zeros(rmax, 1); % 每轮存活节点数 re_ndsct = zeros(rmax, 1); % 每轮节点总能量 ce_ndsct = zeros(rmax, 1); % 每轮节点消耗总能量 sleep = zeros(rmax, 1); % 每轮休眠节点数 for r = 1:rmax r % figure; if mod(r, round(1/p)) == 0 for i = 1:n Node(i).G = 0; end end % 初始化 for i = 1:n if Node(i).E > 0 Node(i).type = 'N'; Node(i).CH = 0; Node(i).status = 1; Node(i).NumNbr = 0; alive_ndsct(r) = alive_ndsct(r)+1; re_ndsct(r) = re_ndsct(r)+Node(i).E; end end if alive_ndsct(r) == 0 break; end % 计算邻居节点 for i = 1:n if Node(i).E > 0 count = 0; for j = 1:n if Node(j).E > 0 dist = sqrt((Node(i).xd-Node(j).xd)^2+(Node(i).yd-Node(j).yd)^2); if j ~= i && dist < Rs count = count + 1; Node(i).Nbr(count) = j; end end if j == n Node(i).NumNbr = count; end end end end %% 簇头选举 cluster = 0; for i = 1:n if Node(i).E > 0 temp_rand = rand; if Node(i).G <= 0 && temp_rand < p/(1-p*mod(r,round(1/p)))*(Node(i).E/E0) Node(i).type = 'C'; % 节点类型为簇头 Node(i).G = round(1/p)-1; cluster = cluster + 1; % 簇头节点存入C数组 C(cluster).xd = Node(i).xd; C(cluster).yd = Node(i).yd; C(cluster).dist = Node(i).d; C(cluster).id = i; % X(cluster) = Node(i).xd; % Y(cluster) = Node(i).yd; % plot(Node(i).xd, Node(i).yd, 'r*'); % hold on; CH = C; Node(i).CH = -1; % 广播自成为簇头 distanceBroad = sqrt(xm*xm+ym*ym); if distanceBroad > d0 Node(i).E = Node(i).E- (Eelec*ctrPacketLength + Emp*ctrPacketLength*distanceBroad^4); ce_ndsct(r) = ce_ndsct(r)+Eelec*ctrPacketLength + Emp*ctrPacketLength*distanceBroad^4; else Node(i).E = Node(i).E- (Eelec*ctrPacketLength + Efs*ctrPacketLength*distanceBroad^2); ce_ndsct(r) = ce_ndsct(r)+Eelec*ctrPacketLength + Efs*ctrPacketLength*distanceBroad^2; end % 簇头自己发送数据包能量消耗 if Node(i).d > d0 Node(i).E = Node(i).E- ((Eelec+ED)*packetLength+Emp*packetLength*Node(i).d^4); ce_ndsct(r) = ce_ndsct(r)+(Eelec+ED)*packetLength+Emp*packetLength*Node(i).d^4; else Node(i).E = Node(i).E- ((Eelec+ED)*packetLength+Efs*packetLength*Node(i).d^2); ce_ndsct(r) = ce_ndsct(r)+(Eelec+ED)*packetLength+Efs*packetLength*Node(i).d^2; end end end end % 判断最近的簇头结点,如何去判断,采用距离矩阵 for i = 1:n if Node(i).type == 'N' && Node(i).E > 0 if cluster > 0 Length = zeros(cluster, 1); for c = 1:cluster Length(c) = sqrt((Node(i).xd - C(c).xd)^2+(Node(i).yd-C(c).yd)^2); end [min_dis, min_dis_cluster] = min(Length); % 找到距离簇头最近的簇成员节点 % 接收簇头发来的广播的消耗 Node(i).E = Node(i).E - Eelec*ctrPacketLength; ce_ndsct(r) = ce_ndsct(r)+Eelec*ctrPacketLength; % 加入这个簇 if min_dis < d0 Node(i).E = Node(i).E-(Eelec*ctrPacketLength+Efs*ctrPacketLength*min_dis^2); ce_ndsct(r) = ce_ndsct(r)+Eelec*ctrPacketLength+Efs*ctrPacketLength*min_dis^2; else Node(i).E = Node(i).E-(Eelec*ctrPacketLength+Emp*ctrPacketLength*min_dis^4); ce_ndsct(r) = ce_ndsct(r)+Eelec*ctrPacketLength+Emp*ctrPacketLength*min_dis^4; end Node(i).CH = C(min_dis_cluster).id; % plot(Node(i).xd, Node(i).yd, 'ko'); % hold on; % plot([Node(i).xd; Node(C(min_dis_cluster).id).xd], [Node(i).yd; Node(C(min_dis_cluster).id).yd]); % hold on; % 簇头接收簇成员接收加入消息 if min_dis > 0 Node(C(min_dis_cluster).id).E = Node(C(min_dis_cluster).id).E - Eelec*ctrPacketLength; %接收加入消息 ce_ndsct(r) = ce_ndsct(r)+Eelec*ctrPacketLength; end end end end %% 判断冗余节点,进行休眠调度 for i = 1:n if Node(i).E > 0 && Node(i).type == 'N' % 非簇头节点 if Node(i).NumNbr >= 4 % 邻居节点个数≥4 if isFullCover(Node, i) == 1 Node(i).status = 0; % 冗余节点,状态调整为休眠状态 sleep(r) = sleep(r)+1; % plot(Node(i).xd, Node(i).yd, 'go'); % hold on; end end end end %% 数据传输 for i = 1:n if Node(i).E > 0 && Node(i).status ~= 0 % 节点存活且状态为激活态 if Node(i).type == 'N' % 普通节点 if cluster > 0 % 簇头节点存在 dist = sqrt((Node(i).xd-Node(Node(i).CH).xd)^2+(Node(i).yd-Node(Node(i).CH).yd)^2); % 向簇头发送数据 if dist < d0 Node(i).E = Node(i).E-(Eelec*packetLength+Efs*packetLength*dist^2); ce_ndsct(r) = ce_ndsct(r)+Eelec*packetLength+Efs*packetLength*dist^2; else Node(i).E = Node(i).E-(Eelec*packetLength+Emp*packetLength*dist^4); ce_ndsct(r) = ce_ndsct(r)+Eelec*packetLength+Emp*packetLength*dist^4; end else % 无簇头选出 % 直接发送数据到基站 dist = Node(i).d; if dist < d0 Node(i).E = Node(i).E-(Eelec*packetLength+Efs*packetLength*dist^2); ce_ndsct(r) = ce_ndsct(r)+Eelec*packetLength+Efs*packetLength*dist^2; else Node(i).E = Node(i).E-(Eelec*packetLength+Emp*packetLength*dist^4); ce_ndsct(r) = ce_ndsct(r)+Eelec*packetLength+Emp*packetLength*dist^4; end end end end end end load data1.mat; %%%%%%%%%%%%%%LEACH%%%%%%%%%%%%%%% %% alive_leach = zeros(rmax, 1); % 每轮存活节点数 re_leach = zeros(rmax, 1); % 每轮节点总能量 ce_leach = zeros(rmax, 1); % 每轮节点消耗总能量 for r = 1:rmax % figure; if mod(r, round(1/p)) == 0 for i = 1:n Node(i).G=0; end end for i = 1:n if Node(i).E > 0 Node(i).type = 'N'; Node(i).CH = 0; alive_leach(r) = alive_leach(r)+1; re_leach(r) = re_leach(r)+Node(i).E; end end if alive_leach(r) == 0 break; end %% 簇头选举 cluster = 0; for i = 1:n if Node(i).E > 0 temp_rand = rand; if Node(i).G <= 0 && temp_rand < p/(1-p*mod(r,round(1/p))) Node(i).type = 'C'; % 节点类型为簇头 Node(i).G = round(1/p)-1; cluster = cluster + 1; % 簇头节点存入C数组 C(cluster).xd = Node(i).xd; C(cluster).yd = Node(i).yd; C(cluster).dist = Node(i).d; C(cluster).id = i; X(cluster) = Node(i).xd; Y(cluster) = Node(i).yd; CH = C; Node(i).CH = -1; % 广播自成为簇头 distanceBroad = sqrt(xm*xm+ym*ym); if distanceBroad > d0 Node(i).E = Node(i).E- (Eelec*ctrPacketLength + Emp*ctrPacketLength*distanceBroad^4); ce_leach(r) = ce_leach(r)+Eelec*ctrPacketLength + Emp*ctrPacketLength*distanceBroad^4; else Node(i).E = Node(i).E- (Eelec*ctrPacketLength + Efs*ctrPacketLength*distanceBroad^2); ce_leach(r) = ce_leach(r)+Eelec*ctrPacketLength + Efs*ctrPacketLength*distanceBroad^2; end % 簇头自己发送数据包能量消耗 if Node(i).d > d0 Node(i).E = Node(i).E- ((Eelec+ED)*packetLength+Emp*packetLength*Node(i).d^4); ce_leach(r) = ce_leach(r)+(Eelec+ED)*packetLength+Emp*packetLength*Node(i).d^4; else Node(i).E = Node(i).E- ((Eelec+ED)*packetLength+Efs*packetLength*Node(i).d^2); ce_leach(r) = ce_leach(r)+(Eelec+ED)*packetLength+Efs*packetLength*Node(i).d^2; end end end end % 判断最近的簇头结点,如何去判断,采用距离矩阵 for i = 1:n if Node(i).type == 'N' && Node(i).E > 0 if cluster > 0 Length = zeros(cluster, 1); for c = 1:cluster Length(c) = sqrt((Node(i).xd - C(c).xd)^2+(Node(i).yd-C(c).yd)^2); end [min_dis, min_dis_cluster] = min(Length); % 找到距离簇头最近的簇成员节点 % 接收簇头发来的广播的消耗 Node(i).E = Node(i).E - Eelec*ctrPacketLength; ce_leach(r) = ce_leach(r)+Eelec*ctrPacketLength; % 加入这个簇,并发送数据给簇头 if min_dis < d0 Node(i).E = Node(i).E-(Eelec*(ctrPacketLength+packetLength)+Efs*(ctrPacketLength+packetLength)*min_dis^2); ce_leach(r) = ce_leach(r)+Eelec*(ctrPacketLength+packetLength)+Efs*(ctrPacketLength+packetLength)*min_dis^2; else Node(i).E = Node(i).E-(Eelec*(ctrPacketLength+packetLength)+Emp*(ctrPacketLength+packetLength)*min_dis^4); ce_leach(r) = ce_leach(r)+Eelec*(ctrPacketLength+packetLength)+Emp*(ctrPacketLength+packetLength)*min_dis^4; end Node(i).CH = C(min_dis_cluster).id; % 簇头接收簇成员数据包消耗能量,接收加入消息 if min_dis > 0 Node(C(min_dis_cluster).id).E = Node(C(min_dis_cluster).id).E - (Eelec+ED)*packetLength; %接受簇成员发来的数据包 Node(C(min_dis_cluster).id).E = Node(C(min_dis_cluster).id).E - Eelec*ctrPacketLength; %接收加入消息 ce_leach(r) = ce_leach(r)+(Eelec+ED)*packetLength+Eelec*ctrPacketLength; end else % 无簇头选出,直接发送数据包到基站 if Node(i).d < d0 Node(i).E = Node(i).E-(Eelec*packetLength+Efs*packetLength*Node(i).d^2); ce_leach(r) = ce_leach(r)+Eelec*packetLength+Efs*packetLength*Node(i).d^2; else Node(i).E = Node(i).E-(Eelec*packetLength+Emp*packetLength*Node(i).d^4); ce_leach(r) = ce_leach(r)+Eelec*packetLength+Emp*packetLength*Node(i).d^4; end end end % [vx, vy] = voronoi(X, Y); % plot(X, Y, 'r*', vx, vy, 'g-'); % hold on; % voronoi(X, Y); % axis([0 xm 0 ym]); end end %% 绘图显示 figure; plot(1:rmax, sleep, 'r', 'linewidth', 1); xlabel '轮数'; ylabel '每轮休眠节点数'; legend('NDSCT'); figure; plot(1:rmax, alive_ndsct, 'r', 1:rmax, alive_leach, 'g', 'LineWidth', 2); xlabel '轮数'; ylabel '每轮存活节点数'; legend('NDSCT', 'LEACH'); figure; plot(1:rmax, re_ndsct, 'r', 1:rmax, re_leach, 'g', 'LineWidth', 2); xlabel '轮数'; ylabel '每轮剩余总能量'; legend('NDSCT', 'LEACH'); figure; plot(1:rmax, ce_ndsct, 'r', 1:rmax, ce_leach, 'g', 'LineWidth', 1); xlabel '轮数'; ylabel '每轮消耗总能量'; legend('NDSCT', 'LEACH');
[1] 张雷. 基于分簇拓扑的无线传感器网络节点休眠调度算法研究[D]. 2019.