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); }
关键修复点说明
- 地址配置区分:两个模块需设置不同的
localAddress,并将destinationAddress设为对方的地址,确保双向通信的精准性,避免广播带来的混乱。 - 规范数据读取:按照发送时约定的
payloadLength读取对应字节的内容,避免重复读取和长度不匹配导致的乱码。 - 添加地址校验:接收时先判断数据包是否发给当前设备,避免处理无关数据包。
- 移除阻塞延迟:删除
onReceive中的delay(1000),保证主循环的定时发送逻辑正常执行,解决另一模块接收失效的问题。 - 统一变量类型:将接收的地址变量改为
byte类型,匹配发送时的字节写入操作,避免类型转换问题。
内容的提问来源于stack exchange,提问作者Nataniel Slowikowski
相关产品推荐
相关产品推荐

