This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2650: Packet loss with multiple sensors transmitting to a single receiver

Part Number: CC2650

The current project I am working on has a multiple sensors transmitting (RF, 2440 MHz) to another, acting as a receiver, which then sends the packets over UART for processing. I am running into an issue with packet loss. 

For instance I currently have 4 sensors transmitting with a 100 ms interval (10 /s) which results in ~2-4% of packets being lost. Surprisingly, a single sensor transmitting with a 10 ms interval (100 /s) has no packet loss whatsoever. Ideally we would be able to have 11 sensors transmitting with 25 ms interval.

From testing further I have noticed that:

  - Packet loss increases with frequency and number of sensors

  - Most of the time lots of packets are lost consecutively i.e will lose ~20 in a row (occasionally still loses individual packets)

  - Often multiple sensors will lose packets at the same time

Any help with this issue would be greatly appreciated.

Thanks,

Olly

  • Hi Olly,

    Often multiple sensors will lose packets at the same time

    What kind of communication model are you using? E.g. many-to-one? many-to-many?

    Packet loss increases with frequency and number of sensors

    By "increases with frequency", do you mean increasing the frequency at which packets are TX'ed?
    If yes, this observation makes sense -- all other things being equal, as you lower the TX interval and increase the number of TX devices, it increases the number of packets which the single RX device must receive, which in turn increases the probability of packet loss.

    Can you share some more details? Specifically:

    1. How large are the packets?
    2. What data rate are you using?
    3. Is your project based on SDK examples? If yes, which ones? (And which SDK are you using?)

    I think a calculation of the maximum "bandwidth" in your system has might be useful.
    For example, a simplified inequality could be:

    maxNumTxDevices * (sizeOfPacket / dataRate)    <    txInterval

    11 * (sizeOfPacket / dataRate)    <    25 msec

    As the left-hand-side increases and approaches the right-hand-side, we can reasonably expect higher packet loss.

    which then sends the packets over UART for processing

    The above is not considering other potential sources of device workload cycles, for example UART processing.
    Does the UART processing happen in real time?
    If yes, can you reduce this as much as possible to see if packet loss decreases?

    Thanks,
    Toby

  • Hi Toby,

    Thank you very much for getting back to me.

    What kind of communication model are you using? E.g. many-to-one? many-to-many?

    I am using many-to-one. What I meant by muliple sensors losing packets at the same time is that most of the packets will still be received, but multiple specific sensors will lose packets. 

    By "increases with frequency", do you mean increasing the frequency at which packets are TX'ed?

    Yes, frequency as in number of packets per second

    How large are the packets?

    13 bits. I have tested with fewer (8 & 2) and it doesn't appear to have made a difference

    What data rate are you using?

    What is this the data rate of and how would I find out?

    Is your project based on SDK examples? If yes, which ones? (And which SDK are you using?)

    Yes, it is based off the CC2650 LaunchPad RF Packet Tx and Rx examples (from TI-RTOS for CC2650 (2.21.00.06)). I then replaced the header files with the ones for the SensorTag as that is the one I am using. I am using CC2650STK.

    Does the UART processing happen in real time?
    If yes, can you reduce this as much as possible to see if packet loss decreases?

    The processing does happen in real time on the computer, although currently I have only been measuring the packet loss. I will have a go at recording the raw data then finding the packet loss after the fact

    Olly

  • I have recorded the data then found packet loss after the fact - there was no change

  • What is this the data rate of and how would I find out?

    Can you attach your smartrf_settings.c file?

    13 bits. I have tested with fewer (8 & 2) and it doesn't appear to have made a difference

    This should be relatively manageable. 13 bits would be rounded up to 16 bits (radio payload length is specified in bytes).

    Next thing to check are packet collisions. Is each sensor TX'ing with some random time offset?

  • Can you attach your smartrf_settings.c file?

    
    //*********************************************************************************
    // These settings have been generated for use with TI-RTOS and cc26xxware
    //
    // Generated by SmartRF Studio version 2.3.0
    // Tested with TI-RTOS version tirtos_simplelink_2_16_xx_xx
    //
    //*********************************************************************************
    
    
    //*********************************************************************************
    // Parameter summary
    // Address: aa-bb
    // Frequency: 2445.00000 MHz
    // Data Format: Serial mode disable
    // Deviation: 50.000 kHz
    // Packet Length Config: Variable
    // Max Packet Length: 128
    // Packet Length: 30
    // RX Filter BW: 220 kHz
    // Symbol Rate: 50.00000 kBaud
    // Sync Word Length: 32 Bits
    // TX Power: 5 dBm
    // Whitening: No whitening
    
    #include <driverlib/rf_mailbox.h>
    #include <driverlib/rf_common_cmd.h>
    #include <driverlib/rf_prop_cmd.h>
    #include <ti/drivers/rf/RF.h>
    #include <rf_patches/rf_patch_cpe_genfsk.h>
    #include <rf_patches/rf_patch_rfe_genfsk.h>
    #include <rf_patches/rf_patch_mce_genfsk.h>
    #include "smartrf_settings.h"
    
    
    // TI-RTOS RF Mode Object
    RF_Mode RF_prop =
    {
        .rfMode = RF_MODE_PROPRIETARY_2_4,
        .cpePatchFxn = &rf_patch_cpe_genfsk,
        .mcePatchFxn = &rf_patch_mce_genfsk,
        .rfePatchFxn = &rf_patch_rfe_genfsk,
    };
    
    
    uint32_t shape[] = {0x00000000, 0x00000000, 0x00000000, 0x360c0100, 0xacaba076, 0xacacacac};
    
    
    // Overrides for CMD_PROP_RADIO_SETUP
    uint32_t pOverrides[] = {
            MCE_RFE_OVERRIDE(1,0,0,1,0,0),
            HW_REG_OVERRIDE(0x4038,0x34),
            HW_REG_OVERRIDE(0x6088,0x3F1F),
            HW_REG_OVERRIDE(0x608C,0x8213),
            HW32_ARRAY_OVERRIDE(0x405C,1),
            (uint32_t) 0x1801F800,
            HW32_ARRAY_OVERRIDE(0x402C,1),
            (uint32_t) 0x00608402,
            (uint32_t) 0xc0040031,
            (uint32_t) &shape[0],
            (uint32_t) 0x00000343,
            (uint32_t) 0x001000a3,
            (uint32_t) 0x000484a3,
            (uint32_t) 0x1c8f0583,
            (uint32_t) 0x1c8f0543,
            (uint32_t) 0x65980603,
            (uint32_t) 0x00020623,
            (uint32_t) 0x659805c3,
            (uint32_t) 0x000205e3,
            (uint32_t) 0x02010403,
            HW32_ARRAY_OVERRIDE(0x4034,1),
            (uint32_t) 0x177F0408,
            (uint32_t) 0x00008463,
            (uint32_t) 0x00388473,
            (uint32_t) 0x00F388a3,
            (uint32_t)0xFFFFFFFF,
    };
    
    // CMD_PROP_RADIO_SETUP
    rfc_CMD_PROP_RADIO_SETUP_t RF_cmdPropRadioDivSetup =
    {
        .commandNo = 0x3806,
        .status = 0x0000,
        .pNextOp = 0, // INSERT APPLICABLE POINTER: (uint8_t*)&xxx
        .startTime = 0x00000000,
        .startTrigger.triggerType = 0x0,
        .startTrigger.bEnaCmd = 0x0,
        .startTrigger.triggerNo = 0x0,
        .startTrigger.pastTrig = 0x0,
        .condition.rule = 0x1,
        .condition.nSkip = 0x0,
        .modulation.modType = 0x1,
        .modulation.deviation = 200,
        .symbolRate.preScale = 15,
        .symbolRate.rateWord = 131072,
        .rxBw = 7,
        .preamConf.nPreamBytes = 0x8,
        .preamConf.preamMode = 0x0,
        .formatConf.nSwBits = 16,
        .formatConf.bBitReversal = 0x0,
        .formatConf.bMsbFirst = 0x1,
        .formatConf.fecMode = 0x0,
        .formatConf.whitenMode = 0x0,
        .config.frontEndMode = 0x0,
        .config.biasMode = 0x0,
        .config.analogCfgMode = 0x0,
        .config.bNoFsPowerUp = 0x0,
        .txPower = 0x9324,
        .pRegOverride = pOverrides,
    };
    
    // CMD_FS
    rfc_CMD_FS_t RF_cmdFs =
    {
        .commandNo = 0x0803,
        .status = 0x0000,
        .pNextOp = 0, // INSERT APPLICABLE POINTER: (uint8_t*)&xxx
        .startTime = 0x00000000,
        .startTrigger.triggerType = 0x0,
        .startTrigger.bEnaCmd = 0x0,
        .startTrigger.triggerNo = 0x0,
        .startTrigger.pastTrig = 0x0,
        .condition.rule = 0x1,
        .condition.nSkip = 0x0,
        .frequency = 2450,
        .fractFreq = 0x0000,
        .synthConf.bTxMode = 1,
        .synthConf.refFreq = 0x0,
    };
    
    // CMD_PROP_TX
    rfc_CMD_PROP_TX_t RF_cmdPropTx =
    {
        .commandNo = 0x3801,
        .status = 0x0000,
        .pNextOp = 0, // INSERT APPLICABLE POINTER: (uint8_t*)&xxx
        .startTime = 0x00000000,
        .startTrigger.triggerType = 0x0,
        .startTrigger.bEnaCmd = 0x0,
        .startTrigger.triggerNo = 0x0,
        .startTrigger.pastTrig = 0x0,
        .condition.rule = 0x1,
        .condition.nSkip = 0x0,
        .pktConf.bFsOff = 0x0,
        .pktConf.bUseCrc = 0x1,
        .pktConf.bVarLen = 0x1,
        .pktLen = 0x1e, // SET APPLICATION PAYLOAD LENGTH
        .syncWord = 0xD391D391,
        .pPkt = 0, // INSERT APPLICABLE POINTER: (uint8_t*)&xxx
    };
    
    // CMD_PROP_RX
    rfc_CMD_PROP_RX_t RF_cmdPropRx =
    {
        .commandNo = 0x3802,
        .status = 0x0000,
        .pNextOp = 0, // INSERT APPLICABLE POINTER: (uint8_t*)&xxx
        .startTime = 0x00000000,
        .startTrigger.triggerType = 0x0,
        .startTrigger.bEnaCmd = 0x0,
        .startTrigger.triggerNo = 0x0,
        .startTrigger.pastTrig = 0x0,
        .condition.rule = 0x1,
        .condition.nSkip = 0x0,
        .pktConf.bFsOff = 0x0,
        .pktConf.bRepeatOk = 0x0,
        .pktConf.bRepeatNok = 0x0,
        .pktConf.bUseCrc = 0x1,
        .pktConf.bVarLen = 0x1,
        .pktConf.bChkAddress = 0x0,
        .pktConf.endType = 0x0,
        .pktConf.filterOp = 0x0,
        .rxConf.bAutoFlushIgnored = 0x0,
        .rxConf.bAutoFlushCrcErr = 0x0,
        .rxConf.bIncludeHdr = 0x1,
        .rxConf.bIncludeCrc = 0x0,
        .rxConf.bAppendRssi = 0x0,
        .rxConf.bAppendTimestamp = 0x0,
        .rxConf.bAppendStatus = 0x1,
        .syncWord = 0xD391D391,
        .maxPktLen = 0x7d, // MAKE SURE DATA ENTRY IS LARGE ENOUGH
        .address0 = 0xaa,
        .address1 = 0xbb,
        .endTrigger.triggerType = 0x1,
        .endTrigger.bEnaCmd = 0x0,
        .endTrigger.triggerNo = 0x0,
        .endTrigger.pastTrig = 0x0,
        .endTime = 0x00000000,
        .pQueue = 0, // INSERT APPLICABLE POINTER: (dataQueue_t*)&xxx
        .pOutput = 0, // INSERT APPLICABLE POINTER: (uint8_t*)&xxx
    };
    
    // CMD_TX_TEST
    rfc_CMD_TX_TEST_t RF_cmdTxTest =
    {
            .commandNo = 0x0808,
            .status = 0x0000,
            .pNextOp = 0, /*INSERT APPLICABLE POINTER: (uint8_t*)&xxx */
            .startTime = 0x00000000,
            .startTrigger.triggerType = 0x0,
            .startTrigger.bEnaCmd = 0x0,
            .startTrigger.triggerNo = 0x0,
            .startTrigger.pastTrig = 0x0,
            .condition.rule = 0x1,
            .condition.nSkip = 0x0,
            .config.bUseCw = 0x0,
            .config.bFsOff = 0x0,
            .config.whitenMode = 0x2,
            .__dummy0 = 0x00,
            .txWord = 0xabcd,
            .__dummy1 = 0x00,
            .endTrigger.triggerType = 0x1,
            .endTrigger.bEnaCmd = 0x0,
            .endTrigger.triggerNo = 0x0,
            .endTrigger.pastTrig = 0x0,
            .syncWord = 0x930b51de,
            .endTime = 0x00000000,
    };
    

    Attached

    13 bits. I have tested with fewer (8 & 2) and it doesn't appear to have made a difference

    This should be relatively manageable. 13 bits would be rounded up to 16 bits (radio payload length is specified in bytes).

    I am very sorry, I meant 13 bits, though I tried with 8 & 2 bytes and it didn't make a difference

    Is each sensor TX'ing with some random time offset?

    Yes, each sensor starts TX'ing when it is switched on at constant intervals

  • Hi,

    Looks like the datarate is 50 kbps (// Symbol Rate: 50.00000 kBaud).

    Yes, each sensor starts TX'ing when it is switched on at constant intervals

    The constant interval may explain why you are missing several packets from a single sensor -- for example, the RX device is receiving data from sensor 1, and then sensor 2 transmits data before sensor 1 data is fully received, then sensor 2 data is missed.
    Adding some jitter into the interval may help here (in general, something like TDMA would be applicable (time-division multiple access)).

    Probably, we need to add some extra margin into this calculation: 11 * (sizeOfPacket / dataRate)    <    25 msec

    Perhaps something like 11 * (sizeOfPacket / dataRate) * margin    <    25 msec

    numDevices * (sizeOfPacket / dataRate) * margin    <    TX interval

    So, to receive reliably for a given setup, some simple things to try:

    1. reduce numDevices
    2. reduce sizeOfPacket (probably not as relevant for now, as observed from your experiment with "8 & 2 bytes"
    3. increase dataRate (see section "23.7.5.2 Proprietary Mode Setup Command" in the CC2650 TRM)
    4. increase TX interval