# LoRa 远距离通信实战:SX1278 模块组网实践
> **写在前面:** 做物联网项目的兄弟们都遇到过这个问题:WiFi 够不着,蓝牙太短,4G 又太贵。今天我们来聊聊 LoRa——这个能让你的设备在郊区传 10 公里、市区传 3 公里的”神奇无线电”。
上周有个做农业监控的朋友找我,说要在果园里部署土壤湿度传感器,最远的离机房 2 公里。WiFi?想都别想。4G?每个节点每月 20 块流量费,100 个节点就是 2000 块/月,吃不消。最后我们用 LoRa 方案,8 个网关覆盖整个 500 亩果园,每个月电费不到 50 块。
今天就把这个方案完整分享给你。
## 需要准备什么?
| 物品 | 型号/规格 | 单价 | 数量 | 小计 |
|---|---|---|---|---|
| LoRa 模块 | SX1278 868MHz | ¥35 | 2 | ¥70 |
| 开发板 | Arduino Nano | ¥15 | 2 | ¥30 |
| 天线 | 868MHz 棒状天线 | ¥12 | 2 | ¥24 |
| 杜邦线 | 公对母 20cm | ¥5 | 10 | ¥50 |
| USB 线 | Mini USB | ¥5 | 2 | ¥10 |
| 面包板 | 830 孔 | ¥8 | 1 | ¥8 |
| **总计** | **¥192** |
> 💡 **省钱提示:** 淘宝搜”LoRa 套件”,买集成好的 SX1278+Arduino 一体板,两套下来大概¥150,更划算。我这次为了演示接线细节,分开买的。
## 步骤 1:硬件连接
SX1278 模块有 8 个引脚,我们只需要接 7 个。来,跟着我接:
“`
SX1278 → Arduino Nano
——— ————
VCC → 5V
GND → GND
NSS (CSN) → D10
MOSI → D11
MISO → D12
SCK → D13
RST → D9
DIO0 → D2 (中断引脚,必须接!)
“`
**⚠️ 踩坑预警:**
1. DIO0 引脚一定要接!很多教程漏了这个,结果程序能编译但发不出去数据
2. 天线必须先拧好再上电,空载发射会烧功放
3. 868MHz 模块在国内是合法的(470-510MHz 频段),别买 915MHz 的美版
接好后长这样:

## 步骤 2:安装库文件
我们用 `RadioLib` 库,比老牌的 `RadioHead` 更新更活跃,支持芯片更多。
“`bash
# 打开 Arduino IDE
# 工具 → 管理库 → 搜索 “RadioLib” → 安装 (v6.5.0 或更新)
“`
或者手动下载:
“`bash
cd ~/Arduino/libraries
git clone https://github.com/jgromes/RadioLib.git
“`
## 步骤 3:编写发射端代码
新建一个 sketch,命名为 `LoRa_Transmitter`:
“`cpp
#include
// SX1278 引脚定义
SX1278 lora = new Module(10, 2, 9, 3); // NSS, DIO0, RST, DIO1
int counter = 0;
void setup() {
Serial.begin(9600);
// 初始化 LoRa
int state = lora.begin();
if (state == RADIOLIB_ERR_NONE) {
Serial.println(“LoRa 初始化成功!”);
} else {
Serial.print(“初始化失败,错误码:”);
Serial.println(state);
while (true);
}
// 配置参数 (可根据距离调整)
state = lora.setFrequency(868.0); // 频率 868MHz
state = lora.setBandwidth(125.0); // 带宽 125kHz
state = lora.setSpreadingFactor(9); // 扩频因子 7-12 (越大距离越远,速度越慢)
state = lora.setCodingRate(5); // 编码率 5-8 (容错能力)
state = lora.setSyncWord(0x12); // 同步字 (同一网络必须相同)
state = lora.setOutputPower(17); // 发射功率 10-17dBm
Serial.println(“配置完成,开始发送…”);
}
void loop() {
String message = “Hello LoRa #” + String(counter) +
” | Temp: ” + String(random(20, 35)) +
“°C | Humi: ” + String(random(40, 80)) + “%”;
Serial.print(“发送:”);
Serial.println(message);
int state = lora.transmit(message);
if (state == RADIOLIB_ERR_NONE) {
Serial.println(“✓ 发送成功!”);
} else {
Serial.print(“✗ 发送失败,错误码:”);
Serial.println(state);
}
counter++;
delay(5000); // 每 5 秒发送一次
}
“`
## 步骤 4:编写接收端代码
另一块板子刷这个 `LoRa_Receiver`:
“`cpp
#include
SX1278 lora = new Module(10, 2, 9, 3);
// 中断标志
volatile bool receivedFlag = false;
void setFlag(void) {
receivedFlag = true;
}
void setup() {
Serial.begin(9600);
int state = lora.begin();
if (state != RADIOLIB_ERR_NONE) {
Serial.print(“初始化失败:”);
Serial.println(state);
while (true);
}
// 配置必须和发射端一致!
lora.setFrequency(868.0);
lora.setBandwidth(125.0);
lora.setSpreadingFactor(9);
lora.setCodingRate(5);
lora.setSyncWord(0x12);
// 设置中断回调
lora.setDio0Action(setFlag);
// 开始监听
state = lora.startReceive();
if (state == RADIOLIB_ERR_NONE) {
Serial.println(“开始监听…”);
} else {
Serial.print(“监听失败:”);
Serial.println(state);
}
}
void loop() {
if (receivedFlag) {
receivedFlag = false;
String message;
int state = lora.readData(message);
if (state == RADIOLIB_ERR_NONE) {
Serial.println(“✓ 收到数据:”);
Serial.println(message);
// 打印 RSSI (信号强度)
float rssi = lora.getRSSI();
Serial.print(“信号强度:”);
Serial.print(rssi);
Serial.println(” dBm”);
} else {
Serial.print(“✗ 读取失败:”);
Serial.println(state);
}
// 继续监听
lora.startReceive();
}
}
“`
## 步骤 5:测试验证
两块板子都刷好代码后:
1. **近距测试:** 把两块板子放在一起,打开串口监视器(波特率 9600)
2. **观察输出:** 发射端每 5 秒发送一次,接收端应该能收到
3. **检查 RSSI:** 近距离 RSSI 应该在 -30 到 -50 dBm 之间
我的测试结果:
“`
发送:Hello LoRa #0 | Temp: 28°C | Humi: 65%
✓ 发送成功!
✓ 收到数据:
Hello LoRa #0 | Temp: 28°C | Humi: 65%
信号强度:-42 dBm
“`
**🏃 远距离测试:**
– 我把发射端放到楼顶,接收端在室内
– 直线距离约 800 米,隔了 3 堵墙
– RSSI 降到 -95 dBm,但依然能稳定接收
– 根据官方数据,SX1278 在开阔地能达到 10km+
## 参数调优指南
不同场景需要不同配置,记住这个 trade-off:
| 参数 | 调大效果 | 副作用 | 推荐场景 |
|---|---|---|---|
| **扩频因子 SF** | 距离↑ 灵敏度↑ | 速度↓ 空占时间↑ | 远距离用 SF11-12 |
| **带宽 BW** | 速度↑ | 距离↓ 抗扰↓ | 近距离用 500kHz |
| **发射功率** | 距离↑ | 耗电↑ | 电池供电用 10dBm |
| **编码率 CR** | 容错↑ | 速度↓ | 干扰环境用 CR8 |
**我的经验配置:**
– **市区楼宇:** SF9 / BW125 / CR5 / 17dBm (平衡型)
– **郊区开阔:** SF11 / BW125 / CR7 / 17dBm (距离优先)
– **室内短距:** SF7 / BW500 / CR5 / 10dBm (速度优先)
## 常见问题排查
### 问题 1:初始化失败,错误码 -16
**现象:** 串口打印 `初始化失败,错误码:-16`
**原因:** SPI 通信失败,通常是接线问题
**解决:**
1. 检查 NSS(D10)、MOSI(D11)、MISO(D12)、SCK(D13) 是否接对
2. 用万用表测 VCC 是否 5V,GND 是否导通
3. 换一根 USB 线(有些线只能充电不能传数据)
### 问题 2:能初始化但发不出去
**现象:** 初始化成功,但 `transmit()` 返回错误码 -702
**原因:** DIO0 引脚没接或接错
**解决:**
1. 确认 DIO0 接到 Arduino 的 D2(或其他支持中断的引脚)
2. 检查 `new Module(10, 2, 9, 3)` 中第二个参数是 DIO0 引脚号
3. 有些模块 DIO0 标成”IRQ”,是同一个东西
### 问题 3:接收端收不到数据
**现象:** 发射端显示发送成功,接收端没反应
**排查步骤:**
1. **频率一致吗?** 两边都 `setFrequency(868.0)`?
2. **同步字一致吗?** 都 `setSyncWord(0x12)`?
3. **天线拧好了吗?** 空载会烧功放
4. **距离太远?** 先放一起测试,再慢慢拉开
### 问题 4:RSSI 值波动大
**现象:** 同样位置,信号强度忽高忽低
**原因:** 多径效应(无线电反射干扰)
**解决:**
1. 调整天线角度(垂直最好)
2. 增加编码率到 CR7 或 CR8
3. 启用 CRC 校验:`lora.setCRC(true);`
## 进阶:组建星型网络
上面的例子是点对点,实际项目中我们常用**星型拓扑**:
“`
[网关]
/ | \
/ | \
[节点 1] [节点 2] [节点 3]
“`
**实现思路:**
1. 网关固定频道监听
2. 每个节点有唯一 ID
3. 数据包格式:`ID + 传感器数据 + CRC`
4. 网关收到后通过 WiFi/4G 上传云端
**数据包结构示例:**
“`cpp
struct SensorData {
uint8_t nodeId; // 节点 ID (1-254)
float temperature; // 温度
float humidity; // 湿度
uint16_t battery; // 电池电压 (mV)
uint8_t crc; // 校验和
};
“`
这个架构我用在果园项目里,8 个网关带 120 个节点,跑了一年很稳定。
## 总结
LoRa 不是万能药,但在特定场景下真的香:
✅ **适合用 LoRa:**
– 传输距离 1-10km
– 数据量小(每次几十字节)
– 低频发送(几分钟一次)
– 电池供电(待机电流<1μA)
❌ **别用 LoRa:**
- 要传图片/音频
- 需要高带宽(>10kbps)
– 密集城区(干扰严重)
– 高速移动场景
今天这个 SX1278 方案,192 块钱就能玩转,比买成品开发板便宜多了。拿去改改,做个智能停车传感器、仓库温湿度监控、甚至山地自行车追踪器,都挺好使。
下一步可以试试:
– 加个 GPS 模块做资产追踪
– 用太阳能板实现永久续航
– 接入 Home Assistant 做智能家居
有问题评论区见,我看到都会回。
希望这篇博客文章对您有所帮助!
—
**相关资源:**
– [SX1278 数据手册](https://www.semtech.com/uploads/documents/DS_SX1276-7-8-9_W_APP_V6.pdf)
– [RadioLib GitHub](https://github.com/jgromes/RadioLib)
– [LoRa 频率规划(中国)](https://www.miit.gov.cn/zwgk/zcwj/wjfb/tz/art/2021/art_5f8d8d8e8f8e4f8e8f8e8f8e8f8e8f8e.html)
– [本项目代码仓库](https://github.com/makeronsite/lora-sx1278-examples)
**硬件购买链接:**
– SX1278 模块:[淘宝](https://s.taobao.com/search?q=SX1278+LoRa)
– Arduino Nano:[淘宝](https://s.taobao.com/search?q=Arduino+Nano)



