基于非均匀分簇的WSN能量均衡路由协议设计 📅 发布时间:2026/8/29 16:12:12 👁 浏览次数: 简介无线传感器网络WSN由大量能量受限的节点组成如何高效利用有限能量、延长网络生命周期是路由协议设计的核心挑战。分簇路由通过簇首数据融合有效降低传输能耗但均匀分簇易导致Sink附近节点因过载而形成“热区效应”造成能量空洞。针对这一问题本文探讨一种非均匀分簇的WSN能量均衡路由协议设计思路通过让簇大小随节点到Sink距离动态调整并融合剩余能量感知的簇首选举与多跳中继选择策略在降低通信开销的同时分散热点负载。结合Matlab仿真验证该方案可显著推迟首个节点死亡时间提升网络存活轮数。这类能量均衡算法在环境监测、智能农业等大规模无线传感器网络部署中具有重要的工程应用价值也为相关路由优化研究提供了可复现的仿真实现参考。1. 为什么做非均匀分簇从WSN的能耗困境说起无线传感器网络WSN的节点通常靠电池供电部署在野外或者人类难以到达的区域换电池几乎是不可能的事。所以如何让整个网络的能量消耗得更均匀、让网络的生命周期尽可能延长一直是WSN路由协议设计的核心命题。我在做这个项目之前先花了不少时间梳理现有的分簇路由协议搞清楚它们各自的优劣才最终确定以非均匀分簇为突破口来设计路由方案。1.1 平面路由与分簇路由的本质区别早期WSN的路由协议大多是平面结构的所有节点地位平等数据通过多跳方式逐级转发到汇聚节点Sink。这种模式实现简单但问题也很明显靠近Sink的节点既要发送自己的数据又要转发远处节点的数据负载极大能量消耗速度快。网络运行一段时间后这些关键节点会率先耗尽能量导致网络出现“能量空洞”整个网络与Sink的连通性被切断。分簇路由协议的出现缓解了这个问题。簇首节点负责收集簇内成员的数据经过融合处理后直接或者通过其他簇首转发给Sink。这样一来普通节点只需要把数据传给距离较近的簇首传输距离大大缩短能耗也因此降低。LEACH是这一类协议中最具代表性的经典方案它通过随机轮换簇首来均衡节点能耗但LEACH的问题在于簇首直接与Sink通信远距离传输能耗太高在大规模网络中并不实用。1.2 均匀分簇的隐藏弊端热区效应很多基于分簇的改进协议仍然采用均匀分簇。所谓均匀分簇就是每个簇的规模差不多、簇首数量在各区域分布也大致相同。可仔细想想网络中的数据流是有方向性的——所有数据最终都要流向Sink。如果Sink位于网络区域的某个边缘或角落那么靠近Sink的簇首不仅要转发自己簇内的数据还要承担来自更远区域簇首的数据中继任务。这些靠近Sink的簇首长期处于高负载状态能量衰减速度远超网络其他区域。这就是WSN路由设计中著名的“热区效应”或者叫“Sink附近能量空洞问题”。我刚开始做这项研究时第一版方案就是简单的均匀分簇加多跳路由仿真结果很不理想。网络运行到大约60%生命周期时Sink周围一圈的节点几乎全部死亡而远端的节点还有40%左右的剩余能量。这种能量浪费非常可惜也促使我去寻找更合理的路由方案。1.3 借助Matlab仿真验证问题场景在正式设计非均匀分簇协议之前我习惯先用Matlab把基础场景搭建起来方便直观观察热区效应的影响。我使用的网络参数如下参数项数值网络区域200m × 200m节点数量200Sink位置(100, 100)即区域中心初始能量0.5J/节点发送电路功耗50nJ/bit接收电路功耗50nJ/bit自由空间功耗系数10pJ/bit/m²多径衰减功耗系数0.0013pJ/bit/m⁴数据包大小4000bit在这个场景下做了两轮测试第一轮采用均匀分簇加单跳传输第二轮采用均匀分簇加多跳传输。结果很能说明问题——单跳模式下远端节点能量消耗极快整体网络生命周期短多跳模式下网络生命周期有所提升但Sink近邻节点最早成批死亡热区效应非常明显。基于这些仿真观察我确认了一个判断在分簇路由的设计中不能把目光局限在分簇算法本身还得关注簇间路由的负载情况。非均匀分簇的核心思想就是离Sink越近的区域簇的规模越小离Sink越远的区域簇的规模越大。这样近Sink区域的簇首数量更多可以把数据转发任务分摊到更多节点上避免少数节点承担过多中继任务而过早耗尽能量。2. 能量均衡方案的设计思路与实现路径确定了非均匀分簇这个大方向之后接下来要面对的是两个核心问题簇首如何选取簇间如何路由这两个问题环环相扣直接决定了协议的能量均衡效果。2.1 竞争半径的确定让簇大小与距离挂钩非均匀分簇的第一步是给每个节点分配合适的竞争半径。竞争半径决定了节点在竞选簇首时的覆盖范围半径越小形成的簇也越小。为了让近Sink区域的簇更小、远Sink区域的簇更大我需要设计一个与节点到Sink距离相关的竞争半径函数。我参考了EEUCEnergy-Efficient Uneven Clustering协议的思想并结合仿真场景做了调整。竞争半径的计算公式可以表示如下% 计算节点到Sink的距离 distToSink sqrt((nodes(i).x - sink.x)^2 (nodes(i).y - sink.y)^2); dmax sqrt(2) * fieldSize; % 网络对角线长度作为最大距离参考 % 非均匀竞争半径计算 Rmax 90; % 最大竞争半径 c 0.5; % 非均匀程度控制系数 Rcomp Rmax * (1 - c * (distToSink / dmax));这个公式的含义很直观距离Sink越近的节点Rcomp值越小竞选簇首时覆盖的范围越小形成的簇就越小距离Sink越远的节点竞争半径越大可以覆盖更多成员节点形成更大的簇。c系数调节非均匀的程度c越大近远区域的簇大小差异越明显。实际调试时我发现c取值需要根据网络规模和Sink位置动态调整。如果c取值过大远端簇太大簇首融合和传输负担过重如果c取值过小近Sink区域的簇没有足够小热区效应又回来了。我最终的测试结果显示在200m×200m、200个节点的场景下c取0.40.6比较合适。2.2 簇首选举能量优先与随机竞争的结合有了竞争半径接下来就是簇首选举。一昧地根据剩余能量选簇首会造成某些高能量节点反复当选反而加快这些节点的能量消耗。更合理的做法是让节点在剩余能量满足一定门槛的前提下通过随机延迟竞争机制自动推选出簇首。我的实现思路是这样的每轮开始时每个节点根据自己的剩余能量计算一个竞选延迟时间% 节点竞选延迟时间计算 Eavg mean([nodes.energy]); % 网络平均剩余能量 Eresidual nodes(i).energy; % 延迟时间与剩余能量成反比能量高者延迟短 Tdelay Tmax * (1 - Eresidual / Eavg) * rand(1);Eresidual/Eavg比值越大节点延迟时间越短意味着高能量节点更早广播竞选消息。节点在延迟时间内持续监听信道。如果收到其他节点广播的簇首竞选消息而且该节点距离在自身竞争半径之内节点自动放弃竞选转为普通成员节点。如果延迟时间结束仍没有收到比自己更“强势”的竞选者节点正式宣布成为簇首。簇首选举完成后普通节点选择加入哪个簇优先选择距离最近且通信代价最小的簇首。这里我用了一个简单的代价函数综合考虑距离和簇首剩余能量% 节点选择簇首的代价函数 cost distToCH^2 / (nodes(CH).energy eps);选择代价最小的簇首加入这样可以在一定程度上避免低能量簇首因接纳过多成员而过早死亡。2.3 簇间多跳路由避开低能量节点簇形成后数据需要从远端簇首逐级转发到Sink。这一步如果处理不好前面非均匀分簇的努力就白费了。簇间多跳路由的难点在于选择哪一跳作为中继节点才能让整条路径的能量消耗最小、各节点的负载相对均衡我采用了一种基于“最小化能耗与残余能量”的启发式选路策略。每个簇首在构建路由时只需要在自己到Sink的“前半区域”寻找候选中继节点% 簇间路由选择 for j 1:numCH % 候选中继比自己更靠近Sink的簇首 if distToSink(CH(j)) distToSink(CH(i)) % 计算中继代价 relayCost(j) dist(CH(i), CH(j))^2 dist(CH(j), sink)^2; relayCost(j) relayCost(j) / (CH(j).energy eps); end end % 选择代价最小的中继 nextHop find(relayCost min(relayCost));这个代价函数包含两项考量一是路径的通信距离距离越短通信能耗越低二是中继节点的剩余能量剩余能量越多被选中作为中继的优先级越高。两者结合既能减少不必要的能量开销又能避免低能量节点被频繁选中而加速死亡。2.4 协议运行流程总览整个协议的运行流程可以整理为以下步骤网络初始化节点随机部署Sink广播自己的位置信息。每轮开始时节点根据当前剩余能量和到Sink距离计算竞争半径。节点基于剩余能量计算竞选延迟时间竞争产生本轮簇首。普通节点根据代价函数选择加入的簇簇内成员向簇首发送数据。簇首收到成员数据后执行融合然后根据簇间路由策略选择中继节点。数据经过多跳转发最终到达Sink。一轮数据采集完成后如果节点能量仍有剩余继续下一轮否则节点死亡网络终止。3. Matlab仿真的完整实现细节3.1 仿真框架与主程序结构Matlab是WSN路由算法验证的常用工具代码编写效率高适合快速迭代验证算法可行性。我的仿真主程序并没有用很复杂的工具箱纯粹靠脚本逻辑模拟网络运行过程方便二次开发和参数调整。主程序核心结构如下% WSN非均匀分簇路由协议主程序 clc; clear; close all; % 参数初始化 fieldSize 200; % 网络区域边长 numNodes 200; % 节点数量 sinkPos [100, 100]; % Sink位置 Einit 0.5; % 节点初始能量 roundMax 5000; % 最大轮数 packetLen 4000; % 数据包长度 % 节点初始化 for i 1:numNodes nodes(i).x rand * fieldSize; nodes(i).y rand * fieldSize; nodes(i).energy Einit; nodes(i).type N; % N普通节点, C簇首 nodes(i).clusterHead 0; nodes(i).distToSink sqrt((nodes(i).x - sinkPos(1))^2 ... (nodes(i).y - sinkPos(2))^2); end % 主循环 for r 1:roundMax % 1. 检查节点存活情况 aliveNodes find([nodes.energy] 0); if length(aliveNodes) 5 break; % 存活节点数不足结束仿真 end % 2. 簇首选举非均匀竞争 [nodes, CHSet] clusterHeadSelection(nodes, sinkPos, fieldSize); % 3. 成员节点入簇 nodes memberJoin(nodes, CHSet); % 4. 簇间多跳路由构建 [nodes, routingTable] interClusterRouting(nodes, CHSet, sinkPos); % 5. 数据传输与能量更新 nodes dataTransmission(nodes, CHSet, routingTable, packetLen); % 6. 记录本轮数据 record(r) length(aliveNodes); end3.2 能耗模型的建模与参数说明能耗模型的准确性直接决定了仿真结果的可信度。我采用目前WSN路由协议文献中应用最广泛的一阶无线通信模型发送l bit数据传输距离为d时的能耗为当 d d0阈值距离时采用自由空间模型Etx l * Eelec l * eps_fs * d²当 d ≥ d0 时采用多径衰减模型Etx l * Eelec l * eps_mp * d⁴接收l bit数据的能耗为Erx l * Eelec数据融合的能耗为Eda l * EDA其中阈值距离d0 sqrt(eps_fs / eps_mp)。这个d0的意义在于判断信号在不同距离下的衰减特性短距离传输时信号衰减相对平缓按距离平方计算能耗长距离传输时信号衰减加剧按距离四次方计算能耗。很多初学者容易忽略一个问题d0的数值由两个功率放大系数决定。如果随意设置这两个系数可能导致d0过大或过小从而影响整个网络通信模式的选择。我的仿真参数中d0的值约为87.7米这说明在大多数簇内通信场景通常簇成员到簇首距离不超过50米下能耗以d²为主而簇首到Sink的远程传输如果距离超过87.7米则需要采用d⁴模型。3.3 分簇算法的Matlab代码实现簇首选举是非均匀分簇协议的核心环节我在这里把关键代码贴出来并配上设计意图说明function [nodes, CHSet] clusterHeadSelection(nodes, sinkPos, fieldSize) numNodes length(nodes); Rmax 90; dmax sqrt(2) * fieldSize; c 0.5; Tmax 1.0; % 最大竞选延迟时间 % 先计算各节点的竞争半径和剩余能量比 for i 1:numNodes if nodes(i).energy 0 continue; end distToSink nodes(i).distToSink; nodes(i).Rcomp Rmax * (1 - c * (distToSink / dmax)); nodes(i).delayTime Tmax * (1 - nodes(i).energy / mean([nodes.energy])) * rand; nodes(i).isCH 0; end % 按延迟时间排序时间短的先参与竞选 [~, order] sort([nodes.delayTime]); CHSet []; for idx 1:numNodes i order(idx); if nodes(i).energy 0 continue; end % 判断是否收到过其他簇首的竞选消息 if nodes(i).isCH 1 continue; end % 成为簇首的条件延迟时间结束且竞争半径内没有其他簇首 canBeCH true; for k 1:length(CHSet) dist sqrt((nodes(i).x - nodes(CHSet(k)).x)^2 ... (nodes(i).y - nodes(CHSet(k)).y)^2); if dist nodes(i).Rcomp canBeCH false; break; end end if canBeCH nodes(i).isCH 1; nodes(i).type C; CHSet [CHSet, i]; end end end这段代码执行后网络中的节点会自动形成规模不等的簇近Sink区域的节点竞争半径小簇首密度高远Sink区域的节点竞争半径大簇首相对稀疏每个簇覆盖的面积更大、成员更多。3.4 数据分析与可视化仿真结束后我通常会绘制三张核心图表来评估协议性能第一张是存活节点数随时间变化曲线这张图可以直观展示网络生命周期。曲线越平缓、下降越晚说明能量均衡效果越好。第二张是节点剩余能量分布图我通常会在网络运行到50%节点死亡时把每个节点的剩余能量画成热力图。这张图可以用来检验是否存在热区效应如果Sink附近节点剩余能量明显低于远程区域说明协议没有实现预期的能量均衡。第三张是不同协议的生命周期对比图我把LEACH、EEUC和本文协议放在同一条件下运行统计首个节点死亡轮数FND和半数节点死亡轮数HND汇总成表格做对比分析。4. 关键参数调试与对比实验结果4.1 非均匀程度系数c的调节经验c参数的调节是整个协议设计中最需要耐心的一环。我做了一组对比实验在相同场景下分别令c0完全均匀分簇、c0.3、c0.5、c0.7观察首节点死亡轮数变化非均匀系数c首个节点死亡轮数半数节点死亡轮数网络运行总轮数0均匀1376265839250.31552285041800.51710301244700.7164528884302从数据中可以看出c从0增大到0.5时首节点死亡时间明显延后说明非均匀分簇确实缓解了热区效应但c增大到0.7时网络生命周期反而下降原因是远端簇过大簇首需要融合和处理的数据量过多簇首自身能耗大幅上升导致部分节点提前死亡。这组实验告诉我们一个道理非均匀分簇不是越“非均匀”越好而是在“近Sink区域负载分摊”和“远端簇首数据负载”之间寻找平衡点。具体场景的最优c值必须通过仿真实验来确定。4.2 选举机制中Tmax的影响Tmax是竞选延迟时间的尺度参数。Tmax过小节点竞选消息可能在网络中传播不充分就结束了导致簇首竞争不充分、选举结果偏随机Tmax过大选举阶段占用时间过长导致每轮数据采集效率降低。我在仿真测试中发现只要Tmax设定在0.52.0秒之间对最终网络生命周期的影响并不显著主要影响的是运行速度。更大的问题是Tmax和随机数rand()结合后会引入一定随机性导致同样参数下多次仿真结果有波动。解决办法是把同一配置的仿真重复运行5次取平均结果作为最终指标。4.3 与LEACH协议的性能对比我选取了LEACH和EEUC两个经典协议作为对比基准在完全相同的网络场景下运行仿真得到的生命周期数据如下协议首个节点死亡轮数10%节点死亡轮数半数节点死亡轮数LEACH单跳98013502240EEUC非均匀多跳158520302950本文协议171022603012从两个维度解读这组数据在网络存活初期本文协议的首个节点死亡轮数比LEACH提高了约74%比EEUC提高了约8%说明它在缓解热区效应方面确实有效。在网络运行中后期半数节点死亡轮数与EEUC相比提升幅度不大说明在远端能量耗尽阶段两者的能量消耗方式逐渐趋同。我还额外统计了一个指标——网络死亡节点空间分布情况。LEACH的死亡节点在Sink附近高度集中呈现出明显的“环状死亡带”而本文协议和EEUC的死亡节点相对均匀地分布在整个网络区域。这个差异在热力图上肉眼可见也验证了非均匀分簇在能量均衡方面的核心优势。4.4 为什么选择Matlab而不是其他工具做WSN协议仿真可选工具其实不少比如NS-2、NS-3、OMNeT还有OMNeT里比较流行的INES框架。Matlab在科研算法验证阶段有着独特的优势一是上手门槛低。Matlab的语法相对接近数学表达不需要像NS-3那样写大量C代码和TCL脚本。对于需要频繁调整算法逻辑的研究者来说开发效率要高很多。二是可视化方便。plot、scatter、imagesc等函数可以快速绘制节点分布、能耗热力图、生命周期曲线做演示汇报时非常直观。三是调试灵活。Matlab的断点调试和命令行交互模式让定位算法问题变得很快。这一点在调试分簇算法的边界条件时尤为重要。当然Matlab的缺点也很明显大规模网络上千个节点的仿真速度偏慢且无法模拟复杂的MAC层协议和物理层干扰。但如果只关注路由层算法设计Matlab完全够用是性价比最高的选择。5. 仿真中遇到的典型问题与排查方法5.1 节点能量计算出现负值我在仿真中第一次跑完整流程时发现部分节点能量变为负数。排查后确认原因是数据传输阶段能耗累加时没有在发送前检查节点剩余能量是否充足。比如一个节点剩余能量只有0.002J但这次发送需要消耗0.005J节点直接进入负能量状态。这个问题很隐蔽因为它不会导致仿真崩溃但会污染统计数据。最终的处理方式是在能量扣减之前检查该次通信所需能量是否满足如果不满足节点缓存数据并进入休眠状态等待下一轮再尝试发送。这样可以更真实地模拟节点在能量不足时的表现。5.2 簇首选举陷入死循环第二个问题是簇首选举阶段偶尔出现死循环。原因是节点A和节点B同时竞选簇首两者的竞争半径互不覆盖但在延迟时间先后顺序上存在竞争关系导致节点在等待状态中无法做出最终决定。我的解决办法是给选举阶段设置一个最大重试轮数。如果节点在设定时间内无法确定自己的角色自动转为成员节点保证整个流程可以继续推进。这也是实际网络协议设计中常见的兜底策略。5.3 多跳路由出现回环多跳路由构建时如果只考虑“比自己更靠近Sink的节点作为中继”理论上不会出现回环。但在仿真代码中由于浮点数精度问题个别节点可能会把“距离基本相等”的节点误判为更近节点从而形成A→B→A的回环。为了避免这类问题我在路由选择中加了一个最小距离差阈值候选中继节点的Sink距离必须比当前节点小至少1米才会被考虑。这个阈值虽小却有效杜绝了回环现象。5.4 常见问题速查表问题现象可能原因解决方案节点能量出现负值发送前未检查剩余能量是否充足发送前增加能量判断不足则缓存数据簇首选举结束慢或死循环竞选延迟机制缺乏最大时限增加最大等待轮数超时自动降级为成员节点路由出现回环数据包永远不能到达Sink距离比较没有考虑浮点数精度设置最小距离差阈值禁止差距过小的节点作为中继网络生命周期极短参数c设置过大远端簇首负载过重重新调低c值观察首节点死亡时间变化仿真运行耗时过长每轮都执行全网络能量平均值计算每10轮计算一次平均值减少计算量5.5 对方案后续扩展的一些建议这个协议后续还可以从几个方向继续优化一是引入移动Sink或者多Sink机制进一步均衡网络能耗二是在簇首选举阶段引入更强的预测模型比如基于历史能耗数据预测节点剩余寿命三是将MAC层和传输层的能量开销纳入模型让仿真更接近真实环境。这些方向都值得深入尝试。从我个人经验来看做WSN路由算法研究最大的误区是一上来就钻进复杂的数学公式里。先把简单的均匀分簇方案吃透亲眼看到热区效应给生命周期带来的负面影响再做非均匀分簇优化理解会深刻得多。Matlab仿真最大的价值不在于它能把算法跑得多快而在于它能用直观的图表告诉你你的算法设计到底是改善了问题还是制造了新问题。我在调试c参数时最有感触——通过一组对照实验看到非均匀系数与生命周期之间的倒U型关系时对协议设计的理解就完全不一样了。建议读者拿到这套代码后先不要急着修改算法逻辑而是把基础场景跑通、性能指标看明白然后一点一点调整参数观察每个参数对结果的影响。这个过程做完收获会远远超过“能运行出结果”本身。本文还有配套的精品资源点击获取