You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Arduino UNO+SX1278 LoRa双向通信异常,求排查方案

LoRa双向通信乱码与接收失效问题修复

问题根源分析

  • 重复读取与长度不匹配:接收函数中先调用LoRa.readString()读取全部数据,后续又通过while循环再次读取,且未按照发送时约定的payload长度读取内容,导致数据解析混乱,出现乱码。
  • 模块地址配置冲突:两个模块使用相同的localAddress且目标地址设为广播地址0xFF,双向通信时无法精准指向对方,可能导致一方接收逻辑异常。
  • 接收函数阻塞:onReceive中的delay(1000)会阻塞主循环,打断发送逻辑的定时执行,造成另一模块接收不到数据。
  • 变量类型不统一:接收时用int类型读取字节型的目标地址,可能引发符号扩展问题,影响地址校验逻辑(原代码未做地址校验,也是潜在问题)。

修复后的代码

#include <SPI.h>
#include <LoRa.h>

byte msgCount = 0;            // 发送消息计数
byte localAddress;            // 当前设备地址
byte destinationAddress;      // 目标设备地址
long lastSendTime = 0;        // 上次发送时间
int interval = 300;           // 发送间隔

// 注意:两个模块需分别配置不同地址,比如模块1设为0xAA、目标0xBB;模块2设为0xBB、目标0xAA
void setup() {
  Serial.begin(115200);
  while (!Serial);
  
  // 模块1配置:localAddress = 0xAA; destinationAddress = 0xBB;
  // 模块2配置:localAddress = 0xBB; destinationAddress = 0xAA;
  localAddress = 0xAA;
  destinationAddress = 0xBB;

  Serial.println("LoRa 双向通信测试");
  if (!LoRa.begin(433E6)) {
    Serial.println("LoRa初始化失败!");
    while (1);
  }
}

void loop() {
  // 定时发送消息
  if (millis() - lastSendTime > interval) {
    String message = "data from sensors " + String(msgCount);
    Serial.print("发送消息: ");
    Serial.println(message);
    sendMessage(message);
    lastSendTime = millis();
    interval = random(50) + 300; // 随机间隔300-350ms
  }

  // 处理接收数据包
  int packetSize = LoRa.parsePacket();
  if (packetSize > 0) {
    onReceive(packetSize);
  }
}

void sendMessage(String message) {
  LoRa.beginPacket();
  LoRa.write(destinationAddress); // 目标地址
  LoRa.write(localAddress);       // 源地址
  LoRa.write(msgCount);           // 消息ID
  LoRa.write(message.length());   // 负载长度
  LoRa.print(message);            // 负载内容
  LoRa.endPacket();
  msgCount++;
}

void onReceive(int packetSize) {
  // 读取头部信息
  byte recipient = LoRa.read();    // 目标地址(统一byte类型)
  byte sender = LoRa.read();       // 源地址
  byte incomingMsgId = LoRa.read();// 消息ID
  byte payloadLength = LoRa.read();// 负载长度

  // 校验目标地址是否匹配当前设备
  if (recipient != localAddress && recipient != 0xFF) {
    Serial.println("不是发给当前设备的数据包,丢弃");
    // 清空剩余数据
    while (LoRa.available()) LoRa.read();
    return;
  }

  // 读取指定长度的负载内容
  String payload = "";
  for (int i = 0; i < payloadLength && LoRa.available(); i++) {
    payload += (char)LoRa.read();
  }

  // 输出接收信息
  Serial.print("收到来自0x");
  Serial.print(sender, HEX);
  Serial.print("的消息: ");
  Serial.println(payload);
  Serial.print("RSSI: ");
  Serial.println(LoRa.packetRssi());

  // 移除阻塞性delay,避免打断主循环
  // delay(1000);
}

关键修复点说明

  1. 地址配置区分:两个模块需设置不同的localAddress,并将destinationAddress设为对方的地址,确保双向通信的精准性,避免广播带来的混乱。
  2. 规范数据读取:按照发送时约定的payloadLength读取对应字节的内容,避免重复读取和长度不匹配导致的乱码。
  3. 添加地址校验:接收时先判断数据包是否发给当前设备,避免处理无关数据包。
  4. 移除阻塞延迟:删除onReceive中的delay(1000),保证主循环的定时发送逻辑正常执行,解决另一模块接收失效的问题。
  5. 统一变量类型:将接收的地址变量改为byte类型,匹配发送时的字节写入操作,避免类型转换问题。

内容的提问来源于stack exchange,提问作者Nataniel Slowikowski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 01:45:34