LoRa 网关组网方案
需求: 网关每6秒接收不同节点的数据,使用SX1262芯片。
以下是完整的组网方案:
1. 网络架构设计
采用星型拓扑:
- 网关:作为中心节点,持续监听多个信道
- 节点:分布在网关周围,定时发送数据(每6秒)
- 区分网络:通过网络ID和信道分配隔离不同网络
- 区分节点:通过设备地址识别
2. 关键区分机制
2.1 网络隔离方案
方法 |
实现方式 |
优点 |
网络ID (NetID) |
数据包头加入2字节网络ID(0xAABB, 0xCCDD等) |
软件实现简单,灵活 |
信道分配 |
不同网络使用不同频率(如433.0MHz/433.2MHz/433.4MHz) |
物理隔离,抗干扰能力强 |
扩频因子(SF) |
不同网络使用不同SF(SF7/SF9/SF12) |
提高信道容量 |
同步字(SyncWord) |
设置自定义同步字(默认0x1424为私有) |
硬件级过滤 |
推荐组合:网络ID + 信道分配
2.2 节点识别方案
// 数据包结构
typedef struct {
uint16_t net_id; // 网络ID (0xAABB)
uint32_t dev_addr; // 设备地址 (0x11223344)
uint8_t payload[50]; // 实际数据
uint16_t crc; // CRC校验
} lora_packet_t;
3. 网关实现方案
3.1 网关工作流程
sequenceDiagram
participant Gateway
participant Node1
participant Node2
Note over Gateway: 初始化(多信道监听)
loop 每6秒
Node1->>Gateway: 数据(NetID=0xAABB, DevAddr=0x01)
Gateway-->>Gateway: 校验网络ID
Gateway-->>Gateway: 记录DevAddr=0x01
Node2->>Gateway: 数据(NetID=0xAABB, DevAddr=0x02)
Gateway-->>Gateway: 校验网络ID
Gateway-->>Gateway: 记录DevAddr=0x02
end
3.2 关键代码实现
网关初始化 (lora_gateway_init.c
):
#define MAX_NETWORKS 3
const uint32_t NETWORK_FREQS[MAX_NETWORKS] = {433000000, 433200000, 433400000};
const uint16_t NETWORK_IDS[MAX_NETWORKS] = {0xAABB, 0xCCDD, 0xEEFF};
void Gateway_Init() {
for(int i=0; i<MAX_NETWORKS; i++) {
Radio.SetChannel(NETWORK_FREQS[i]);
Radio.SetRxConfig(MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
LORA_SYMBOL_TIMEOUT, false, 0, true, 0, 0, false, true);
Radio.Rx(0); // 连续接收模式
}
}
数据接收处理 (gateway_rx_handler.c
):
void OnRxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) {
lora_packet_t *pkt = (lora_packet_t*)payload;
// 校验网络ID
int valid_net = 0;
for(int i=0; i<MAX_NETWORKS; i++) {
if(pkt->net_id == NETWORK_IDS[i]) {
valid_net = 1;
break;
}
}
if(!valid_net) return; // 丢弃其他网络数据
// 记录设备信息
printf("来自节点 %08X 的数据: RSSI=%d, SNR=%d\n",
pkt->dev_addr, rssi, snr);
// 处理有效载荷
process_payload(pkt->payload);
}
4. 节点实现方案
4.1 节点工作流程
void Node_Runtime(uint32_t dev_addr) {
while(1) {
// 1. 随机延迟(0-500ms)避免碰撞
delay_ms(rand() % 500);
// 2. 准备数据包
lora_packet_t pkt = {
.net_id = 0xAABB, // 所属网络ID
.dev_addr = dev_addr,
.payload = {...} // 传感器数据
};
pkt.crc = RadioComputeCRC((uint8_t*)&pkt, sizeof(pkt)-2, CRC_TYPE_IBM);
// 3. 发送数据
Radio.Send((uint8_t*)&pkt, sizeof(pkt));
// 4. 等待6秒
delay_ms(6000);
}
}
4.2 防碰撞机制
- 随机延迟:每个节点在6秒周期内随机选择发送时间
- CSMA/CA(可选):
bool channel_free = RadioIsChannelFree(MODEM_LORA, 433000000, -90, 100);
if(channel_free) Radio.Send(...);
5. 参数配置建议
参数 |
推荐值 |
说明 |
频率 |
433MHz/868MHz |
根据地区法规选择 |
扩频因子 |
SF9 |
兼顾距离和容量 |
带宽 |
125kHz |
标准配置 |
编码率 |
4/8 |
提高抗干扰性 |
发射功率 |
20dBm |
最大功率(需符合当地法规) |
同步字 |
0xAABB |
自定义私有网络 |
网络ID长度 |
2字节 |
平衡效率和网络容量 |
6. 抗干扰策略
- 频率跳变(FHSS):
void Node_SendWithFHSS() {
int channel = rand() % 8;
RadioSetChannel(433000000 + channel*200000);
Radio.Send(...);
}
- 动态扩频因子:
// 根据信号质量动态调整SF
if(snr > -7.5) {
Radio.SetSpreadingFactor(SF7); // 高速模式
} else {
Radio.SetSpreadingFactor(SF12); // 长距离模式
}
- 重传机制:
for(int retry=0; retry<3; retry++) {
if(Radio.Send(...) == SUCCESS) break;
delay_ms(100 * (retry+1));
}
部署建议
- 网络规划:
- 每个网络使用独立频率+网络ID组合
- 网关支持同时监听3-8个信道(需硬件支持)
- 节点部署:
graph TD
A[网关] --> B[区域1: 433.0MHz/0xAABB]
A --> C[区域2: 433.2MHz/0xCCDD]
A --> D[区域3: 433.4MHz/0xEEFF]
B --> E[节点1-10]
C --> F[节点11-20]
D --> G[节点21-30]
- 安全增强:
- AES-128加密载荷数据
- 动态设备地址分配
- 数据包签名验证
关键提示:实际部署前需进行频谱扫描,选择干扰最小的频段,并根据距离要求调整SF和带宽参数。