做物联网的朋友应该都对LoRa不陌生,但真要自己从零搭一个可以用的串口转LoRa模块单元,很多人会卡在选型、接线、配置和天线这几关上。我今天把基于E22-900M22S模组和树莓派Pico的整套设计思路整理出来,从硬件选型到代码实现,再到调试踩坑,一次性讲透。这套方案我实际跑过,稳定性和距离都符合预期,适合做环境监测、农田数据采集、远程控制这类需要低功耗长距离通信的场景,也适合想入门LoRa开发的嵌入式爱好者拿来练手。
1. 整体设计与核心原理
1.1 串口转LoRa的本质:把有线变成无线
串口转LoRa,说白了就是把传统的UART串口数据包,通过LoRa射频调制后发送出去,接收端再把无线信号还原成串口数据。从MCU的角度看,它以为自己在跟一个普通串口设备通信,实际上数据已经飞了几百米甚至几公里。
E22-900M22S是亿佰特的一款LoRa模组,内置SX1262射频芯片,工作在850~930MHz频段,发射功率最高22dBm。它最大的特点是封装了完整的串口透传协议,外部MCU不需要理解LoRa调制解调的底层细节,只需要通过UART给它发数据、收数据,再配几个GPIO管脚做状态判断就行。这颗模组我用下来感觉它的空中速率、发射功率、串口波特率都可以通过AT指令或者在线配置修改,灵活度相当高。
树莓派Pico作为主控,用的是RP2040芯片,双核Cortex-M0+,虽然有主频和内存的限制,但拿来驱动一个LoRa模组绰绰有余。Pico的好处是3.3V电平、价格便宜、MicroPython支持好,调试的时候改代码特别快。如果你手头有其他3.3V MCU,比如STM32、ESP32,这套设计思路完全一样,只需要改一下引脚映射和串口初始化代码。
1.2 为什么选E22-900M22S而不是其他LoRa方案
市面上LoRa方案分两类:一类是纯射频芯片,比如SX1262、SX1278,需要自己写驱动、自己处理协议栈,难度大但灵活度高;另一类是串口透传模组,比如E22系列、E32系列,内部已经做好了LoRaWAN点对点协议,外部MCU只需要操作串口。
我这里选了E22-900M22S,核心考虑有三点:
- 开发周期短。不需要处理射频寄存器配置、CRC校验、数据白化这些底层细节,串口发什么它就发什么,把精力集中在业务逻辑上。
- 带AUX引脚。这个引脚可以输出模组的工作状态,比如是否正在发送数据、是否配置完成,对做可靠通信帮助很大。
- 官方资料齐全。亿佰特的数据手册里提供了参考电路、天线设计建议和AT指令集,照着做不容易翻车。
E22-900M22S还有一个细节要注意:它支持两种配置方式,一种是把M0和M1引脚拉高进入配置模式,通过AT指令修改参数;另一种是直接使用默认参数。我建议你第一次上电先把M0、M1都拉低,进入正常透传模式跑通数据,再回头研究配置。
1.3 适用场景与通信链路估算
LoRa的通信距离受三个因素影响:发射功率、接收灵敏度、天线增益。E22-900M22S的接收灵敏度在SF7速率下约-126dBm,在SF12速率下能到-136dBm左右,发射功率22dBm。在开阔地带、天线架高的情况下,实现3~5公里的通信是没问题的,市区环境下500米到1公里也比较常见。
我做这个模块单元的典型场景是温室大棚环境监测,传感器节点放在大棚角落,网关放在值班室,中间隔了几面墙。用SF10速率、发射功率22dBm,实测能稳定通信,丢包率低于百分之一。如果你想跑更远,可以把空中速率调低,比如SF12,数据速率下降但灵敏度提升,距离能明显增加。当然,实际距离还跟天线质量、馈线长度、周围电磁环境有关,不能只看理论值。
2. 硬件准备与连接设计
2.1 材料清单与模块说明
在做这个项目之前,我建议先把材料备齐,清单如下:
- 树莓派Pico开发板1块。注意不要买成Pico W,虽然Pico W也能用,但板载无线模块跟LoRa模块同时工作的话功耗会高一些,纯做LoRa透传用普通Pico就够了。
- E22-900M22S模组1颗。购买时注意区分频率版本,900M22S覆盖850~930MHz,在国内用920.8MHz附近没问题。
- 3.3V稳压模块1个。如果Pico用USB供电,可以直接从Pico的3V3引脚取电给LoRa模组,但注意Pico板载LDO最大输出电流有限,如果你还要外接传感器,最好单独给LoRa模组供电。
- 天线。推荐外接弹簧天线或者小吸盘天线,SMA接口那种最容易买到。如果自己做板载天线,后面的4.3节会有说明。
- 杜邦线若干、面包板1块、USB转TTL模块1个(用于调试串口)。
为什么特别强调供电?E22-900M22S在发射的时候峰值电流能达到上百毫安,如果电源质量不好,电压跌落会导致射频功率下降甚至模组复位。我踩过这个坑:用过一根长杜邦线从Pico的3V3引脚给模组供电,近距离通信没问题,但距离一拉远就不稳定,后来换成短粗的飞线加一个100uF电容在模组电源脚附近才解决。
2.2 引脚接线图与电平匹配
E22-900M22S模组的引脚不多,关键是TX、RX、M0、M1、AUX、VCC、GND这7个。树莓派Pico侧需要选择两组UART,一组连接LoRa模组,一组用于调试或者跟外部设备通信。Pico的UART0默认是GP0(TX)和GP1(RX),UART1默认是GP4(TX)和GP5(RX)。
我的建议是:LoRa模组接UART1,GP4连接模组的RX,GP5连接模组的TX,注意这里是交叉连接的;把UART0留出来做调试串口,接USB转TTL模块,方便在电脑上看日志。如果你只需要单组串口,也可以把UART0用作与外部设备通信的接口,UART1专门跑LoRa,但这样调试的时候就要拔线,比较麻烦。
模组的M0和M1是模式选择引脚,正常透传模式下都接GND;AUX引脚接Pico的GP6,用来查询模组状态。VCC接3.3V,GND共地。
这里有个新手特别容易搞错的地方:串口通信是交叉连接的,模组的TX要接MCU的RX,模组的RX要接MCU的TX。我见过好几个朋友把两个设备的TX接TX、RX接RX,结果怎么调都不通,还以为是模组坏了。
E22-900M22S是3.3V TTL电平,树莓派Pico也是3.3V电平,两者可以直接相连,不需要电平转换。如果你的主控是5V的,比如Arduino Uno的AVR芯片,就必须加电平转换或者用分压电路,否则长期工作会损坏模组。
2.3 天线的选型与板载天线设计要点
天线是整个射频链路里最容易出问题、也最容易被忽视的环节。很多人买了LoRa模组以后,随手找一根短线接上去,结果通信距离只有几十米,然后开始怀疑模组质量。实际上,LoRa通信距离大部分问题都出在天线上。
如果你用的是外接天线,需要注意三点:
- 阻抗匹配。LoRa频段主流天线都是50欧姆阻抗,购买时认准SMA接口或者ipex接口,不要买成WiFi用的2.4G天线,频率完全不匹配。
- 天线位置。天线要尽量远离MCU、电源走线和金属外壳,最好垂直摆放,天线周围不要有地平面遮挡。
- 馈线长度。SMA馈线越短越好,馈线每增加一米,信号损耗可能达到0.5dB甚至更多。
热搜词里有人问“LoRa模组板载天线怎么画”,这个问题也很典型。如果你要在自己的PCB上画板载天线,E22系列的参考设计里通常提供的是弹簧天线或者PCB天线方案。PCB天线一般用倒F天线或直板天线,长度跟频率强相关。以915MHz为例,四分之一波长天线大约82mm,但PCB天线因为介质材料和地平面影响,实际长度需要通过仿真或者参考厂商图纸确定。我建议你第一次做板子不要自己画天线,直接用模组原厂推荐的陶瓷天线或者IPEX外接天线,走通整个链路以后再考虑天线小型化。
3. 软件实现与参数配置
3.1 MicroPython下的串口初始化和透传代码
树莓派Pico最友好的开发方式就是MicroPython,代码逻辑清晰,改起来也快。下面的代码实现了一个最基础的透传程序:Pico把外部设备发到UART0的数据,原样转发给UART1上的LoRa模组;同时把LoRa模组收到的数据,打印到UART0调试串口。
from machine import UART, Pin import time # 初始化UART0,作为调试串口,波特率115200 uart0 = UART(0, baudrate=115200, tx=Pin(0), rx=Pin(1)) # 初始化UART1,连接LoRa模组,波特率9600 uart1 = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5)) # 初始化AUX引脚,作为输入,检测模组状态 aux = Pin(6, Pin.IN) def wait_aux_high(timeout_ms=1000): start = time.ticks_ms() while not aux.value(): if time.ticks_diff(time.ticks_ms(), start) > timeout_ms: return False time.sleep_ms(1) return True print("LoRa Transparent Relay Start") while True: # 从UART0读取外部设备发来的数据 if uart0.any(): data = uart0.read() if data: # 等待LoRa模组空闲 wait_aux_high() uart1.write(data) print("TX ->", data) # 从UART1读取LoRa收到的数据 if uart1.any(): data = uart1.read() if data: uart0.write(data) print("RX <-", data)这段代码有几个关键点值得细说。uart.any()是MicroPython里判断接收缓冲区是否有数据的方法,返回的是可读字节数,不是布尔值,有些新手直接拿来跟True比较,发现总是进入分支,其实是理解错了。wait_aux_high()这个函数是用来等待LoRa模组AUX引脚变高的,AUX在模组空闲时为高电平,在忙碌时拉低,掌握这个时序能避免你在模组还在处理上一包数据的时候强行发送下一包,导致数据被丢弃。
3.2 参数配置方法:AT指令和在线配置模式
E22-900M22S默认的串口波特率是9600,但如果你要跟外部设备对接,可能需要改成4800、115200等。改参数有两种方式。
第一种是AT指令配置,需要把M0和M1引脚同时拉高,使模组进入配置模式,然后通过串口发送AT指令。我用过的一些指令格式如下:
AT+UART=9600,N,8,1 // 设置串口波特率 AT+POWER=22 // 设置发射功率,单位dBm AT+AIRRATE=10 // 设置空中速率,不同档位对应不同速率 AT+CH=920800000 // 设置工作频率,单位Hz AT+NETID=1234 // 设置网络ID,只有相同NETID的模组才能互通需要注意的是,不同批次模组的AT指令集可能略有差异,建议以你手里模组标签上的版本为准。AT指令发送后模组会返回OK或者ERROR,配置完成以后需要重新上电或者发送AT+REBOOT使参数生效。
第二种方式是用亿佰特官方的RF Setting软件,通过USB转TTL模块连接模组,图形化配置。这种方式更适合新手,不容易把参数写错。配置完以后把M0、M1重新拉低,进入正常透传模式即可。
我在实际使用中通常会配成固定速率和固定信道,比如9600波特率、SF10、920.8MHz,这样收发双方只要约定一致就能通信。如果你有多个节点,建议用不同的网络ID隔离,防止不同系统之间的无线数据互相干扰。
3.3 接收端模块的同步配置
串口转LoRa是点对点通信还是点对多点通信,取决于你配置了几个节点。最简单的是两个模块一对一:A模块接传感器,B模块接网关,两边配置成相同的频率、空中速率、网络ID,然后把A模组的串口数据发出去,B模组就能收到并转发到网关。
如果有多节点需求,E22-900M22S支持多种通信模式:
- 透明传输模式:发送方不管接收方是谁,所有处于同一信道的模组都能收到数据。适合广播通知场景,但安全性不高。
- 定点传输模式:数据包中携带目标地址,只有地址匹配的模组才会输出串口数据。适合点对点定向控制。
- WOR模式:接收方周期性唤醒监听,发送方需要发送前导码长度足够长的数据包,接收方才能在被唤醒时正确捕获。这个模式最省电,但延迟会变大。
我在温室监控项目里用的是定点传输,每个传感器节点有一个固定地址,网关发控制指令时带上地址,只有目标节点会执行,别的节点虽然也能收到无线信号,但会直接丢弃,不会干扰到自家串口。
4. 常见问题与排查技巧实录
4.1 收不到数据:先查串口再查无线
这是我被问得最多的问题。模块单元做好了,调试串口能看到自己发出去的数据,但接收端毫无反应。遇到这种情况,我建议按下面的顺序排查:
- 先用USB转TTL模块直接连LoRa模组,写一个简单的回环测试:把模组的TX和RX用杜邦线短接,然后往串口发送数据,看是否能立即收到。这个测试能验证模组本身是否正常工作、波特率是否匹配。
- 如果回环测试过了,再查你的主控串口引脚是否接反。用万用表量一下模组TX引脚和主控RX引脚的电压,正常情况下空闲时都应该是高电平3.3V。
- 查网络ID和频率。两个模组在同一办公室测试时没必要用不同频率,但如果你改过配置,一定要确认双方的
AT+CH和AT+NETID完全一致。 - 查天线。我遇到过一次天线内芯断了的奇葩案例,模组本身没有问题,但射频信号出不去。换一根天线就好了。
串口调试助手在这里作用很大。把USB转TTL模块接到模组以后,用串口调试助手(比如SSCOM、MobaXterm的串口功能)打开对应COM口,把波特率设置成模组的配置值,直接手动发送十六进制数据,观察模组返回结果。很多串口调试助手还带定时发送功能,可以模拟周期性的数据上报,用来长时间测试稳定性非常好用。
4.2 丢包与乱码:时序问题和供电问题
数据丢包的原因通常不在无线链路,而在串口侧。我遇到过的情况有三种:
- 发送端没有等AUX就绪。如果LoRa模组在处理上一包数据时,你连续往串口写数据,后面的数据就可能被丢弃。解决方法是每次发送前检查AUX状态,或者每包之间的间隔不要低于模组处理时间。
- 波特率不匹配。模组配置成9600,但主控初始化为115200,收到的数据就是乱码。这个排查起来非常快,看一下串口调试助手的接收区就能判断。
- 供电不足导致发射失败。LoRa发射瞬间电流很大,如果电源线过长或稳压芯片余量不足,发射时电压跌落,射频前端的功率放大器就可能工作不正常。我强烈建议在模组的VCC和GND之间加一个100uF电解电容加0.1uF陶瓷电容,靠近模组引脚放置。
另外,串口调试时收到的数据偶尔多一个字节或者少一个字节,大概率是UART帧格式不对,检查一下数据位、停止位、校验位是否跟对端一致。
4.3 常见问题速查表
下面的表格是我做这套设计时整理出来的问题对照表,基本覆盖了大部分新手的坑:
| 现象 | 可能原因 | 解决办法 |
|---|---|---|
| 完全无响应 | 供电异常或引脚接反 | 检查VCC、GND、TX/RX交叉连接,用万用表量电压 |
| 串口收到乱码 | 波特率或数据格式不匹配 | 确认双方串口参数一致,尤其是数据位和停止位 |
| 数据丢失 | 模组忙碌时强发数据 | 发送前检查AUX引脚状态,增加等待时间 |
| 距离达不到预期 | 天线不匹配或安装位置不当 | 换用正确频段的50欧姆天线,远离地平面 |
| 配置后不生效 | 参数未保存或未重启 | 发送AT+REBOOT或断电重启 |
| 多个节点间互相干扰 | 网络ID相同 | 为每个系统分配不同的网络ID |
4.4 CH340与FTDI串口驱动的坑
调试过程中经常需要跟USB转TTL模块打交道,而Windows系统对CH340和FTDI芯片的驱动支持情况不一样。CH340在Windows 10以上版本基本是即插即用,但某些精简系统需要手动安装驱动;FTDI芯片在驱动未正确安装时会把设备识别为USB Serial Converter而不是COM口,导致串口调试助手找不到设备。
遇到这种情况,我的建议是先打开设备管理器,看端口列表里有没有带感叹号的设备,如果有,直接右键更新驱动;如果驱动正常但还是打不开串口,多半是串口被占用,比如串口调试助手里面已经打开了同一个COM口,或者你之前打开过minicom没有正常释放。Linux下还常见ttyACM0被锁定报错的问题,一般是modemmanager服务抢占了串口,停掉那个服务或者加udev规则能解决。
4.5 串口调试助手的选型建议
调试串口转LoRa模块,核心工具就是串口调试助手。Windows环境我推荐MobaXterm自带的串口终端,既能普通收发又能定时发送;也可以直接用开源的SSCOM5.13.1,它支持中文显示、HEX收发、文件发送,功能足够。macOS用户可以试试Serial Tools,或者用screen /dev/tty.usbserial-xxx 9600这个命令行方式,简单直接。
如果你需要做数据统计分析,比如统计一段时间内的收发字节数、错误帧数,可以自己写一个简单的Python脚本,用pyserial库打开串口,记录数据并计算丢包率。我在实测E22-900M22S通信稳定性时就是这么干的,连续跑24小时,统计发送和接收的包数,计算丢包率是否在可接受范围内。
5. 功能扩展与模块化设计建议
5.1 加入RS485接口支持工业场景
很多工业现场的设备是RS485接口,而E22-900M22S和树莓派Pico都是TTL电平。如果你要做串口转LoRa模块,希望直接对接RS485设备,需要在中间加一个TTL转RS485的收发器芯片,比如SP3485或MAX485。接法很简单:Pico的UART TX和RX分别接收发器的DI和RO,再加一个GPIO控制收发器的DE和RE引脚,发送数据前拉高,发送完毕后拉低。
注意RS485是半双工通信,发送和接收不能同时进行。你在写透传代码时,需要根据RS485的时序特点增加方向切换的延时,否则会出现发送还没结束就开始接收,导致数据截断。
5.2 低功耗休眠策略
LoRa的一大优势是低功耗,但如果你的主控一直在跑轮询循环,做LoRa模块省电就无从谈起。树莓派Pico支持休眠模式,在MicroPython里可以用machine.lightsleep()或machine.deepsleep()。比较实用的策略是:平时让Pico进入休眠,LoRa模组设置成WOR模式周期性监听,一旦收到唤醒数据,通过AUX引脚或者中断唤醒Pico,完成数据采集后再继续休眠。
不过E22-900M22S在WOR模式下需要接收方和发送方都配置成匹配的WOR周期,否则接收方沉睡时发送方发数据会丢失。这个配置要仔细看亿佰特的PDF,不同固件版本的时序差异比较大。
5.3 多设备组网与自定义协议
如果你想做星型网络或者简单的点对多点协议,可以在透明传输之上加一层自己的协议封装。比如设计一个简易帧格式:
[起始字节0xAA] [目的地址1字节] [数据长度1字节] [数据N字节] [CRC16校验2字节]Pico每次收到串口数据后,按照打包函数生成这个帧,再交给LoRa模组发送;接收端解析帧头、校验CRC,只有通过校验的数据才输出给外部设备。这样做的优点是协议可控,不会因为透明传输模式下的串口噪声产生误动作。
我实际测试过,E22-900M22S在9600波特率下的单包最大长度是200字节,如果你的业务数据包超过了这个长度,需要在发送端做分包处理,接收端做组包。分包时要注意每包之间的发送间隔,不能让LoRa模组的缓冲区和处理速度跟不上。
5.4 从原型到PCB的注意事项
原型验证阶段可以用面包板和杜邦线,但如果你想做成一个长期稳定运行的模块单元,还是建议画一块小的PCB。画PCB时重点注意:
- 晶振、射频电路尽量靠近LoRa模组的射频引脚,走线要短。
- 模组下方不要铺地铜,让地平面在模组周围保持完整,但模组底部的地焊盘要与主地平面良好连接。
- 电源走线要加粗,至少20mil以上,电源引脚附近放去耦电容。
- 天线区域要净空,顶层和底层都不能有走线和覆铜,天线两侧最好加一排地过孔做隔离。
我自己画第一版PCB时就是照搬了亿佰特官方的参考设计,然后把UART引脚引到排针上,调试方便,实测发射功率和接收灵敏度和开发板没有明显差异。
6. 我把这套方案用在真实项目中的体会
这个串口转LoRa模块单元做下来,我个人最大的感受是:选对了模组,整个项目就成功了一半。E22-900M22S把射频最复杂的部分都封装好了,树莓派Pico又提供了非常快的迭代环境,两者配合起来,从零到跑通不到半天时间。但在现场部署时,真正决定成败的却是那些看起来不起眼的细节:电源去耦、天线摆放、串口时序、参数一致性。
如果让我重新再做一次,我会在原型阶段就把AUX引脚的时序用逻辑分析仪抓一遍,确认每一包数据发送的间隔和模组处理时间,避免后续调试的时候对时序问题毫无头绪。我也建议你在做长距离通信测试时,不要站在同一个房间里按发送键,而是选择一条可以拉长距离的线路,真实验证无线链路的稳定性。LoRa通信被干扰和衰落的问题,只有到真实的电磁环境里才会暴露出来,这是仿真和近距离测试永远替代不了的。