CC2340R5: 广播包发送的问题,并不能按我设定的时间间隔去发送

Part Number: CC2340R5
Other Parts Discussed in Thread: SYSCONFIG

我想使用CC2340R5来定时发送5条广播包,但在调试过程中,发现并不能按照设定的间隔来发送,而且有时候会发送不出来,使用rfPacketTx的例程,BLE的例程,还是使用SmartRF发送都是一样的结果,

rfPacketTx例程中,调用RCL_Command_submit后返回active,调用 RCL_Command_pend functions返回finished,这两个函数的返回结果是正常的,但数据并没有发送出来。

以下是SmartRF的设置

这是SmartRF发送出来的数据包

以下为使用rfPackerTx的例程更改后发送的数据包,红框为能够发出来的那一次,而且并不是每次都能够发送完整,我需要怎么去排查这个问题

  • 您好,

    已经收到了您的案例,调查需要些时间,感谢您的耐心等待。

  • 您好

    你能回复你的SDK版本吗?

    您提到您正在使用rfPacketTx发送数据包。
    -你是在不做任何修改的情况下使用这个例子吗?
    -如果没有,你做了哪些修改?
    -您能发送修改后的rfPacketTx的代码吗?

  • SDK版本:simplelink_lowpower_f3_sdk_9_11_00_18

    修改了syscfg中的发送频率,为37通道

    以下为代码和问题现象

    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <limits.h>
    
    /* TI Drivers */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/rcl/RCL.h>
    #include <ti/drivers/rcl/RCL_Scheduler.h>
    #include <ti/drivers/rcl/commands/generic.h>
    
    /* SysConfig Generated */
    #include "ti_drivers_config.h"
    #include "ti_radio_config.h"
    #include "string.h"
    
    /***** Defines *****/
    /* Packet TX Configuration */
    #define MAX_LENGTH              (30U) // Max packet length
    #define NUM_DATA_ENTRIES        (0U)  // Number of data entries
    #define NUM_PAD_BYTES           (3U)  // Number of pad bytes
    #define PACKET_INTERVAL     100000    // Set packet interval to 500000us or 500ms
    
    /* The index of the length in the TX packet and the length of the header */
    #define LEN_INDEX (RCL_REGISTER_FIELD_PBE_GENERIC_RAM_LENCFG_LENPOS/CHAR_BIT)
    #define HDR_LEN   (LEN_INDEX + (RCL_REGISTER_FIELD_PBE_GENERIC_RAM_LENCFG_NUMLENBITS/CHAR_BIT))
    
    /* Indicates if FS is off */
    #define FS_OFF                  (1U)  // 0: On, 1: Off
    
    #define FREQUENCY               (2402000000U)
    
    
    /***** Variable declarations *****/
    /* RCL Commands */
    extern RCL_CmdGenericTx rclPacketTxCmdGenericTx;
    
    /* RCL Client used to open RCL */
    static RCL_Client rclClient;
    
    /* TX packet buffer */
    uint32_t packet[NUM_DATA_ENTRIES][3 + ((MAX_LENGTH + 10)/ 4)];
    
    /* Counters for RCL event callback */
    volatile uint32_t gCmdDone = 0;     // Command done
    
    /***** Callback Functions *****/
    void defaultCallback(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEvents)
    {
        if (rclEvents.lastCmdDone)
        {
            gCmdDone += 1;
    
            GPIO_toggle(CONFIG_GPIO_GLED);
        }
    }
    
    uint8_t debug_buf[22] = {
        0x02,0x14,
        0x78,0x56,0x34,0x12,0xCD,0xAB,
        0x08,0x08,'T','C','D','E','B','U','G',
        0x04,0xFF,0x8F,0x03,00
    
    };
    
    /***** Function definitions *****/
    
    void *mainThread(void *arg0)
    {
        /* Initialize and open RCL */
        RCL_init();
    
        RCL_Handle rclHandle = RCL_open(&rclClient, &LRF_config);
    
        /* Set RF frequency */
        rclPacketTxCmdGenericTx.rfFrequency = FREQUENCY;
        
        
        /* Start command as soon as possible */
        rclPacketTxCmdGenericTx.common.scheduling = RCL_Schedule_Now;
        rclPacketTxCmdGenericTx.common.status = RCL_CommandStatus_Idle;
    
        rclPacketTxCmdGenericTx.config.fsOff = FS_OFF; // Turn off FS
    
        /* Callback triggers on last command done */
        rclPacketTxCmdGenericTx.common.runtime.callback = defaultCallback;
        rclPacketTxCmdGenericTx.common.runtime.rclCallbackMask.value = RCL_EventLastCmdDone.value;
    
        /* Set RCL TX buffer packet to be packet buffer */
        RCL_Buffer_TxBuffer *txPacket = (RCL_Buffer_TxBuffer *)&packet;
    
        GPIO_setConfig(CONFIG_GPIO_GLED, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
        GPIO_write(CONFIG_GPIO_GLED, CONFIG_GPIO_LED_OFF);
    
        while(1)
        {
            /* Create packet with random payload */
            uint8_t *txData;
            txData = RCL_TxBuffer_init(txPacket, 3, 0, 22);
    
            memcpy(txData, debug_buf, 22);
    
            /* Set packet to transmit */
            RCL_TxBuffer_put(&rclPacketTxCmdGenericTx.txBuffers, txPacket);
    
            rclPacketTxCmdGenericTx.common.status = RCL_CommandStatus_Idle;
    
            /* Submit command */
            RCL_Command_submit(rclHandle, &rclPacketTxCmdGenericTx);
    
            /* Pend on command completion */
            RCL_Command_pend(&rclPacketTxCmdGenericTx);
    
            usleep(PACKET_INTERVAL);
        }
    }

  • 您好

    您是否希望在项目中使用BLE?在这种情况下,为了证明您的产品适用于BLE,我建议您使用我们的BLE堆栈。您可以使用我们SDK示例中的basic_ble示例来使用此堆栈。从这里,您可以在sysconfig中将设备的BLE角色设置为Broadcaster,并以此方式广播您的BLE数据。

  • 这个方式我也试过了,也是一样的现象,按一秒时间发送,发送正常间隔的几条数据后有个较大间隔时间2~3s后才发下一条,并且在basic_ble这个例程中,我尝试关闭广播的时候会卡在某个循环,这种带有RTOS的SDKdebug会很困难,而且这个项目我们需要极低的低功耗,仅使用BLE的广播功能,希望软件是尽量的轻量化的,使用RTOS会有风险。目前rfPacketTx这个例程,不能稳定地按照我想要的时间间隔去发送,或者你们技术支持工程师按照我上面的代码验证一下是否也是一样的现象,顺便我想知道这个问题有没有可能与硬件相关,我使用的CC2340R5开发板,bom版本是B。

  • 您好

    默认情况下,basic_ble示例是一个以固定间隔发送一个广告包的外围设备。这是BLE广告的常规行为。BLE堆栈不支持每隔固定时间发送5个不同的广告包。此外,没有BLE函数可以直接自己发送数据包,所以我不确定你到底在做什么。

    我可以问一下,你每秒发送5个数据包的用例是什么吗?数据包中的所有5个数据包的数据是否相同?数据会在运行时发生变化吗?

  • 目前测试的时候数据是相同的,正式项目中,该数据会有变化,我想做的功能是每几分钟,例如三分钟,可以发送一包广播数据,这包广播数据中有五帧相同的数据,由于该项目对这个数据数量有严格要求,需要保证数据每次都能够发送出来。目前的测试情况是按照我设定的时间间隔,并不是每次都能够发送出来。我的接收端的扫描窗口跟扫描间隔是相同的,相当于全打开扫描,不会是接收端的原因,所以需要求助一下你们,谢谢

  • 您好

    你有多种选择可以做到这一点。对于您的用例,我认为最好的解决方案是使用定期的蓝牙LE广告来发送您的数据。您可以按照本SLA指南了解如何通过修改AdvData1对象发送自定义广告数据,然后按照用户指南的本章启用定期广告。默认情况下,BLE广告的限制为31字节,但使用扩展广告,您可以将此限制增加到1650字节,这应该绰绰有余。

    这种解决方案的主要问题是,BLE广告不能保证总是被接收到:数据包可能会因恶劣的环境而丢失。如果你想对数据接收有更多的保证,你可以使用BLE通知。为此,您需要首先建立连接,然后将连接间隔设置为1秒。当发送通知时,中心将向外围设备发送确认。如果外围设备没有收到此确认,则外围设备将再次发送通知。如果你想使用通知,你可以看到basic_ble示例如何通过特征4发送通知,并阅读用户指南的这一章。您将需要使用API的GATT_Notification函数。

  • 我这个项目不需要用到连接,只是需要定期发送数据,当然我会希望使用不带有RTOS的例程,我会尝试使用basic_ble的例程,但是我需要知道这个basic_ble例程是在哪里进入休眠以及唤醒,我要在芯片醒来和进入休眠的时候做某些动作

  • 我这个项目不需要连接,当然,我更希望使用非RTOS的版本,我会尝试使用basic_ble这个例程,但是我需要知道这个例程是从哪里进入休眠以及唤醒,我要在进入休眠和唤醒的时候做某些动作

  • 您好

    您是否需要保证您的数据被接收?如果是,则您的项目需要连接。如果没有,你可以使用定期广告。

    BLE堆栈没有一个单独的点可以唤醒并进入睡眠状态,我们的BLE堆栈中发生的事情是,您注册了在调用某些事件(广告启动、停止、接收连接、写入GATT等)时调用的事件处理程序。您可以将代码放在BLE的一个事件处理程序中。

    我真的很难看到你的用例是什么,这使得很难就特定的方法或协议向你提供建议。你需要什么代码才能进入睡眠和醒来?您的数据是否需要保证被接收?您正在发送的数据是什么?谁在接收数据,是手机还是其他MCU?他们支持什么协议?

  • 我这个项目的需求很简单,平时芯片处在休眠模式,每2s醒来检查一次传感器的数据,如果有变化就立刻通过RF去发送数据。如果没有变化会定时1分钟去发送RF数据,这期间也是每2s会醒来一次,按你所说的basic_ble这个例程只能是调用事件时再处理,但是这些事件并不包含唤醒和进入休眠,所以basic_ble这个例程并不适合我,只能使用rfPacketTX这个例程

  • 发出的RF数据是需要保证被收到的,正如我一开始所提出的问题,我需要保证每次数据都能够发送出来,但是使用rfPacketTx例程的时候数据并不是每次唤醒的时候都能够发送出来,包括使用SmartRF测试的时候也是。发送的RF数据是符合BLE广播仅可发现不可连接格式的数据,但严格来说并不是蓝牙规范的广播数据,BLE的堆栈并不适用于这个项目,因为这个发送间隔有时候是2s,有时候是1分钟。接收端只需要收到到这个广播数据就行,也不需要连接,仅仅打开扫描就可以,没有特定的设备,可以是任何带有2.4G频段的设备。

  • 您好

    由于连接的延迟参数,BLE堆栈仍然适用于该项目。启动连接时,连接参数可以将延迟值设置为正数或空值。此值将是外围设备或中央设备跳过的BLE数据包的最大数量。连接间隔为2秒,延迟值为30,外围设备可以每2秒或每分钟发送一次数据包,具体取决于传感器读取的内容。BLE还为您的用例提供了必要的数据包大小。

    我可以肯定地说:如果您没有设置自己的RF协议,rfPacketTx不能保证其他人正在接收数据,因为它需要一个响应。对于可以通过BLE轻松实现的事情来说,创建这个RF协议将是一项艰巨的任务。

  • 您可以理解成我这个就是一个私有RF协议,只是通过2.402GHz这个频段发送,而且不需要连接,也不需要回复,就跟广播数据一样,单方面发送,所以使用BLE堆栈就大材小用了,而且我的老大明确禁止我使用BLE堆栈,他认为这是不可控的。

    现在我们来重新梳理一下问题:

    1.我的接收端,是已经验证好能够保证完全接收到这个私有RF协议的所有数据的一个模块,我们公司其他产品发送的数据也是能够完全接收到的,接收端是能够保证不会出错的;

    2.发送端,目前是使用TI的开发板,我使用的是rfPacketTx的示例,发送的数据更改成我们的私有协议;

    3.在验证其数据发送效果时,发现其每两秒醒来一次发送数据,是有概率发送不出来,现象就是这一次醒来能够发送成功,我接收到了,但是下一次醒来发送数据,我没有收到任何数据,然后过几秒钟又能够接收到了,看起来就是RF功能会周期性关闭一样。

    4.我想知道怎么样去排查这个问题,包括怎么去查看RCL底层发送数据时候的状态以及RCL_Command命令的运行状态等等,RCL_Command命令状态我已经是验证好,包括submit和pend时候的状态都是完全没有问题的,下面是我RF发送部分的代码,如果需要查看其他部分我也可以提供。

  • 好吧,我现在有了新发现,RF模块是能够正常工作的,我在频谱仪上能够看到数据有按两秒的间隔发出,但是我的接收器上并没有把符合协议数据发送出来,可能他是已经收到了,但是数据格式不对就直接过滤掉,这是否就是意味着在给RF发送的寄存器写入数据的时候,数据有变化,有时候是对的,但是有时候又不对,所以才会造成我接收器这边有时候能够收到数据,有时候收不到数据的现象。

    现在我可以把重心放在私有协议数据包的构建上了,我想知道RCL_TxBuff_put();和RCL_TxBuffer_init()这两个函数的具体工作原理,特别是RCL_TxBuffer_init()中numPad参数和HDRLen的具体意义,我这里都设置成了0,我的私有协议数据是直接通过memcpy()函数复制过去的,这其中是否跟numpad参数以及hdrlen参数有关。

    以下是我这边使用频谱仪抓包时候的照片。发送五条数据出来的时候,上面显示也是五条数据,但是我的RF接收器上没有显示有收到数据

  • 您好

    您是否有嗅探器或任何工具来分析通过空中发送的射频数据,以确保它们具有您的接收器所期望的正确格式?
    如果没有,您可以在rfPacketRx项目中使用不同的启动板,以确保发送正确的数据。