ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

自制LoRa中继器:无信号区域短信级远距离通信完整指南

2026/9/4 4:45:49 拓冰建站 浏览量
自制LoRa中继器:无信号区域短信级远距离通信完整指南 当你在偏远山区、地库、海上或者地震后的临时安置点手机屏幕右上角显示的不是信号格而是“无服务”时你还能用什么方式把一条消息送到几公里外这听起来像是一个生存爱好者才会考虑的问题但如果你正在做户外巡检、应急救援通信、农场监控、地下管廊或临时活动组网这就是一个实际的工程需求。LoRa中继器正是为了解决“无基站但有近距离设备”的场景而生。它不依赖运营商基站不需要 SIM 卡也不用拉网线只需要在两端各放一个低功耗 LoRa 节点中间加一两个中继器就能把短信量级的文本消息接力传出去。本文会从场景、原理、硬件选型、协议设计、固件实现到现场部署完整拆解“自制LoRa中继器”这个项目。读完你不仅能跑通一条“手机-网关-LoRa中继-LoRa网关-手机”的通信链路还能避开中继方向、回环、功耗治理这些真正容易翻车的坑。先说一个明确判断中继器的技术难点从来不在“把功率加大”或者“把天线架高”而在于如何设计一个不会无限循环、不会重复泛洪、又能自动恢复的转发协议。硬件只是载体协议才是灵魂。这个项目真正值得动手的地方也在这里。1. 一个真实痛点当手机没有信号时你还能怎么发消息大多数人的第一反应是手机没有信号那就用卫星电话。但卫星电话成本高、终端门槛高多人之间互相通信更不现实。第二反应是用对讲机。对讲机确实能点对点通话但短波和模拟对讲机通常不传数字消息而且没有中继的话山体一挡就断了。于是出现了一个空白地带在没有基站覆盖、但人还需要互相传递短消息的场景里需要一种体积小、功耗低、不需要基础设施、又能自行组网延展覆盖范围的通信方式。LoRa 正好贴近这个需求。LoRa 是一种远距离低功耗无线调制技术单节点在开阔环境下通常能覆盖几百米到数公里数据速率不高通常只有零点几 kbps 到几十 kbps但传输文本消息绰绰有余。更重要的是LoRa 是公共频段技术不需要申请运营商频段只需要遵守当地无线电管理要求。但一个问题随之而来单个 LoRa 节点的覆盖半径有限而且手机本身不带 LoRa 芯片。一个完整的断网通信系统至少需要三类角色手机端用户实际使用的界面负责编辑和展示消息。LoRa 网关节点通过蓝牙或 WiFi 和手机连接把手机消息转成 LoRa 无线帧发出去。LoRa 中继器位于通信链路的中间收到一端的信号后重新转发给另一端实现超视距、越障碍通信。现实中很多人只做了前两个角色也就是两个 LoRa 板子配对收发。这样在几千公里以外的概念演示里够用但到了真实项目里当两个节点相距过远或者之间隔着一座山、一栋楼时就必须借助中继器。这也是本文标题里的“中继器”三个字最核心的价值。2. LoRa基础与中继器核心原理2.1 LoRa是什么不是LoRA微调先澄清一个容易混淆的点。最近很多人在说 LoRA是指大模型微调中的 Low-Rank Adaptation而本文讨论的 LoRa是 Long Range 的缩写是 Semtech 主导的一种无线扩频调制技术。两者名字相似领域完全不同。如果搜索资料时混在一起会浪费很多时间。LoRa 使用 Chirp Spread Spectrum 扩频调制。通俗理解是它把一个比特的信息用一段很长的线性调频信号来表示。接收端即使接收到很微弱的信号也能从噪声中把这段特有的“扫频”识别出来。这就是 LoRa 灵敏度高、抗干扰强的根本原因。但代价是速率低。它不像 WiFi 那样一次传几 Mbps而是用更长的空中占用时间换取更远的距离。所以 LoRa 适合的是小数据量、低速率、高频次的遥测和短消息不适合传图片、语音流和大文件。无线技术典型速率典型覆盖是否依赖基站适合发什么手机蜂窝网络Mbps 级较广依赖运营商基站任意数据WiFiMbps 到 Gbps 级几十米依赖 AP任意数据蓝牙 BLE1-2 Mbps十米内不依赖小数据、音频模拟对讲机语音模拟数百米到数公里不依赖语音LoRa通常几十 bps 到几十 kbps数百米到数公里不依赖小数据、文本、传感器读数2.2 中继器的本质转发是协议问题不是功率问题很多人对中继器的朴素理解是把信号再发一遍。这在模拟对讲机中继系统里大致成立因为模拟中继只需要收射频信号、变频、再放大发射。但 LoRa 中继器通常不是这种“模拟中继”而是“数字中继”。数字中继的完整操作链是接收端解调出数据包。校验 CRC确认数据包完整。解析数据包的目的地址、源地址和跳数信息。更新帧头字段如 TTL 减一、当前中继 ID。在下一个时隙或随机退避后重新调制发射。为什么必须这样做因为 LoRa 是半双工通信。如果一个节点正在发射它不可能同时接收。如果只是简单地把接收到的信号放大转发就会出现“自己发给自己听”的啸叫和冲突。数字中继把收发变成了两次独立的事件先收完再发。还有一个必须面对的问题如果链路中不止一个中继器多个中继器同时转发同一个包就会产生重复包风暴。没有去重机制的泛洪式转发会迅速耗尽信道资源最后谁都发不出去。所以在中继系统里防环、去重、TTL 控制是比射频功率更关键的工程点。3. 系统设计与通信链路3.1 手机怎么“接入”LoRa 网络手机没有 LoRa 芯片所以必须通过一个桥接设备接入。最常见的方案是手机通过低功耗蓝牙或 WiFi 连到一个 LoRa 节点上这个节点叫做“网关节点”。网关节点承担三件事从手机接收文本消息解析成 LoRa 帧。把 LoRa 帧按低速率空口发送到信道。接收来自远端的 LoRa 帧把文本消息回传给手机 App。在实际项目中网关节点就是那个插着 LoRa 模块的开发板可以做成 USB 小棒、便携盒子或者太阳能供电的固定终端。手机 App 可以自己写也可以用开源串口工具配合 AT 指令调试。3.2 中继器的工作过程假设通信链路是手机A - 网关A - LoRa 链路 - 中继器R1 - LoRa 链路 - 网关B - 手机B当网关 A 发出一条消息时中继器 R1 会收到它。R1 先判断这个消息是不是发给自己的如果不是再判断自己是不是已经转发过这个序列号。如果没转发过就自动更新 TTL 并重新发射。如果链路里有两个中继器 R1 和 R2那么 R1 转发后R2 可能同时收到 R1 的转发帧和网关 A 的原始帧。没有去重机制R2 会把同一个包转发两次进而引发下一跳的重复转发形成泛洪风暴。所以核心帧结构里必须要有“源地址 序列号 TTL 最近一跳中继ID”这些字段。4. 硬件选型与电路连接4.1 硬件清单下面是制作中继器常用的硬件组成以入门级方案为参考。具体型号和版本请以实际采购物料为准本文重点讲选型思路不写死参数。组件作用选择建议LoRa 模块无线收发选择常见模块平台支持 433/470/868/915MHz 等频段注意区分收发一体和纯发射模块主控 MCU运行协议逻辑Arduino、STM32、ESP32 均可开发简单优先选 Arduino 兼容板电源模块供电锂电池 低功耗 LDO或太阳能充电板 锂电池天线空中信号辐射外置天线优于板载天线频率必须和模块匹配外壳防尘防水户外使用建议选 ABS 防水接线盒指示灯/调试口状态确认至少留一个 LED 和串口调试口从项目定位看中继器不需要大屏幕也不需要键盘更看重长时间无人值守稳定性。所以 MCU 不必选性能特别强的够运行协议栈和收发逻辑就行。4.2 连接方式一个典型的中继器硬件连接如下LoRa 模块的 SPI 引脚SCK、MOSI、MISO、NSS接 MCU 对应 SPI 引脚。模块的 RESET、DIO0或 IRQ引脚接 MCU 的 GPIO用于接收完成中断。如果有 DIO1、DIO2 用于发送完成、CAD 检测则再接两个 GPIO。LED 指示灯接两个 GPIO表示发送状态和接收状态。电池电压经过分压电阻后接 MCU 的 ADC 引脚。串口 TTL 引脚TX/RX接调试 USB 转串口工具。在实际接线前一定要看 LoRa 模块的具体数据手册确认引脚是 3.3V 逻辑还是 5V 逻辑。如果模块是 3.3V 而 MCU 是 5V需要串电阻限流或用电平转换板否则容易烧模块。4.3 天线选型注意事项热搜词里有个是“lora模组板载天线怎么画”这其实说明很多人在用 PCB 板载天线。板载天线的问题是走线短、增益低、周围铺铜面积和外壳材质都会影响天线性能。对于中继器这种需要长期稳定通信的节点建议优先使用外置天线并把天线竖直固定在远离金属外壳的位置。如果必须使用板载天线需要注意天线区域下方不要铺地铜避免阻抗失配。天线周围尽量少走高频信号线。外壳最好用塑料或 ABS不要用金属屏蔽罩完全包住天线。5. 固件实现从点对点到中继转发5.1 通信帧格式设计在写代码之前先定义帧格式。一个完整的 LoRa 中继帧至少需要包含协议版本、帧类型、源节点 ID、目的节点 ID、当前中继 ID、TTL、序列号、时间戳、负载长度和负载数据。// 文件路径relay_frame.h #ifndef RELAY_FRAME_H #define RELAY_FRAME_H #include stdint.h #define FRAME_TYPE_USER_MSG 0x01 #define FRAME_TYPE_ACK 0x02 #define FRAME_TYPE_ROUTE 0x03 #define MAX_PAYLOAD_LEN 64 typedef struct { uint8_t protocol_version; // 协议版本固定为 0x01 uint8_t frame_type; // 帧类型 uint8_t src_id; // 源节点 ID uint8_t dst_id; // 目的节点 ID uint8_t relay_id; // 最近一次转发的中继 ID uint8_t ttl; // 剩余跳数初始建议 3 uint16_t seq; // 报文序号用于去重 uint32_t timestamp; // 发送时间戳 uint8_t payload[MAX_PAYLOAD_LEN]; uint8_t payload_len; // 负载长度 } lora_relay_frame_t; #endif关键字段说明relay_id每转发一次就更新为当前中继节点 ID用于判断该节点是否已经转发过同一个包。ttl每转发一次减一减到 0 就丢弃避免包在网络里无限循环。seq源节点生成的自增序号中继器用它配合源 ID 去重。消息内容本身放在payload中最大长度可根据信道速率调整。实际部署中不要硬塞长文本一次传 64 字节已经接近普通 LoRa 报文的一包上限更长的消息要拆包重组。5.2 中继转发核心逻辑下面的代码是中继器最关键的一段逻辑。完整工程里还会有 LoRa 驱动、串口日志、电源管理这里先列出转发函数的核心思路。// 文件路径relay_node.ino // 该函数在 LoRa 模块收到一个完整数据包后调用 // packet_len 为实际接收长度 void afterReceive(int packet_len) { lora_relay_frame_t frame; memcpy((uint8_t *)frame, (uint8_t *)LoRa.packetData(), packet_len); // 1. 如果是发给本节点的包交给上层处理不转发 if (frame.dst_id local_id) { handleLocalPacket(frame); return; } // 2. 如果本节点已经转发过这个包丢弃避免回环 if (frame.relay_id local_id) { Serial.println( already relayed by me, drop ); return; } // 3. 如果 TTL 耗尽丢弃 if (frame.ttl 0) { Serial.println( TTL expired, drop ); return; } // 4. 如果最近一段时间内收到过同一源节点同一序号丢弃 if (isDuplicate(frame.src_id, frame.seq)) { Serial.println( duplicate packet, drop ); return; } // 5. 记录去重条目 markDuplicate(frame.src_id, frame.seq); // 6. 更新转发信息 frame.ttl--; frame.relay_id local_id; // 7. 多中继场景下延迟一小段随机时间 // 避免所有中继同时转发同一包造成信道冲突 delay(random(50, 300)); sendFrame(frame); }这段逻辑同时适用于端节点和中继器。端节点设置为relay_id 0且不执行转发分支中继节点则开启转发分支。判断的关键是relay_id与seq的组合这比单纯按数据内容去重更可靠因为不同用户可能发送相同文本。isDuplicate和markDuplicate在实现时可以维护一个较小的高速缓存表例如保存最近 20 条src_id seq记录超过容量后覆盖最老记录。中继器不需要长期存储所有历史包只需要防止最近几秒内的重复。5.3 模块参数配置LoRa 模块需要配置频率、扩频因子、带宽、网络 ID 等参数。不同厂商的模组指令略有不同使用 AT 指令模组时常见配置如下以抽象风格展示具体关键词以你的模组手册为准# 配置串口波特率 ATIPR9600 # 本机地址 ATADDRESS2 # 工作频率必须符合当地无线电法规允许的频段 ATFREQ470000000 # 扩频因子越大速度越慢、灵敏度越高 ATSF9 # 信号带宽 ATBW125 # 发射功率按法规和功耗要求配置 ATPOWER22 # 网络 ID不同网络之间分配不同 ID避免串扰 ATNETWORKID88如果是用库直接驱动芯片则在初始化代码里设置同样的参数。需要特别注意链路两端和中继器必须使用完全相同的频率、带宽、扩频因子和同步字否则无法互通。5.4 电池电压监测中继器部署到野外后拆机检查不方便最好通过固件读取电池电压定时发送给管理端。// 文件路径power_monitor.cpp // 读取电池电压返回电压值单位mV // 电路中使用两个电阻分压将电池电压降到 ADC 可测范围 uint16_t readBatteryMilliVolt(int adcPin, float r1, float r2) { float vRef 1.1; // 内部参考电压依据芯片而定 int raw analogRead(adcPin); // ADC 原始值 float vAtPin (raw / 1023.0) * vRef; float batteryVolt vAtPin * (r1 r2) / r2; return (uint16_t)(batteryVolt * 1000.0); }如果用 ESP32 等 ADC 输入范围不同的平台需要改用对应的衰减配置。实际采样时要多次读取取平均值避免偶发噪声导致电压抖动。5.5 编译烧录与验证编译和烧录的步骤相对标准化在 Arduino IDE 中打开工程文件。选择正确的开发板型号和端口。把中继器节点、网关节点的本地 ID 分别设置好。编译烧录到各节点。打开串口监视器观察节点启动日志。启动后可以先做一次“空口回环测试”让节点 A 发一个测试帧节点 B 收到后自动回 ACK。串口日志里能看到 RSSI 和 SNR这两个数值是判断通信质量的关键指标。6. 供电、功耗与低功耗设计中继器通常放置在两段通信链路的中间位置很多时候是山顶、铁塔、屋顶现场不一定有市电。供电设计直接决定设备能稳定运行多久。6.1 功耗来源LoRa 中继器的主要功耗来自三部分LoRa 模块发射时瞬时电流较大通常在 100mA 级别和发射功率、模块型号有关。MCU 运行主循环时持续消耗电流。指示灯、降压模块的静态损耗。如果设备一直处在监听状态LoRa 接收模式本身就有持续功耗。对于固定位置的中继器如果条件允许建议接太阳能板和锂电池组成浮充系统如果只是临时应急可以用普通 18650 电池组。6.2 低功耗策略对于中继器最简单的低功耗策略不是频繁进入休眠而是降低发射功率只用到满足链路质量的最小功率。关闭不必要的 LED 指示灯。使用低静态功耗的 LDO 稳压芯片。在无消息时段让 MCU 进入 sleepLoRa 模块进入 CAD 模式周期性检测信道前导码。CAD 模式是一种“先侦听、再接收”的模式。节点不是一直全速接收而是定时检查空中是否有 LoRa 前导码没有就继续休眠。这种方式能显著降低平均功耗但会增加延迟。如果应用允许秒级延迟CAD 轮询是首选方案。6.3 功耗验证思路不要根据芯片手册上的数值直接估算续航必须实测。方法很简单用 USB 电流表接在电源输入端。分别测量空闲状态、接收状态、发射状态三种电流。根据消息频率估算平均电流。再用电池容量除以平均电流得到理论续航时间。还需要考虑电池自放电、低温容量衰减和稳压电路效率理论值通常打七折到八折才是实际可用值。7. 现场部署与传输距离验证7.1 天线位置与极化部署中继器时天线高度和位置比发射功率的影响更大。越高越开阔越好天线周围尽量避免金属遮挡。同时所有节点的天线极化方向最好一致比如都是垂直极化。如果一个节点天线横放另一个竖放信号损耗会非常明显。实际项目里中继器外壳可以用 PVC 管做立柱把天线固定在管顶部模块和电池放在管内下部防止雨水进入。7.2 距离验证流程不要一上来就挑战最大距离。建议按以下流程逐步验证两个端节点距离 10 米先验证配对成功和消息收发正常。拉大到 200 米记录 RSSI 和 SNR。加入中继器放在两个端节点之间验证中继链路。逐步拉开距离直到出现丢包再往回收紧。每次测试都用固定文本消息循环发送例如每 5 秒发送一次连续发 50 次统计成功率。成功率在 90% 以上才适合正式使用低于 90% 要优先调整天线和位置。7.3 用日志评估链路质量在端节点和中继器固件中加入日志输出把每次收包的 RSSI、SNR、源 ID、序号打印出来。[RECV] src1 seq12 rssi-87 snr8.5 ttl2 [RECV] src1 seq13 rssi-91 snr6.2 ttl2 [RELAY] src1 seq13 - dst2 ttl1RSSI 的绝对值越小越好SNR 越大越好。如果 RSSI 接近 -120dBm 且丢包严重说明链路余量不足需要调整位置或天线。从这些日志里还能直接看到中继器是否正确改写了 TTL有没有重复转发。8. 常见问题与排查问题现象可能原因排查方式解决方案两个节点收不到对方的包频率、带宽、扩频因子不一致对比各节点初始化配置统一参数检查同步字和网络 ID中继器收到包但目标节点没收到中继转发条件未满足或 TTL 耗尽查看中继器串口日志是否打印 RELAY 信息检查目的 ID 和 TTL 初始值收到重复消息多个中继节点同时转发同一包查看目标节点收到相同 seq 的次数启用去重表增加随机退避距离很近但 RSSI 很差天线不匹配、馈线过长、极化方向不一致更换天线缩短馈线统一极化方向使用匹配频率的外置天线设备一段时间后不工作供电电压下降MCU 复位测量电池电压查看复位日志增加低电压关机阈值优化休眠策略发送时自身收到自己的包没有合理配置接收过滤检查中继器是否收到自己转发的包判空 relay_id 与当前 ID 相同则丢弃消息偶尔丢失信道冲突、发射中接收查看日志中是否出现接收中断提前触发引入随机退避和重发机制排查时先看日志再动硬件。大多数问题在日志里都能找到直接证据不要盲目换模块。9. 工程最佳实践与合规提醒9.1 可靠性设计固件版本号要体现在启动日志里方便现场判断烧录的是哪个版本。配置文件用单独的头文件管理把节点 ID、频道参数、TTL 初始值集中在同一处避免改代码时漏改。中继器的串口日志建议开启但正式部署后可以降低日志等级减少干扰。如果你在测试中需要反复烧录先把每个节点的角色和 ID 写在标签上贴到外壳上。中继部署在野外后调试不方便良好的文档能省很多时间。涉及自动重启逻辑时要加看门狗定时器。LoRa 节点长期无人值守偶发死机会因为看门狗复位而自动恢复。在代码中启用看门狗的示例写法#include avr/wdt.h void setup() { // 其他初始化... wdt_enable(WDTO_8S); // 8 秒内未喂狗则复位 } void loop() { // 主循环... wdt_reset(); // 在每次循环或任务完成后喂狗 }9.2 无线电合规LoRa 使用公共频段但不同地区对频率、发射功率、占空比有明确规定。部署前一定要确认项目所在地允许使用的具体频段和功率上限并通过合法渠道使用。不要私自改装大功率功放不要干扰其他合法无线电业务不要在禁止使用的场所开机。涉及频段、发射功率、天线规格的调整请以当地无线电管理机构最新文件为准。9.3 最后建议如果你刚接触 LoRa最容易犯的错误是把所有时间花在选模块和调天线上结果跳过了协议设计。先做一对一的点对点通信确认硬件链路可靠再加入一个中继节点验证 TTL、去重和转发逻辑最后再考虑太阳能供电、外壳防护和批量部署。每一步都验证通过再继续下一步这个项目并不难难的是在看似简单的“转发”里把边界条件处理好。真正动手之后你会发现最值得琢磨的部分不是射频而是一个朴素的问题当一个数据包在一个多跳网络里被复制、转发、延迟之后如何保证它只到达它该去的地方且只到达一次。这个设计思路放到任何自组网系统里都通用。