ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

LoRa自组网三条路线对比:洪泛、路由与网络栈的工程选型

LoRa自组网三条路线对比:洪泛、路由与网络栈的工程选型 去年我做农田环境监测30个LoRa节点分在两片大棚区想着省事就用广播转发。结果雨夜一跑网关附近信道全被占满节点互相补发、重传整个网络像“广播风暴”现场一样几乎瘫痪。后来我又试了按需路由再后来干脆整理了一版带ACK和重传的轻量协议栈。这篇文章就把我在“洪泛、路由、网络栈”三条路线里反复横跳的体会做一个量化对比把设计取舍、参数选择和踩过的坑一次性讲清楚。想给自己项目选型的嵌入式工程师、物联网开发者、折腾LoRa自组网的电子DIY玩家应该都能从中找到参考。先说一个共识LoRa自组网之所以比WiFi、ZigBee的自组网难做不是因为“没有协议”而是因为三个硬约束——链路速率低0.3kbps到50kbps、绝大多数模块是半双工、加上射频距离远导致单跳时延大。这三个约束叠加在一起导致任何“轻飘飘”的算法在LoRa上都会被放大成致命的信道占用问题。所以LoRa自组网不是“能通就行”而是必须把每一次空中发送都当成宝贵的信道资源来规划。1. 三条路线先分清“解决问题”的本质1.1 洪泛Flooding把每个节点都变成广播员洪泛是最朴素的组网方式。一个节点要发数据直接把包扔到射频信道上所有听见的邻居除了源节点都会无条件把这个包再转发一次直到整个网络里的节点都收到。不需要路由表不需要路径计算整个网络就是一个“全村广播”。它的核心价值是冗余和简单。任何一个节点掉线、任何一条链路被遮挡都不影响整包数据的到达因为数据可以从无数条路径绕过去。洪泛的代价也在这里一份数据网络里每个节点都要发一遍信道占用随节点数量线性上涨。LoRa这种低速率信道上节点数一旦超过20个周期上报就会变成灾难。1.2 路由Routing给数据包一张“地图”路由的思路是先找到一条从源到目标的“路”然后数据只沿着这条路走。典型代表是按需路由协议AODVAd Hoc On-Demand Distance Vector。当源节点要发数据但没有路由表项时先广播一个路由请求RREQ目标节点收到后回复RREP源节点才正式开始按路径发数据。路由路线的本质是“用一次洪泛的代价换取长期的低开销转发”。好处很明显数据包不再全网广播信道上只有路径上的节点在转发代价是要维护路由表、要处理链路断裂、要设计老化机制开发复杂度比洪泛高一个量级。1.3 网络栈Network Stack让LoRa“长满”协议层网络栈路线不再只是解决“包往哪走”而是把物理层、链路层、网络层、传输层、应用层全部整合成一套可用的通信系统。物理层管扩频因子和带宽链路层管信道侦听、ACK和重传网络层管拓扑和路由传输层管端到端确认应用层提供类似TCP/IP的socket接口给业务代码调用。这条路线的代表作有LoRaWAN的mesh扩展、国内常用的一些商用LoRa自组网协议栈以及像TinyMesh这样的开源实现。它们的特点是可靠、好用、可维护但代价是代码量大、RAM/Flash占用高、开发和调试周期变成“月”甚至“季度”为单位。路线本质复杂度典型网络规模典型场景洪泛全网广播、多路径冗余低10~30节点事件告警、稀疏固定节点、小规模遥测路由按需寻路、定向转发中30~100节点多跳传感网、固定/低速移动节点网络栈分层协议、可靠传输高100节点商用物联网、工业数据采集、大规模监测2. 洪泛路线实测简单但别被“简单”骗了2.1 极简洪泛设计包头、去重、TTL洪泛不是“把包发出去就行了”。如果没有去重机制一个包在网络里会形成无限循环直到信道彻底堵死。我的做法是在payload前面加一个简单的包头包含源地址、包序号、TTL三个字段。源地址标记这个包是谁产生的用于生成临时路由回包也方便接收端识别。包序号每个节点维护一个自增计数器接收端用它判断这个包是不是已经收过。TTL初始值设为最大跳数比如8每转发一次减1减到0就丢弃。每个节点维护一个最近包序列号的环形缓冲比如保存最近32个包的(源地址, 包序号)对。收到广播包时先查环形缓冲命中就丢弃不命中就记录并转发。这个缓冲用循环队列实现满了就覆盖最旧的记录内存占用很小。下面是我在STM32上用的去重判断伪代码实际项目里直接照着写就行#define DUPLICATE_CACHE_SIZE 32 typedef struct { uint16_t src_addr; uint16_t seq; } dup_entry_t; static dup_entry_t dup_cache[DUPLICATE_CACHE_SIZE]; static uint8_t dup_index 0; bool is_duplicate(uint16_t src, uint16_t seq) { for (uint8_t i 0; i DUPLICATE_CACHE_SIZE; i) { if (dup_cache[i].src_addr src dup_cache[i].seq seq) { return true; } } dup_cache[dup_index].src_addr src; dup_cache[dup_index].seq seq; dup_index (dup_index 1) % DUPLICATE_CACHE_SIZE; return false; }转发逻辑更简单收到包TTL减1如果TTL大于0且不是重复包就重新封装并塞进发送队列。需要注意LoRa模块空口发送时不能同时接收所以转发节点必须做“先收完、再发送”的排队这个队列深度在洪泛网络里至少要能容纳4~8个包否则高负载下会丢包。2.2 量化洪泛的代价一次数据包占用多少信道时间很多人低估了洪泛在LoRa上的“放大效应”。冷冰冰地说“洪泛开销大”没有概念我们来算一笔账。LoRa的空中时间计算公式可以简化理解为空中时间 ≈ 前导码时间 负载符号时间。以最常见的配置带宽125kHz、扩频因子SF7、编码率4/5为例一个空包前导码加最小帧头大约要花15~20ms如果带上20字节的payload总空中时间大约36ms。现在想象一个只有6个节点的全联通网络节点A要发一个数据包给网关。洪泛模式下A发一次B、C、D、E、F各自再转发一次理想情况是6次空中发送总信道占用约216ms。这里还没算CSMA侦听退避和重传。再把规模扩大到20个节点理想情况下是20次发送总占用约720ms。这意味着在SF7这种“较快”的速率下整个网络每秒钟最多只能洪泛1~2个业务包再多信道就满了。如果换成SF10或SF12单包空中时间直接飙升到数百毫秒甚至1.4秒20个节点洪泛一包要吃掉20多秒的信道时间这已经彻底不可用了。所以洪泛在LoRa上的甜区是节点数量少、业务频率低、对延时容忍度高。比如温室内几个温湿度传感器每5分钟上报一次用洪泛完全没问题又比如变电站的开关量告警节点只有十几个事件触发时才发一包洪泛能提供极高的冗余可靠性非常合适。2.3 洪泛路线的使用心得我踩过最大的坑是“周期性上报 洪泛 大网络”的组合。节点一多每个节点周期上报都全网广播网络很快就雪崩了。而且雪崩是“突然死亡”——平时看起来挺稳节点数一超过阈值新增任何一个节点整个网络延迟从几秒跳到几十秒再跳到完全收不到。我的经验是洪泛只适合事件驱动型业务不适合流式或周期型业务。另外TTL值一定不要设置得过大够用就行。比如一个区域网络深度只有3跳TTL设为8就是纯粹的浪费因为多余的转发都在占用信道。我会在部署前用串口打印每跳的源地址和RSSI实测出最大跳数再把TTL设成“最大跳数1”这样风暴概率会明显下降。3. 路由路线当网络开始有“方向”3.1 为什么AODV比OLSR更适合LoRa路由协议分两大类先应式表驱动和反应式按需。先应式的代表是OLSR节点周期性地交换HELLO消息维护全网路由表。反应式的代表是AODV只用当源节点需要发送数据时才发起路由发现。在LoRa自组网里几乎所有人最终都会选反应式核心原因有两个。第一LoRa节点大部分时间在休眠。一个电池供电的传感节点可能每小时只活跃几秒钟。如果跑先应式协议意味着即使没有业务节点也要周期醒来交换HELLO否则邻居路由表就过期了。这会让休眠节点功耗飙升完全违背LoRa低功耗的初衷。AODV不需要周期交换路由只在需要通信时建立空闲时节点可以深度睡眠。第二LoRa速率太低OLSR维护全网路由表需要周期发送拓扑控制消息这些消息本身就会占满大半信道真正传数据的机会反倒所剩无几。AODV的路由发现虽然也是广播泛洪但只在“有业务且无路由”时发生平摊下来开销小得多。3.2 路由发现与路由表设计自己动手改AODVLoRa自组网里用的AODV几乎是必然要“本土化改造”的因为标准AODV是给高带宽无线网络设计的直接搬过来一个RREQ广播就可能把信道打爆。我的改造集中在三方面。第一RREQ只在网关方向发起。LoRa自组网大多是数据汇聚型业务所有数据往网关走。这样路由发现从“全网任意节点之间互相可知”简化为“每个节点找一条到网关的路”RREQ泛洪半径和频次大幅下降。我在路由表的表项上做了一个标记区分“上行到网关”和“下行到节点”下行表项其实很少用。第二路由表不再用标准AODV的按条目超时而是按“周期性刷新业务触发刷新”。标准AODV路由表项空闲超过一定时间就删除这在LoRa低速业务下不适用——因为低业务率时路由表全被删光了每次上报都要重新路由发现代价比保持路由还高。我的方案是对活跃路径上的路由表项每收到一次上行数据就刷新它的生命周期默认生命周期设为10分钟如果10分钟没有流量才清除。第三选路标准从“跳数最少”改为“RSSI加权跳数惩罚”。LoRa链路的RSSI波动极大一条跳数少但RSSI很差的链路传输成功率可能只有50%不如多跳一跳但每跳RSSI都在-110dBm以上的路径可靠。我实际用的选路公式是cost 跳数 * 3 平均RSSI惩罚值RSSI超过-105dBm的链路额外加2低于-115dBm的链路直接不选。路由表条目结构很简单核心就是这六个字段typedef struct { uint16_t dest_addr; // 目标地址网关或节点 uint16_t next_hop; // 下一跳地址 uint8_t hop_count; // 跳数 uint8_t seq; // 路由序列号用于防环和判断新旧 int16_t rssi; // 路径RSSI均值 uint32_t expire_time; // 过期时间戳 } route_entry_t;3.3 量化AODV在LoRa上的代价AODV的第一个代价是路由发现。RREQ本质上就是一次洪泛在网络里广播一圈寻找目标。假设20个节点的网络一个RREQ广播占用信道时间大约和洪泛一包一样约700ms。这个代价不算小但它是一次性的只要路由建立起来后续数据包就只沿路径转发。第二个代价是端到端转发。假设一条5跳的路径每个数据包从源到网关中间节点各转发一次总共5次空中发送。还是以SF7 20字节约36ms的包为例端到端耗时大约180ms加上每跳的处理延迟串口到主控、主控到射频的拷贝一般每跳加20~50ms实际测下来约300ms左右。这和洪泛20个节点转发20次相比信道占用只有1/4到1/5优势非常明显。第三个代价是内存。路由表不像洪泛那样只需要一个32条的去重缓存路由协议需要维护邻居表、路径信息、待发送队列。以20条路由表项计算一个表项大约10字节加上邻居表和协议状态变量总计开销在1~2KB RAM左右。对于STM32这类单片机完全够用但如果设备上只用了8KB RAM的老古董就要小心裁剪。3.4 路由路线实操心得做AODV容易翻车的点是路由环路。LoRa链路易变如果节点同时收到来自两个邻居的RREP或者路由表更新延迟就会形成“数据包在两个节点之间来回弹”的死循环。我的做法是每个数据包头部带一个“经过节点数”计数器超过最大跳数直接丢同时在转发前检查下一跳是否为上一跳如果是就丢弃这个“禁止回跳”规则能消除99%的环路问题。另一个心得是路由发现要有“失败退避”机制。如果RREQ发出后1秒内没收到RREP不要立刻重发而是把下次路由发现时间往后推迟2倍、4倍、8倍。否则在弱信号环境下RREQ广播会不断重发网络被自身的路由发现打爆而不是被业务数据打爆。4. 网络栈路线让LoRa“长满”协议层4.1 网络栈到底比“路由”多了什么洪泛管“通”路由管“方向”而网络栈管的是“可靠地通、有质量地通”。我自己做的轻量协议栈分四层物理层管理LoRa射频参数包括SF、带宽、编码率以及发射功率自适应。MAC层负责信道侦听CSMA、退避、发送排队、ACK和重传。LoRa没有WiFi那种硬件级的ACK必须自己在载荷里定义帧类型。网络层在AODV路由基础上增加邻居管理、链路质量评估、拓扑上报。传输/应用层提供端到端的确认和重传以及一个类似UDP的透传接口业务代码只需要调用lora_send(dest, data, len)就能发数据。网络栈和单纯路由的最本质区别是“链路层可靠性”。AODV只负责找路找到了路路上的包丢了怎么办AODV不管。而网络栈在每一跳上加ACK和重传发出去的包如果下一跳没回ACK就重传超过重传次数才报错。这一层保障让上层业务代码可以放心用“发出去就成功”的模型而不必自己处理丢包。4.2 自研还是选现成的协议栈如果是商业产品、时间紧、节点规模大别自己从零写协议栈。可以考虑LoRaWAN的mesh变种或者直接选商用LoRa自组网模块。商用模块的优势是经过大量现场验证不仅有ACK重传还有组网管理、参数远程配置、固件升级等功能这些自研做起来是巨大工作量。如果是学习、技术验证、或者节点模型固定且只有几十个自研协议栈更划算。我自研时的核心模块就四个邻居表周期性收听到的邻居帧记录RSSI和最近活跃时间最多保存32条。路径表沿用第三节的route_entry_t但增加了“上一条活跃时间”和“成功发送计数”。发送队列优先级队列ACK帧和路由控制帧优先级高于业务帧避免控制帧被业务报文堵塞。重传状态机每包最多重传三次重传间隔随机化退避防止两个节点互相重传形成碰撞。RAM方面我用了STM32L43164KB RAM协议栈运行占约18KB其中发送队列和邻居表是大头。Flash资源占用约25KB包括LoRa驱动、协议栈所有层和应用接口。如果只跑洪泛这段代码体积可以压缩到8KB以内所以网络栈路线的门槛是实实在在的不是“心理门槛”。4.3 网络栈的量化表现与取舍加了ACK和重传之后代价是控制帧数量上升。每发一个业务数据包链路层都会有一个ACK帧如果重传一次则总发送次数变成2次业务帧2次ACK。以SF7计算一个带ACK的可靠传输周期占用信道时间约100ms数据包36ms ACK包约15ms 退避开销。这个数字比纯洪泛的冗余转发低但比BODV的“发完就走”高。从可靠性上看网络栈的价值立竿见影。我用同样的30节点、5跳深度拓扑实测洪泛模式端到端丢包率约8%漏报率高得让人抓狂AODV模式丢包率10%~15%链路断裂恢复期间的丢包拖了后腿而带ACK重传的协议栈业务层端到端丢包率降到0.3%以下几乎可以忽略。代价是每条上报消息从触发到确认成功的平均耗时约为1.2秒比AODV的300ms高出一截。所以网络栈并不是在所有指标上碾压它的核心优势是“可预测、可控、可运维”适合业务质量要求高的场景SODV或洪泛适合“能通就行、丢几次重发也能接受”的场景。选型永远是取舍不是越复杂越好。5. 三条路线量化对比与选型方法论5.1 直接上对比表我把自己在农田监测、仓库环境、矿山边坡三个项目里的实测数据汇总成一张表供参考。测试拓扑均为20到30个节点、5跳深度业务每5分钟上报一次。维度洪泛路由AODV网络栈ACK重传最大节点数实测稳定约20约60约120端到端延迟5跳SF7250~400ms300~500ms800~1500ms单业务包信道占用20次转发约720ms5次转发约180ms2次数据2次ACK约100ms业务层丢包率30节点实测5%~8%10%~15%含路由恢复0.3%以下空闲功耗极低可不接收低无周期信令中需周期监听/信标RAM占用2KB以内2~4KB15~25KB开发周期自研单人1~2周4~8周8~16周动态拓扑适应性好中路由恢复有延迟好链路层可感知切换需要说明的是AODV的实测丢包率比洪泛高是因为测试环境中存在节点短暂移动和遮挡AODV在路径断裂后需要几百毫秒重新路由发现期间的包直接丢了。洪泛反而因为全网广播天然规避了这个问题。这就是工程里常用的“用空间换时间”思路。5.2 选型决策树我后来总结了一套选型逻辑不再凭感觉拍脑袋而是按下面的决策链走如果节点数量小于20、业务是事件触发型、拓扑基本固定直接选洪泛。别加路由更别加协议栈省下的开发时间都是利润。如果节点数量20到60、业务是周期上报、节点有轻微移动或环境遮挡变化选AODV并做RSSI加权和路由表老化优化。如果节点数量超过60、业务要求可靠送达、需要远程配置或固件升级选网络栈路线优先评估商用方案。自研协议栈只适合产品形态固定且团队有足够积累的情况。如果网络里存在一定比例的移动节点洪泛和网络栈都比AODV表现好因为AODV的“按需性”在频繁拓扑变化时会变成频繁路由发现风暴。移动场景可考虑在洪泛基础上做分簇或者用网络栈的接入层快速切换机制。6. 对比实测中的坑与排查技巧实录6.1 洪泛风暴的现场诊断洪泛网络最头痛的问题是“明明节点不多为什么越来越卡”。我的排查步骤是这样的用串口在网关侧打印收到的数据包中的“转发计数”字段在包头的TTL到达前加一个hop_count字段如果打印出来的平均hop_count一直等于或接近最大跳数说明数据绕了远路拓扑可能与预期不符也可能存在回环。再统计每个节点转发的包数量找到“话痨”节点。产生故障前把一个节点拿远观察周边节点是否开始疯狂重发。一旦发现某个转发节点收到的重复包比例超过30%说明去重缓存长度不够需要从32条加大到64条或128条。洪泛风暴的另一大来源是“数据包合并”多个传感器在同一秒上报正好撞上某个中间节点还在转发上一包。我通常在应用层加一个随机延时上报时间在周期时长内均匀散布这个改动能把风暴概率降低一半以上。6.2 AODV路径断裂的血泪经验AODV最气人的一个问题明明通了过一会儿突然又断断了再找找到后又断。排查后发现两个原因。第一个是链路RSSI波动剧烈。LoRa信号在雨天、车辆经过、植物生长遮挡等环境下RSSI能跳变20dB以上。如果选路只看单次RREP的RSSI很容易选一条当下强、十分钟后消失的路径。解决方式是把选路依据改为“三次RREP的RSSI均值”或者让节点周期性发送探测帧修正路径质量发现RSSI均值跌破阈值就主动发起路由重建而不是等数据包丢失后被动重发。第二个是TTL设置的问题。路由发现RREQ的TTL如果小于真实跳数RREP永远回不来如果太大RREQ每次都全网泛洪白白浪费信道。我调试时会在RREQ里记录最大TTL收到RREP后在网关串口打印“跳数/TTL/路由耗时”多测几轮再确定最终值。6.3 如何搭一个可复现的对比试验台量化对比最怕“环境不一致”。我固定用的试验台是这样的用12到30个廉价的LoRa节点排成一条3到5跳的链状拓扑位置固定后不再动。网关接电脑串口以每秒100行打印所有数据包的“源地址/跳数/RSSI/耗时/序号”。连续跑24小时截取其中两个小时的日志做统计。流量模型固定10个节点每1分钟上报一次20字节模拟数据连续跑2小时。统计指标只有三个丢包率、平均端到端延迟、以及用电流探头测出的每节点平均电流。这里有个容易被忽略的细节三组对比必须用同一套物理设备、同一套天线、同一套放置位置只更换协议层代码。否则射频差异会淹没协议差异对比等于白做。6.4 我的最终建议做完这三条路线的对比之后我最深的体会是不要迷信任何“先进”方案也不要用一个模板套所有项目。洪泛解决的是“通”的问题路由解决的是“省”的问题网络栈解决的是“可靠”的问题它们在一个完整的LoRa自组网项目里甚至可以是并存的——比如网络边缘用洪泛接入网络骨干用路由网关侧用协议栈做管理。我现在的习惯是把三条路线当作一组可插拔的传输层策略先按业务流量和目标规模算一遍信道占用再做决定。这个习惯帮我避开了好几次“方案看着很好现场撑不住”的尴尬局面。
返回列表