|
LoRa 远距离通信实战:SX1278 模块组网实践

LoRa 远距离通信实战:SX1278 模块组网实践

写在前面: 做物联网项目的兄弟们都遇到过这个问题:WiFi 够不着,蓝牙太短,4G 又太贵。今天我们来聊聊 LoRa——这个能让你的设备在郊区传 10 公里、市区传 3 公里的”神奇无线电”。

上周有个做农业监控的朋友找我,说要在果园里部署土壤湿度传感器,最远的离机房 2 公里。WiFi?想都别想。4G?每个节点每月 20 块流量费,100 个节点就是 2000 块/月,吃不消。最后我们用 LoRa 方案,8 个网关覆盖整个 500 亩果园,每个月电费不到 50 块。

今天就把这个方案完整分享给你。

需要准备什么?

物品规格参考价格数量小计
LoRa 模块 SX1278868MHz¥352¥70
Arduino NanoATmega328P¥152¥30
868MHz 弹簧天线SMA 接口¥122¥24
面包板 + 杜邦线20cm¥510¥50
USB 数据线Mini USB¥52¥10
USB-TTL 下载线CH340¥81¥8
合计¥192

💡 省钱提示: 淘宝搜”LoRa 套件”,买集成好的 SX1278+Arduino 一体板,两套下来大概 ¥150,更划算。我这次为了演示接线细节,分开买的。

步骤 1:硬件连接

SX1278 模块有 8 个引脚,我们只需要接 7 个。来,跟着我接:

SX1278      →   Arduino Nano
---------       ------------
VCC         →   3.3V   ⚠️ 不要接 5V,会烧模块!
GND         →   GND
NSS (CSN)   →   D10
MOSI        →   D11
MISO        →   D12
SCK         →   D13
RST         →   D9
DIO0        →   D2  (中断引脚,必须接!)

⚠️ 踩坑预警:

  1. SX1278 是 3.3V 模块,绝对不能接 5V,否则直接烧掉。Arduino Nano 的 3.3V 引脚输出电流有限(约 50mA),但 LoRa 发射瞬间需要约 120mA,长距离发射时建议从外部 3.3V 稳压供电。
  2. NSS 片选引脚可以根据需要调整,不一定要用 D10,但代码里要和 Module(10, 2, 9, 3) 第一个参数对应。
  3. DIO0 必须接中断引脚(Arduino Nano 的 D2 或 D3),否则接收端的 setDio0Action() 回调不会触发,你会永远收不到数据。

建议接线后用万用表通断档逐根复核一遍,LoRa 对 SPI 信号质量比较敏感,虚焊或接触不良会导致初始化失败。

步骤 2:安装库文件

我们用 RadioLib 库,比老牌的 RadioHead 更新更活跃,支持芯片更多。

# 打开 Arduino IDE
# 工具 → 管理库 → 搜索 "RadioLib" → 安装 (v6.5.0 或更新)

或者手动下载:

cd ~/Arduino/libraries
git clone https://github.com/jgromes/RadioLib.git

步骤 3:编写发射端代码

新建一个 sketch,命名为 LoRa_Transmitter

#include <RadioLib.h>

// 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

#include <RadioLib.h>

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 波特率),观察是否每隔 5 秒打印一条 “发送成功”。
  2. 再给接收端上电,观察串口是否显示收到的数据以及对应的 RSSI 信号强度。
  3. 如果两端都正常,尝试逐步拉开距离,测试实际通信范围。

我的测试结果:

发送: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:

场景SFBWCR功率特点
市区楼宇SF9125kHz4/517dBm平衡型,兼顾距离和速率
郊区开阔SF11125kHz4/717dBm距离优先,最远可达 5km+
室内短距SF7500kHz4/510dBm速度优先,延迟低
电池供电SF10125kHz4/814dBm低功耗,牺牲速率换可靠性

我的经验配置:

  • 市区楼宇: SF9 / BW125 / CR5 / 17dBm (平衡型)

  • 郊区开阔: SF11 / BW125 / CR7 / 17dBm (距离优先)

  • 室内短距: SF7 / BW500 / CR5 / 10dBm (速度优先)

常见问题排查

问题 1:初始化失败,错误码 -16

现象: 串口打印 初始化失败,错误码:-16

原因: SPI 通信失败,通常是接线问题

解决:

  1. 检查 VCC 是否接 3.3V(不是 5V),用万用表量一下电压。
  2. 用万用表蜂鸣档测 SPI 四根线(MOSI/MISO/SCK/NSS)是否连通,排除虚焊。
  3. 确认杜邦线没有松动,面包板触点接触良好;换一个接口孔位试试。

问题 2:能初始化但发不出去

现象: 初始化成功,但 transmit() 返回错误码 -702

原因: DIO0 引脚没接或接错

解决:

  1. 检查 DIO0 到 D2 的杜邦线是否接好,重新插拔一下。
  2. 确认代码里 new Module(10, 2, 9, 3) 第二个参数(DIO0)和实际接线一致。
  3. 尝试重新上电重启模块,某些情况下 RST 引脚的电容会导致初始化不完整。

问题 3:接收端收不到数据

现象: 发射端显示发送成功,接收端没反应

排查步骤:

  1. 检查两端参数是否完全一致:频率、SF、BW、CR、SyncWord,任何一个不匹配都收不到。
  2. 确认两端代码的 SyncWord 相同(默认 0x12,不同网络必须用不同值隔离)。
  3. 尝试把两端拉近到 1 米内测试,排除距离过远或天线问题。
  4. 检查天线是否接好;天线断路或虚焊会导致信号极弱,把天线拆了重新接。

问题 4:RSSI 值波动大

现象: 同样位置,信号强度忽高忽低

原因: 多径效应(无线电反射干扰)

解决:

  1. 使用外置弹簧天线或胶棒天线代替 PCB 天线,辐射方向图更稳定。
  2. 避免天线靠近金属物体或人体(人体含水量高,对 868MHz 信号衰减明显)。
  3. 多次采样取平均值,建议取 5-10 次 RSSI 读数的中位数作为最终值。

进阶:组建星型网络

上面的例子是点对点,实际项目中我们常用星型拓扑

[网关]
/  |  \
/   |   \
[节点 1] [节点 2] [节点 3]

实现思路:

  1. 网关端:编写接收程序,循环监听并解析不同 nodeId 的数据,按 ID 分组存储。
  2. 节点端:每个节点在代码里分配唯一 nodeId(1-254),定时采集传感器数据并上报。
  3. 数据包结构:在 payload 开头加上 nodeId 字节标识,网关据此区分数据来源(比如 "1,28.5,65" 代表节点 1,温度 28.5℃,湿度 65%)。
  4. 可选 ACK 机制:节点发送后等待网关 200ms 内回复一个 ACK 字节,超时则重发(最多 3 次),提高可靠性。

数据包结构示例:

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 模块:淘宝搜索”Ra-02 868MHz”
  • Arduino Nano:淘宝搜索”Arduino Nano CH340”