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

NRF24模块仅接收首个负载:原因排查与修复咨询

问题描述

使用pyNRF库为NRF24无线模块编写脚本,接线方式与官方示例一致,运行官方simple_receiver和simple_sender脚本时通信正常,但自定义脚本仅能接收首个消息,之后接收器陷入停滞:nrf.data_ready()始终返回True,接收的负载不再更新,且首字节数据错误。

发送端核心代码:

while True:
    if not self.sending_data.empty():
        for _ in range(self.sending_data.qsize()-1):
            send=self.sending_data.get_nowait()
    
        if not send:
            continue
        if send[0][9] and send[0][10]:
            pass
        else:     
            payload = struct.pack("<B"+"?"*13+"f"*6+"h"*2,
                                    0x01,
                                    *send[0].values(),
                                    *send[1].values(),
                                    send[2][0][0],
                                    send[2][0][1])
            nrf.reset_packages_lost()
            nrf.send(payload)
        print("<B"+"?"*13+"f"*6+"h"*2)
        print(not send)
        print(len(send[0].values()))
        print(len(send[1].values()))
    print(payload)        
    # Send the payload to the address specified above.
    
    try:
        if payload:
            nrf.wait_until_sent()
            print("sented")
    except TimeoutError:
        print("Timed out")
        time.sleep(0.2)
        continue
    
    if nrf.get_packages_lost() == 0:
        print(f"Success: lost={nrf.get_packages_lost()}, retries={nrf.get_retries()}")
    else:
        print(f"Error: lost={nrf.get_packages_lost()}, retries={nrf.get_retries()}")
    
    time.sleep(1)

接收端核心代码:

while True:
    while nrf.data_ready():
        # Count message and record time of reception.            
        count += 1
        now = datetime.now()
         
        # Read pipe and payload for message. 
        pipe = nrf.data_pipe()              
        payload = nrf.get_payload()                                             
        print(payload)
        # If the length of the message is 9 bytes and the first byte is 0x01, then we try to interpret the bytes
        # sent as an example message holding a temperature and humidity sent from the "simple-sender.py" program.
        protocol = payload[0] if len(payload) > 0 else -1            
        hex = ':'.join(f'{i:02x}' for i in payload)
        # Show message received as hex.
        print(f"{now:%Y-%m-%d %H:%M:%S.%f}: pipe: {pipe}, len: {len(payload)}, bytes: {hex}, count: {count}, protocol: {protocol}")
        nrf.show_registers()
        
        if payload[0] == 0x01:
            
            for i in payload:
                print(i)
            print("Payload rx: " + str(struct.unpack("<B"+"?"*13+"f"*6+"h"*2, payload)))
            values = struct.unpack("<B"+"?"*13+"f"*6+"h"*2, payload)
            self.queue.put_nowait(values)
    time.sleep(0.1)

配置修改说明:仅将数据速率设为2MBps,负载结构从示例的

payload = struct.pack("<Bff", 0x01, temperature, humidity)

修改为自定义结构:

payload = struct.pack("<B"+"?"*13+"f"*6+"h"*2,
                                        0x01,
                                        *send[0].values(),
                                        *send[1].values(),
                                        send[2][0][0],
                                        send[2][0][1])
核心原因
  1. 负载长度不匹配:NRF24模块默认要求固定长度的负载,自定义负载长度(计算得42字节)远大于示例的9字节,但收发两端未配置对应的数据宽度,导致模块无法正确解析后续数据包,陷入错误状态。
  2. 接收状态未重置:首次接收后,模块的接收中断标志或缓冲区未被正确清空,导致nrf.data_ready()始终返回True,但实际无新数据。
  3. 发送端逻辑漏洞:队列处理逻辑可能丢弃数据不彻底,或导致payload变量未初始化(队列为空时),引发异常或重复发送旧数据。
修复步骤

1. 统一收发两端的负载宽度配置

先计算自定义负载的实际长度:

import struct
print(struct.calcsize("<B"+"?"*13+"f"*6+"h"*2))  # 输出应为42

在收发两端的初始化代码中添加:

nrf.set_payload_size(42)  # 设置为自定义负载的实际长度

2. 修复接收端状态重置逻辑

在接收端的while nrf.data_ready()循环末尾,添加缓冲区清空或状态标志清除代码:

nrf.flush_rx()  # 清空接收缓冲区,重置模块接收状态
# 或使用 nrf.clear_status_flags() 清除中断标志

3. 修复发送端队列处理逻辑

修正队列数据获取逻辑,避免未初始化变量和数据丢弃不彻底:

if not self.sending_data.empty():
    # 只保留队列最新的一条数据,丢弃旧数据(需保留所有数据则删除此循环)
    while self.sending_data.qsize() > 1:
        self.sending_data.get_nowait()
    send = self.sending_data.get_nowait()
    if not send:
        continue
    # 后续payload打包逻辑...
else:
    payload = None  # 避免队列为空时引用未定义的payload变量

4. 验证负载长度一致性

每次打包后打印负载长度,确保发送的负载长度固定为42字节:

payload = struct.pack(...)
print(f"Payload length: {len(payload)}")  # 需稳定输出42

若长度不一致,检查send[0].values()、send[1].values()的元素数量是否符合13个布尔值+6个浮点数的要求,以及send[2]的两个短整数是否正确。

5. 调整数据速率(可选)

2MBps速率对信号质量要求较高,若环境存在干扰,可尝试降为1MBps测试:

nrf.set_data_rate(nrf.DATA_RATE_1MBPS)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 01:21:24