1. 项目概述与整体设计思路
1.1 这是个什么项目,解决什么问题
串口转LoRA模块单元,从名字就能看出来,它干的事情就是把传统的UART串口数据,通过LoRA无线链路发送到远端,同时也能把远端回传的数据还原成串口数据。如果你手里有一堆只有串口输出的传感器、仪器仪表、单片机开发板,想把数据传到几百米甚至几公里之外,又不想布设线缆,这个模块就是中间那座桥。
我选型用的E22-900M22S是亿佰特家的LoRA模组,工作在868/915MHz频段,内置的射频芯片是Semtech的LLCC68,很多人可能更熟悉SX1262,LLCC68本质上就是SX1262的窄带版本,最大发射功率22dBm(约158mW),接收灵敏度能到-137dBm左右,这个参数在远距离低速率场景下非常能打。主控部分我选了树莓派Pico,原因很简单——RP2040这颗芯片带两个UART,价格便宜,MicroPython开发效率高,调试起来比裸机C舒服得多。
这个单元做好之后,典型应用场景包括:
- 农业大棚里的温湿度传感器数据采集,传感器用485或者TTL串口输出,LoRA模块把数据发回中控室;
- 工业现场的设备状态监测,PLC或者仪表只有串口,不方便走线的地方用LoRA透传;
- 临时部署的数据采集链路,比如野外环境监测,架好就能用,不用考虑网络覆盖;
- 智能楼宇里各种串口设备的无线化改造。
整个系统可以说是一个“数据搬运工”,对数据内容不做任何解释,只负责把串口上收到的字节原封不动地搬到无线链路上,再从无线链路上原封不动地吐回串口。这也是LoRA模块最常见的用法——串口透传。
1.2 为什么选E22-900M22S而不是其他模组
市面上串口转LoRA的方案其实很多,有直接用SX1268/SX1276自己画板的,也有买现成透传模块的,比如亿佰特E22系列、安信可的LoRa模块等等。我最后选E22-900M22S,主要是从这几个角度考虑的:
首先是频段匹配。E22-900M22S工作在850~930MHz(不同批次略有差异),在这个频段,国内使用不需要申请专门的频率许可(前提是功率合规),而且900MHz频段在城市环境下的绕射能力和穿透能力比2.4GHz好,比433MHz带宽更宽、天线更短,属于一个比较折中的选择。
其次是模组本身的集成度。E22-900M22S内部已经把射频匹配、滤波、PA、LNA都做完了,外部只需要接一根天线,不需要自己画射频阻抗匹配。这个是新手最容易翻车的地方——433MHz或者915MHz的射频匹配,板上走线稍微长一点,寄生电容稍微大一点,驻波比一上来,发射功率直接打骨折。用模组就完全绕开了这个问题,我只需要关心它暴露出来的接口引脚就行。
再就是驱动方式灵活。E22-900M22S支持通过UART AT指令配置,也可以配置成透传模式之后上电自动进入透传。这意味着我可以先用USB转TTL接电脑把参数配置好,然后再接到Pico上运行,调试路径非常清晰。
1.3 树莓派Pico作为主控的过人之处
树莓派Pico在这个项目里承担的角色是“串口桥接器 + 逻辑控制”。我需要它做以下几件事:
- 从某一个UART口接收外部设备(比如传感器)发来的数据;
- 把数据打包或者原样交给E22-900M22S,通过另一个UART口发送;
- 反过来,从E22-900M22S接收无线链路的数据,再从另一个口吐出给外部设备;
- 顺便控制一下E22-900M22S的M0/M1引脚,用于切换工作模式。
这些活儿用STM32当然也能干,但Pico有一个巨大的优势:MicroPython环境下,串口读写就是open、read、write这么简单,不需要翻寄存器手册配置波特率、校验位、DMA,也不需要处理中断优先级。对于这个项目的核心目标——快速搭建一个可用的串口转LoRA单元——Pico的开发效率是碾压级的。
另外Pico的供电很宽松,官方规格是1.8V~5.5V,但实际用USB的5V供电或者3.3V的LDO都行,配合E22-900M22S的2.3V~3.6V供电范围,直接用Pico板载的3.3V输出给模组供电就行,不用额外做电源轨,省了不少事。
2. 硬件准备与接线设计
2.1 器件清单
我自己做这个项目用到的全部物料如下表:
| 器件 | 型号/规格 | 数量 | 备注 |
|---|---|---|---|
| 主控板 | 树莓派Pico(RP2040) | 1 | 带针脚版本更好接线 |
| LoRA模组 | E22-900M22S | 1 | 亿佰特,22dBm,SMA-K接口 |
| 天线 | 868MHz/915MHz胶棒天线 | 1 | 增益2~3dBi即可 |
| USB转TTL | CH340模块 | 1 | 调试阶段配置模组用 |
| 面包板 | 830孔 | 1 | 原型验证用 |
| 杜邦线 | 母对母、公对母若干 | 若干 | 建议不同颜色区分电源和信号 |
| 稳压/供电 | 5V USB电源或3.7V锂电池 | 1 | 便携场景建议锂电池 |
| 电阻 | 10KΩ上拉电阻 | 2 | M0和M1引脚默认上拉 |
这里面有一个容易被忽略的点:E22-900M22S的M0和M1引脚不能悬空。这两个引脚内部虽然有下拉,但官方推荐的可靠做法是外部加上拉电阻到VCC,或者直接接高电平,通过拉低来切换模式。我见过不少人把M0/M1悬空导致模组偶尔进入异常模式,数据发不出去,排查半天发现是模式引脚电平漂了。所以面包板上先把10KΩ上拉电阻安排上,稳。
2.2 引脚定义与接线表
E22-900M22S的引脚不算多,核心就是VCC、GND、TXD、RXD、M0、M1。它的TXD是模组发送数据给外部MCU的线,RXD是模组接收外部MCU数据的线,这俩和MCU的UART要交叉连接——MCU的TX接模组的RXD,MCU的RX接模组的TXD,这个基础接线问题是新手问得最多的问题,每次都有人接成顺连然后问为什么收不到数据。
树莓派Pico的GPIO0和GPIO1对应UART0的TX和RX,GPIO4和GPIO5对应UART1的TX和RX。我这里的分配方案是:
| Pico引脚 | 功能 | 接到E22-900M22S | 说明 |
|---|---|---|---|
| GPIO0 | UART0 TX | RXD | 向模组发送AT指令/数据 |
| GPIO1 | UART0 RX | TXD | 从模组接收数据 |
| GPIO2 | 普通输出 | M0 | 模式控制,低有效 |
| GPIO3 | 普通输出 | M1 | 模式控制,低有效 |
| 3V3 | 电源正 | VCC | 模组供电 |
| GND | 电源负 | GND | 共地,必须连接 |
| 无 | 无 | AUX | 可选,悬空或接GPIO用于状态判断 |
如果你后续要把这个模块做成一个独立单元,建议把UART1(GPIO4/GPIO5)留出来作为“外部串口”,也就是说:外部传感器的数据线接到Pico的GPIO4(UART1 TX)和GPIO5(UART1 RX),Pico内部做数据搬运,把UART1收到的数据通过UART0转发给LoRA模组。这样外部串口和无线链路就是物理隔离的两个通道,逻辑更清晰。
2.3 供电方案与注意事项
E22-900M22S的供电范围是2.3V~3.6V,这意味它不能直接吃5V。如果用USB给Pico供电,Pico板载的3.3V LDO输出的电流足够驱动模组(模组发射时的峰值电流在100mA~120mA左右,Pico的3V3引脚可以承受),所以直接VCC接Pico的3V3输出即可。
但如果想用锂电池(3.7V)供电,就必须注意:3.7V锂电池满电时是4.2V,直接进Pico的VSYS(5V轨)没问题,但不要直接给模组的VCC供4.2V。要么经过Pico的板载稳压,要么自己加一个低压差LDO(比如ME6211或XC6206)降到3.3V。我一开始图省事,直接把电池正极接到了面包板的3.3V轨上,结果LoRA模组偶尔重启,后来查到是电压超规格了,模组的内部保护电路动作。
共用电源还有一个细节:天线要远离电源走线,尤其是模组发射瞬间电流变化大,如果天线离电源线太近,射频能量会耦合到电源上,造成辐射杂散超标和数据误码。面包板原型阶段可能还好,做成PCB之后这点尤其重要,天线区域下方尽量不要走电源和地。
3. 模组初始化配置与重要参数解析
3.1 通过AT指令配置模组
E22-900M22S上电默认是透传模式,如果要改配置,需要把M0和M1拉高进入AT模式。它有两种AT模式:模式0(M0=0, M1=0)是透传模式,也是正常工作模式;模式1(M0=1, M1=0)是AT指令模式,可以通过串口发送AT指令查询和修改配置;模式2和模式3分别是“双唤醒”和“深睡眠”之类的,这个项目用不上。
我的建议是:先用USB转TTL把模组单独接到电脑上,用串口调试助手配置好参数,然后再接到Pico上跑。这样配置过程所见即所得,不用在MicroPython里写一长串AT指令然后猜测有没有生效。
具体操作流程:
- 把E22-900M22S的M0和M1通过10K电阻上拉或者直接接VCC,进入AT模式;
- USB转TTL的TX接模组RXD、RX接模组TXD,共地,VCC接3.3V;
- 打开串口调试助手,波特率选择9600(出厂默认),发送
AT+RX,模组应该回复OK+...之类的信息; - 用
AT+ADDR查询/修改设备地址,用AT+NETID设置网络ID,用AT+BAND设置频点,用AT+UART设置串口参数,用AT+POWER设置发射功率,用AT+AIR设置空中速率; - 配置完成后发送
AT+RESET让模组重启,然后把M0/M1拉低,进入透传模式。
下面是这个项目我用到的几组核心配置指令(注意不同固件版本的指令集可能略有差异,具体以模组配套的数据手册为准):
| 指令 | 含义 | 我的配置 | 说明 |
|---|---|---|---|
| AT+ADDR=0001 | 设置设备地址 | 0001 | 两个模块地址要一致才能互通 |
| AT+NETID=10 | 设置网络ID | 10 | 相当于虚拟信道隔离 |
| AT+BAND=915000000 | 设置中心频率 | 915MHz | 需要双边一致 |
| AT+UART=9600,8,1 | 串口参数 | 9600,8N1 | 与Pico的UART配置一致 |
| AT+POWER=22 | 发射功率 | 22dBm | 最大功率 |
| AT+AIR=19 | 空中速率 | 见下文 | 需要双边一致 |
3.2 空中速率、发射功率与通信距离的取舍
E22-900M22S的空中速率(Air Data Rate)是一个关键参数,它直接决定了吞吐量、接收灵敏度和通信距离之间的平衡。这个模组的空中速率可以设置在2.4kbps~62.5kbps之间(不同版本可能更高),速率越低,接收灵敏度越好,通信距离越远,但同样大小的数据包在空中的占用时间越长。
这里有个经验公式可以参考:单包传输时间 = 前导码时间 + 数据负载时间。LoRA的机制决定了前导码是每一包都要带的,而且前导码的时间在不同空中速率下差别很大。举例来说,如果空中速率设为2.4kbps,一个包含10字节有效数据的包,加上必要的帧头、CRC、前导码,在空中的时间可能接近80ms~100ms;如果空中速率提到19.2kbps,同样的包可能只需要15ms左右。
所以在实际项目里怎么选?
- 传感器数据量小(几十个字节)、传输频率低(一分钟一次),优先选低速率(比如2.4kbps~9.6kbps),换更远的距离和更强的穿透力;
- 如果数据量稍大(比如几百字节)、实时性要求高一些,空中速率可以设到19.2kbps以上,但要做好通信距离相应变短的准备。
我实测下来,在空旷环境下,22dBm发射功率 + 915MHz + 2.4kbps空中速率 + 2dBi胶棒天线,通信距离可以稳定达到2km以上;同样条件下把空中速率调到19.2kbps,距离会缩到1km左右。这个衰减是指数级的,不是线性的,所以千万别为了那点速率牺牲距离,除非你真的需要。
3.3 通信双方配置必须一致,否则静默失败
这是透传LoRA最容易踩的坑:两边的地址、网络ID、频点、空中速率必须完全一致,否则数据包直接丢掉,没有任何提示。
我自己调试时就遇到过:A模块配置的是915MHz,B模块配置的是868MHz,两边串口都正常,A发数据B收不到,B发数据A也收不到,用频谱仪一测才发现两个模块根本不在一个信道上。E22-900M22S本身有定频和跳频两种模式,默认是定频,所以频点不对就是完全隔离。
另外一个容易忽略的是网络ID(NETID)。这个参数相当于逻辑信道隔离,同一频点上不同NETID的模块互不干扰。如果你在一个区域部署了多组LoRA设备,每组用不同的NETID可以有效防止串扰。但反过来说,如果两边NETID不一致,即使频点一致也收不到。
所以我强烈建议:配置完之后,先用电脑上的串口调试助手做双向透传测试,确认A→B和B→A都能通,再接Pico。这个步骤只要花5分钟,但能省掉后面一两个小时的排错时间。
4. 树莓派Pico上的MicroPython代码实现
4.1 代码逻辑与整体框架
Pico端的功能非常单纯:两个UART口,一个接外部设备,一个接LoRA模组,中间做数据搬运。但搬运方式不同,效果差异很大。
最简单的做法是“裸透传”:UART1收到一个字节就立刻从UART0发出去。这样延迟最低,但如果外部设备发来的数据是分帧的,中间间隔稍长,LoRA会把每一小段当成独立的一包数据发送,无线链路的利用率极低,而且对端拼包会很痛苦。
更好的做法是“分包透传”:在内存里攒够一定字节数(比如64字节或者128字节),或者等待一定空闲时间(比如50ms),再一次性发给LoRA模组。这样做的好处是无线链路上每个数据包都接近模组的单包最大负载,效率高,对端也容易解析。
我的实现方案是空闲超时分包:
from machine import UART, Pin import time import utime # UART0: 连接E22-900M22S(LoRA模组) lora_uart = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1), bits=8, parity=None, stop=1) # UART1: 连接外部串口设备 ext_uart = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5), bits=8, parity=None, stop=1) # M0和M1引脚,拉低进入透传模式 M0 = Pin(2, Pin.OUT) M1 = Pin(3, Pin.OUT) M0.value(0) M1.value(0) BUF_SIZE = 128 IDLE_TIMEOUT_MS = 50 rx_buf = bytearray() while True: # 从外部串口读取数据 if ext_uart.any(): rx_buf += ext_uart.read(ext_uart.any()) # 如果缓冲区满,立即发送 if len(rx_buf) >= BUF_SIZE: lora_uart.write(rx_buf) rx_buf = bytearray() # 如果缓冲区非空且达到空闲超时,则发送 if rx_buf and (utime.ticks_diff(utime.ticks_ms(), last_rx_time) > IDLE_TIMEOUT_MS): lora_uart.write(rx_buf) rx_buf = bytearray() # 从LoRA模组读取数据,转发到外部串口 if lora_uart.any(): data = lora_uart.read(lora_uart.any()) ext_uart.write(data) last_rx_time = utime.ticks_ms()4.2 代码逐段拆解
上面这段代码有三个关键点值得展开讲。
第一个是UART初始化参数。这里波特率设9600、8位数据、无校验、1位停止位,这是最常见的串口参数,E22-900M22S出厂默认也是9600 8N1。但注意,LPUART和普通UART在这颗芯片上的波特率误差不一样,Pico的UART0和UART1都是普通UART,9600波特率下偏差在0.2%以内,任何情况下都不会出问题。如果你用其他主控,比如STM32的LPUART,低速时钟源可能导致9600波特率在低温下偶发误码,这个细节值得留心。
第二个是M0/M1引脚的拉低时机。我在代码里把M0和M1都设为0,这是透传模式。但有个细节:E22-900M22S的模式切换不是瞬间生效的,手册里说配置切换后需要等待至少100ms,让模组内部的射频状态机完成切换。所以如果你的代码里需要动态切换AT模式和透传模式,在拉高/拉低之后最好加一个utime.sleep_ms(200)的延时,否则模组可能还在上一个模式里响应,产生意想不到的结果。
第三个是空闲超时逻辑。这里的核心是用utime.ticks_ms()记录最近一次收到外部数据的时间,然后不断比较间隔是否超过50ms。这个50ms的取值是经验值——如果外部设备的数据帧间隔小于50ms,它们会被合并成一包发送;如果间隔大于50ms,就会被拆成两包。具体取多少取决于你的数据源特性:GPS模块的NMEA数据是一秒一帧,50ms足够;某些高速传感器的数据间隔可能只有几毫秒,这时可以缩短到10ms;如果数据是频繁不定长上报,建议把超时调到100ms左右,宁可延迟一点也要保证一包数据的完整性。
4.3 一个更稳健的带ACK可选项版本
如果你担心无线链路丢包,LoRA本身有前向纠错(FEC)和CRC校验,在多数场景下误码率已经很低了,不需要额外做ACK确认。但如果你的应用对数据完整性要求很高(比如控制指令下发),可以考虑在协议层加一个轻量确认机制。一个最简单的做法是:
CMD_REQ = b'REQ:' CMD_ACK = b'ACK:' def send_with_ack(data, timeout_ms=1000): lora_uart.write(CMD_REQ + data) start = utime.ticks_ms() while utime.ticks_diff(utime.ticks_ms(), start) < timeout_ms: if lora_uart.any(): resp = lora_uart.read() if resp.startswith(CMD_ACK): return True return False发送方在发出数据后等待对端的ACK,超时则重发。这个方案在“点对点确认”场景下够用,但要注意:LoRA是半双工的,对端在收到数据后不能立刻回ACK,因为无线信道还需要处理收发切换,所以ACK的超时时间至少要留200ms以上,否则对端根本来不及回复。
5. 关键指标实测与性能测算
5.1 单包传输时长与吞吐量上限
设计串口转LoRA单元之前,最好先算一笔账:你期望的通信频次和数据量是多少,LoRA链路能不能承载?
我以实测配置为例:空中速率19.2kbps,10字节有效负载。通过逻辑分析仪抓取E22-900M22S的TXD引脚,可以看到从发送数据进入模组,到数据从天线发射出去,整包耗时大约15ms~20ms。如果按20ms估算,单包空中占用时间占20ms,理论上一秒最多发50包,一包10字节,吞吐量上限就是500字节/秒。
如果把空中速率降低到2.4kbps,同样的10字节数据包,空中时间会膨胀到约80ms,一秒最多12包,也就是120字节/秒。这个数字对于大多数传感器上报场景(一分钟一包、每包二三十字节)完全够了,但如果你打算传音频流或者高速采样数据,LoRA这条链路就远远不够。
建议在实际设计时把最大单包长度、空中速率、发送频次三个参数做一张兼容性检查表,确保不超出链路能力。
5.2 通信距离实测
我在一个城郊开阔地进行过简单测试,环境是草地+少量低矮树木,天线高度约2米(手持),配置为22dBm发射功率、915MHz、空中速率9.6kbps、2dBi胶棒天线:
| 距离 | 结果 | 备注 |
|---|---|---|
| 500m | 稳定,RSSI约-75dBm | 偶发丢包,但重传后恢复 |
| 1km | 稳定,RSSI约-95dBm | 数据延迟约80ms |
| 1.5km | 临界,RSSI约-110dBm | 丢包率升高到10%左右 |
| 2km | 基本不可用 | 天线高度降低后完全断连 |
这个结果说明一点:天线高度对通信距离的影响是决定性的。同样的发射功率和接收灵敏度,把天线从2米抬到5米,通信距离几乎翻倍。如果你要固定部署,尽量把天线架高、避开金属遮挡,效果远好于加大功率。
LoRA的接收灵敏度曲线在接近极限时会快速恶化,不是线性衰减。所以设计链路预算时,建议按“比模组标称灵敏度多留10dB余量”来做,否则到了现场会因为天气、电磁干扰、天线方向性等因素频繁丢包。
5.3 功耗与供电余量
E22-900M22S的规格书标注发射电流约110mA@22dBm,接收电流约5.5mA,睡眠模式更低。如果系统由电池供电,要重点考虑发射功耗。
举个例子:10秒上报一次数据,每次发射50ms,平均电流就是110mA × (50ms/10000ms) = 0.55mA,加上接收待机电流约5.5mA,再加上Pico本身的运行电流(RP2040跑MicroPython大约20mA~30mA),总平均电流大约30mA。用一节2000mAh的18650锂电池,理论续航约60小时,实际打个七折大约40小时。如果想提升续航,可以让Pico进入睡眠模式,定时唤醒发送数据,平均电流可以降到几毫安,续航就能拉长到一周以上。
6. 常见问题与调试技巧实录
6.1 数据发不出去或收不到,从哪查起
这个项目最典型的故障是“两边串口都通了,但LoRA之间不通”。我的排查顺序是固定的:
第一步,确认模组供电和天线。用万用表量VCC对GND电压是否稳定在3.3V;天线是否拧紧,SMA头是否完全到位。很多人天线没拧紧,射频能量反射回功放,不仅发射不出去,还可能烧模组。
第二步,确认M0/M1模式。用万用表量一下这两个引脚的电压,透传模式应该是低电平(0V)。如果测量到高电平,检查上拉电阻是不是接错了,或者GPIO初始化时是否先设置了高电平导致模组开机瞬间进入了AT模式。
第三步,确认两边参数一致。通过串口调试助手对每个模块执行AT+RX之类的查询指令,对比地址、频点、空中速率、NETID。特别注意空中速率的单位——有些固件显示的是kbps,有些显示的是索引值,不要被表面数字骗了。
第四步,用频谱仪或者第二个接收模块做空中抓包。如果没有频谱仪,最简单的方法是准备第三个E22模块,设置成与发送方相同参数,接在电脑上,用串口助手看能不能收到数据。如果第三方能收到,说明发送方空中链路正常,问题出在接收方的串口或者接线。
6.2 串口数据乱码
乱码的原因通常是波特率不匹配。排查时用示波器测一下发送端TXD引脚的波形,量一下一位的脉宽,用1除以脉宽就是实际波特率。比如量到104微秒,那就是9600波特率;如果量到52微秒,实际上是19200。
另一个容易忽略的是电平标准。E22-900M22S和Pico都是3.3V TTL电平,但如果外部设备是5V的串口,直接连接可能把模组或者Pico的引脚打坏。这种情况下需要做电平转换,用两个MOS管搭的简单双向电平转换电路就可以,或者直接买现成的电平转换模块。
6.3 距离拉不远
距离拉不远,最可能的原因是天线问题。做一个简单的驻波比测试:把天线拆下来,接上一个50Ω的假负载,如果发射电流基本不变,说明模组输出正常;如果接天线和接假负载时的电流差别很大,说明天线和模组之间阻抗不匹配。
此外还要检查天线是否在正确的频段上。E22-900M22S默认是915MHz,如果配了一根868MHz的天线,虽然中心频率差得不远还能凑合用,但效率会打折扣,如果是433MHz的天线插上去,那基本就是废的。
6.4 干扰与串扰问题
915MHz附近有一些其他的无线设备(比如部分航空导航系统、工业设备),在城市里还可能遇到运营商的某些频段干扰。我在调试时遇到过一次,数据时不时丢包,用频谱仪一看,某个信道一直有一个-90dBm左右的窄带干扰信号,后来把频点往上偏了2MHz,问题就消失了。
所以在正式部署时,建议用频谱仪扫一下现场电磁环境,选一个干净的频点。如果条件不允许,优先选择厂家预置的非默认频点,减少和周围其他同频设备冲突的概率。
6.5 一个容易被忽略的坑:模组AUX引脚的用法
E22-900M22S有一个AUX引脚,用于指示模组的收发状态。在实际调试时,这个引脚非常有用:当模组正在通过无线链路发送数据时,AUX引脚会输出低电平;数据发送完成、模组空闲时,AUX是高电平。
如果在发送完数据后立即让MCU进入睡眠,或者立即切换M0/M1模式,必须等待AUX引脚拉高,否则模组可能正在忙,指令会丢失。我的建议是,在代码里把AUX接到Pico的GPIO6,每次往模组写入数据后轮询AUX直到拉高再执行下一步:
AUX = Pin(6, Pin.IN) def wait_lora_free(): while AUX.value() == 0: utime.sleep_ms(1) lora_uart.write(rx_buf) wait_lora_free()这个技巧在低功耗场景下尤为重要——如果没有等待AUX就休眠,模组发送到一半突然断电,不仅当前这包数据会丢,还可能导致模组内部状态机错乱,下次上电后无法正常工作。
7. 项目后续扩展思路
7.1 双向数据通道带优先级控制
简单的透传模式下,数据是“谁先来谁发送”的FIFO方式。但如果你既要传输传感器上行数据,又要偶尔下发控制指令,可以考虑在协议层做优先级:控制指令优先发送、传感器数据排队等待。
具体做法是在Pico代码里维护两个缓冲区,一个高优先级(控制指令),一个低优先级(传感器数据),每次从LoRA模组读取数据后,优先处理高优先级缓冲区的发送任务。LoRA是半双工机制,无法同时收发,所以高优先级指令必须等待当前发送完成,但可以做到“一旦空闲就立刻插队”,在多数场景下这个响应速度足够。
7.2 多节点组网
E22-900M22S本身是点对点或者广播模式,不支持复杂的Mesh组网。如果你有多个节点需要汇聚到一个网关,可以做星型拓扑:所有终端节点配置同一个频点但不同的地址,网关端用一个地址接收,通过数据内容中的源地址字段区分是哪个节点发的。
这种方案的好处是简单可靠,缺点是网关端如果同时向多个节点下发指令,需要做好时分调度,不能同时发两个指令,否则目标节点中的另一个会被误触发。
7.3 与云平台的对接
串口转LoRA单元最常见的扩展方向是加一个4G Cat.1模块或者WiFi模块,让网关把LoRA汇聚上来的数据转发到云平台。我在实际项目中这么做过:网关端用Pico接收LoRA数据,再通过一个串口4G模块(比如EC800M)把数据以MQTT协议发布到物联网平台。这样整体链路就是“传感器 → 串口 → LoRA → 网关 → 4G/WiFi → 云”,传感器端完全不需要接入互联网,功耗低、成本低,非常适合户外部署。
这个扩展的难点在于4G模块的AT指令解析和MQTT报文构造,但好消息是这类模块厂商一般都会提供现成的SDK或者参考例程,在Pico上只需要处理好串口之间的数据流转即可。
7.4 低功耗唤醒模式
如果整个单元需要电池供电且长期无人值守,E22-900M22S的低功耗模式值得研究。它支持定时唤醒和外部唤醒两种方式:定时唤醒模式下,模组定期进入接收窗口,发射端在发数据前先发送一串唤醒码,等接收端醒过来再发正式数据。
树莓派Pico本身也有休眠模式,可以把RP2040的功耗控制到µA级别,配上LoRA的低功耗接收窗口,整个系统的平均功耗可以压得很低。我测试过一组方案,30s上报一次、每次发射100ms,两节AA电池理论上可以工作半年以上。
当然,低功耗设计的代价是实时性下降——接收端不是一直在线,指令下发可能有几十秒甚至更长的延迟。需要权衡好你的应用场景是“定期采集”还是“实时响应”,再把省电策略做进去。
8. 写在最后的调试心得
做串口转LoRA模块单元这类项目,最怕的不是不会写代码,而是遇到问题没有系统性的排查思路。我个人的经验是,任何无线项目的调试都要遵循“先有线,再无线;先单点,再组网”的原则:
先有线——确保两个串口(外部设备到Pico、Pico到LoRA模组)的数据收发都是通的,用一根杜邦线把TXD和RXD短接做回环测试,能收到自己发的数据就说明串口链路没问题;再无线——通过串口助手直接在两个模组之间做透传测试,确保空中链路通;最后才是组网和协议层面的调试。这样做每一步出现问题都很容易定位,不至于一堆问题纠缠在一起无从下手。
另外一点心得是:E22-900M22S这类模组,官方的数据手册里其实已经把大多数注意事项写得明明白白,关键是调试时愿不愿意静下心去查。比如我前面说的模式切换需要延时、AUX引脚要用起来、天线频段要匹配,这些在手册里都有提及,但新手往往忽略掉,等到现场排查才追悔莫及。
如果你准备复刻这个项目,我建议你把前面的硬件接线、AT配置、Pico代码三步走通之后,先做一个小实验:两个模块,一个接Pico,一个接电脑USB转TTL,中间隔着几百米,用手机和电脑配合测试一下双向收发延迟和丢包率。这个实验做完,你对LoRA这套链路的能力边界和调参方向会有一个非常直观的认知,远比看十篇教程有效。