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.

CCS/CC2640R2F: Bluetooth Remote Controller

Part Number: CC2640R2F


Tool/software: Code Composer Studio

Hello,

I need to implement a bluetooth remote controller for automotive use. The requirements are low power consumption and fast connection time.


I am using simple_central and simple_peripheral examples. Both with the same cc2640r2 processor.

Simple_peripheral is operating correctly. It is sending advertising every 1s when disconnected. After being connected, the peripheral sends a notification each time a key is pressed. This uses a cr2032 battery.


The problem is in simple_central. The connection time is too long. The central takes 15 seconds to connect to the peripheral. After being connected everything works correctly.

The strange thing is that when I run the code with breakpoints I can't find where the software is stuck.

The software works as follows:

1. After executing "SimpleCentral_init", the software waits for "GAP_DEVICE_INIT_DONE_EVENT" and starts the FSM.

2. The software waits 1s and sends "SC_EVT_SCAN_ENABLED" Search time for 1s.
3. The software waits for SC_EVT_SCAN_DISABLED and SC_EVT_ADV_REPORT. The UUID filter is enabled.

4. If the variable "numScanRes" is greater than 0, the event SC_EVT_CONNECT_ENABLED is generated.

5. If the variable "numConn" is greater than 0, the search for new devices is ended.

If the peripheral is switched off and on again, the reconnection time is the same.

The software is probably waiting for the wrong events to make the connection request. Does anyone know what the error is?

And is this application model the most suitable for a remote control?

simplelink_cc2640r2_sdk_4_20_00_04

Regards

  • Hi,

    Did you enable pairing and bonding? First time running it it will take more time since it also needs to save the information in the NV.

    Also you should make sure your scan interval is larger than your advertising interval.

    For more detail information I would recommend you to take a look at our SimpleLink Academy Advertising and Scanning section

  • Hello Christian Lee,

    Follows device configuration. Reconnections also take 15 seconds.

    static void SimpleCentral_init(void)
    {
      uint8_t i;
    
      ICall_registerApp(&selfEntity, &syncEvent);
    
      appMsgQueue = Util_constructQueue(&appMsg);
    
      for (i = 0; i < MAX_NUM_BLE_CONNS; i++)
      {
        connList[i].connHandle = CONNHANDLE_INVALID;
        connList[i].pRssiClock = NULL;
      }
    
      GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN,
                       (void *)attDeviceName);
      {
        #define APP_SUGGESTED_PDU_SIZE 251 //default is 27 octets(TX)
        #define APP_SUGGESTED_TX_TIME 2120 //default is 328us(TX)
    
        //This API is documented in hci.h
        //See the LE Data Length Extension section in the BLE5-Stack User's Guide for information on using this command:
        //software-dl.ti.com/.../
        //HCI_LE_WriteSuggestedDefaultDataLenCmd(APP_SUGGESTED_PDU_SIZE, APP_SUGGESTED_TX_TIME);
      }
    
      VOID GATT_InitClient();
      GATT_RegisterForInd(selfEntity);
      GGS_AddService(GATT_ALL_SERVICES);         // GAP
      GATTServApp_AddService(GATT_ALL_SERVICES); // GATT attributes
      GATT_RegisterForMsgs(selfEntity);
    
    
      {
        uint8_t pairMode = GAPBOND_PAIRING_MODE_INITIATE;
        uint8_t mitm = false;
        uint8_t ioCap = GAPBOND_IO_CAP_NO_INPUT_NO_OUTPUT;//GAPBOND_IO_CAP_DISPLAY_ONLY;
        uint8_t bonding = true;
    
        GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(uint8_t), &pairMode);
        GAPBondMgr_SetParameter(GAPBOND_MITM_PROTECTION, sizeof(uint8_t), &mitm);
        GAPBondMgr_SetParameter(GAPBOND_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
        GAPBondMgr_SetParameter(GAPBOND_BONDING_ENABLED, sizeof(uint8_t), &bonding);
      }
    
      VOID GAPBondMgr_Register(&bondMgrCBs);
    
      GAP_SetParamValue(GAP_PARAM_LINK_UPDATE_DECISION, GAP_UPDATE_REQ_ACCEPT_ALL);
      GAP_RegisterForMsgs(selfEntity);
      GAP_DeviceInit(GAP_PROFILE_CENTRAL, selfEntity, addrMode, NULL);
    
    }
    

    static void SimplePeripheral_init(void)
    {
      ICall_registerApp(&selfEntity, &syncEvent);
    
    #ifdef USE_RCOSC
      RCOSC_enableCalibration();
    #endif // USE_RCOSC
    
      appMsgQueueHandle = Util_constructQueue(&appMsgQueue);
      Util_constructClock(&clkPeriodic, SimplePeripheral_clockHandler,
                          SP_PERIODIC_EVT_PERIOD, 0, false, (UArg)&argPeriodic);
    
      GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName);
    
      {
        uint16_t paramUpdateDecision = DEFAULT_PARAM_UPDATE_REQ_DECISION;
        GAP_SetParamValue(GAP_PARAM_LINK_UPDATE_DECISION, paramUpdateDecision);
        GAP_SetParamValue(GAP_PARAM_LINK_UPDATE_DECISION, paramUpdateDecision);
        uint16_t intervalTimer = 2000;
        GAP_SetParamValue(GAP_ADV_PARAM_PRIMARY_INTERVAL_MIN, intervalTimer);
        GAP_SetParamValue(GAP_ADV_PARAM_PRIMARY_INTERVAL_MAX, intervalTimer);
      }
    
    #if defined(GAP_BOND_MGR)
      {
        uint8_t pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;
        uint8_t mitm = false;
        uint8_t ioCap = GAPBOND_IO_CAP_NO_INPUT_NO_OUTPUT;
        uint8_t bonding = true;
    
        GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(uint8_t), &pairMode);
        GAPBondMgr_SetParameter(GAPBOND_MITM_PROTECTION, sizeof(uint8_t), &mitm);
        GAPBondMgr_SetParameter(GAPBOND_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
        GAPBondMgr_SetParameter(GAPBOND_BONDING_ENABLED, sizeof(uint8_t), &bonding);
      }
    #endif
    
      GGS_AddService(GATT_ALL_SERVICES);
      GATTServApp_AddService(GATT_ALL_SERVICES);
      DevInfo_AddService();
      SimpleProfile_AddService(selfEntity, GATT_ALL_SERVICES);
    
      {
        uint8_t charValue1 = 1;
        uint8_t charValue2 = 1;
        uint8_t charValue3 = 1;
        uint8_t charValue4 = 1;
        uint8_t charValue5 = 1;
    
        SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR1, sizeof(uint8_t),
                                   &charValue1);
        SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR2, sizeof(uint8_t),
                                   &charValue2);
        SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR3, sizeof(uint8_t),
                                   &charValue3);
        SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR4, sizeof(uint8_t),
                                   &charValue4);
        SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR5, sizeof(uint8_t),
                                   &charValue5);
      }
    
      SimpleProfile_RegisterAppCBs(&SimplePeripheral_simpleProfileCBs);
    
    #if defined(GAP_BOND_MGR)
      VOID GAPBondMgr_Register(&SimplePeripheral_BondMgrCBs);
    #endif
    
      GAP_RegisterForMsgs(selfEntity);
      GATT_RegisterForMsgs(selfEntity);
    
      {
        #define APP_SUGGESTED_PDU_SIZE 251
        #define APP_SUGGESTED_TX_TIME 2120
        HCI_LE_WriteSuggestedDefaultDataLenCmd(APP_SUGGESTED_PDU_SIZE, APP_SUGGESTED_TX_TIME);
      }
    
      GATT_InitClient();
    
      Board_initKeys(SimplePeripheral_keyChangeHandler);
    
      SimplePeripheral_clearConnListEntry(CONNHANDLE_ALL);
    
      GAP_DeviceInit(GAP_PROFILE_PERIPHERAL, selfEntity, addrMode, NULL);
    
      SimplePeripheral_initPHYRSSIArray();
    
    }

  • Hi,

    How about your scan parameters? Can you show me the setting you have for scanning?

    Are you making sure that the scan interval is larger than advertising interval.

  • Hi Christin Lee,

    Follows the data used in the gap_scan. According to comments from gap_scan, the search time is in 1s.

    I suspect that I am not waiting for a specific event to start the connection.

    // Default scan duration in 10 ms
    #define DEFAULT_SCAN_DURATION                100 // 1 sec

    bool SimpleCentral_doDiscoverDevices(uint8_t index)
    {
      (void) index;
    
      numScanRes = 0;
      GapScan_enable(0, DEFAULT_SCAN_DURATION, 8);
    
      return (true);
    }

  • Hi,

    You need to check your scan window and scan interval. If your scan duration is set to 1s but scan window is 10 ms, scan interval is 1s, then you are most likely not getting anything.

    You need to make sure your scan window is larger than advertising interval.

    Please take a look at the SimpleLink Academy Scanning session.

    dev.ti.com/.../ble_scan_adv_basic.html

  • Hello Christian Lee,

    You were right, the problem was the search and advertising times. I changed the times and the connection time decreased.

    Now all that remains is to resolve the reconnection time.

    When turning off the connected peripheral and turning it on again, the connection time takes more than 20s.

    Analyzing the software, the processor searches for new devices and finds the same one that is already connected.

    Do you know how reconnections should be handled?

    Regards,

    Dhiego

  • What's your supervision timeout?

    Because even though the peripheral disappeared from the connection, the master needs to stay in the connection until supervision timeout. 

    Then it will go back to scanning state again to search for that device.

    For more information regarding connection, please take a look at our SimpleLink Academy. 

    dev.ti.com/.../ble_connections.html

  • Hello Christin Lee,

    The product needs to respond to several remote controls, so the central is always looking for peripherals.

    When I remove and insert the battery in the peripheral the connection does not return automatically and the device starts advertising. The central receives the advertising. If a new connection is initiated, the software freezes.

    So I created a function to check if the device is already part of the connection list.

    Does the automatic reconnection you mentioned work if the peripheral is turned off and then turned on?

    And is it possible to save a list of peripherals so that the central searches exclusively for these devices? Or will the search always return all devices and a software filter needs to be performed?

    Follows timeout parameters.

    #define DEFAULT_UPDATE_MIN_CONN_INTERVAL      400
    // Maximum connection interval (units of 1.25ms)
    #define DEFAULT_UPDATE_MAX_CONN_INTERVAL      800
    // Slave latency to use if automatic parameter update request is enabled
    #define DEFAULT_UPDATE_SLAVE_LATENCY          0
    // Supervision timeout value (units of 10ms)
    #define DEFAULT_UPDATE_CONN_TIMEOUT           600

  • Hey,

    For BLE, in order to form a connection, the peripheral always needs to enter advertising first. Even if it has previously bonded. .

    After reconnecting, the software should not freeze.

    Can you provide code snippet of your modifications.

    Have you done all the SimpleLink Academy training? If not, I highly recommend you to walk through all the trainings. 

    The supervision timeout parameter you show here is only valid if the connection parameter update is sent.

    The default supervision timeout in the simple_central project is 20 seconds.

    To answer your question:

    Does the automatic reconnection you mentioned work if the peripheral is turned off and then turned on?

    --> I don't think I mentioned anything regarding automatic reconnection. The master still needs to scan and look for the peripheral device.

    And is it possible to save a list of peripherals so that the central searches exclusively for these devices? Or will the search always return all devices and a software filter needs to be performed?

    -->You can use whitelist. For more information, please take a look at the privacy and white list section

    -->You can also add software filtering as well since the whitelist will only work after devices have bonded. For example, simple_central only look for devices that broadcast with certain UUID. You can check the DEFAULT_DEV_DISC_BY_SVC_UUID flag in the software.

  • Hello Christin Lee,

    Now I understand. I was expecting the device to reconnect if it was restarted during the timeout period.

    However, they can only return the connection after the timeout.

    I added the command to reduce the timeout to 2s.

    Thank you for your attention.

    static void SimpleCentral_processGapMsg(gapEventHdr_t *pMsg)
    {
      switch (pMsg->opcode)
      {
        case GAP_DEVICE_INIT_DONE_EVENT:
        {
          GapInit_setPhyParam(INIT_PHY_1M, INIT_PHYPARAM_SUP_TIMEOUT, 200);

  • Hi, 

    In order to change the supervision timeout, you should use GAP_SetParamValue(TGAP_CONN_EST_SUPERV_TIMEOUT, the time you want).

    For more information, please take a look at the API documentation.

    dev.ti.com/.../group___g_a_p___params.html