Part Number: LAUNCHXL-CC2650
Other Parts Discussed in Thread: INA169, CC2640
Tool/software: Code Composer Studio
Hi guys,
I am working on a BME680 (via i2c) based ultra low power sensor node. I started with the simple broadcaster project and made a few modifications. I added the necessary codes and libraries for the i2c and bme api. Also, in the main function I have added standby power policy to save power during BLE broadcast intervals.
In the ble broadcaster init function I kept the gaproll advert off time equal to 0 which should make it advertising for 30 seconds but I wanted to advert only for 1 second which I did via [GAP_SetParamValue(TGAP_LIM_ADV_TIMEOUT, 1);] this command. After every advert packet for 1 second it should automatically disable the advertising.
I am not well familiar with the details of TI-RTOS so, in the main ble broadcaster task function before the original infinite loop I created another infinite loop so that it bypasses the original one and written my repeating code there.
Here, I am reading the bme sensor making the data packet, upload it to gap and started the advertising, Then the device goes to sleep for 10 sec before the next broadcast packet.
This was expected to repeat endlessly. But while testing, I found that only after 12/13 broadcasts there are no more of them but the mcu was still running consuming constant ~3.5mA. Though during the first 12/13 packets the current came out as expected (6mA during broadcast, 50uA during the 10s sleep) ... But after that it was stuck...
*** I measured current using multimeter and INA169 current monitor module.
Any idea what is happening in here? Also please help me to understand what is the purpose of the by default given infinite loop within the ble broadcaster task function. Bypassing it might have caused the problem?
Thanks in advance,
Jawad.
void upload_adv_to_gap(){
GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);
}
void turn_on_adv(){
uint8_t my_adv_en = TRUE;
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &my_adv_en);
}
void turn_off_adv(){
uint8_t is_adv_enabled = FALSE;
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &is_adv_enabled);
}
static void SimpleBLEBroadcaster_init(void)
{
// ******************************************************************
// N0 STACK API CALLS CAN OCCUR BEFORE THIS CALL TO ICall_registerApp
// ******************************************************************
// Register the current thread as an ICall dispatcher application
// so that the application can send and receive messages.
ICall_registerApp(&selfEntity, &sem);
// Hard code the DB Address till CC2650 board gets its own IEEE address
// uint8 bdAddress[B_ADDR_LEN] = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x33 };
// HCI_EXT_SetBDADDRCmd(bdAddress);
// Create an RTOS queue for message from profile to be sent to app.
appMsgQueue = Util_constructQueue(&appMsg);
// Open LCD
dispHandle = Display_open(Display_Type_LCD, NULL);
// Setup the GAP Broadcaster Role Profile
{
// For all hardware platforms, device starts advertising upon initialization
uint8_t initial_advertising_enable = TRUE;
// By setting this to zero, the device will go into the waiting state after
// being discoverable for 30.72 second, and will not being advertising again
// until the enabler is set back to TRUE
// uint16_t gapRole_AdvertOffTime = 0;
uint16_t gapRole_AdvertOffTime = 0;
//this has been modified. original code had scannable undirected type
uint8_t advType = GAP_ADTYPE_ADV_NONCONN_IND; // use non-connectable adv
// Set the GAP Role Parameters
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initial_advertising_enable);
GAPRole_SetParameter(GAPROLE_ADVERT_OFF_TIME, sizeof(uint16_t), &gapRole_AdvertOffTime);
GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof (scanRspData), scanRspData);
GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);
GAPRole_SetParameter(GAPROLE_ADV_EVENT_TYPE, sizeof(uint8_t), &advType);
}
// Set advertising interval
{
uint16_t advInt = DEFAULT_ADVERTISING_INTERVAL;
//device is in limited discoverable mode.
//advertizing will only be running for 1 second.
GAP_SetParamValue(TGAP_LIM_ADV_TIMEOUT, 1);
GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MIN, advInt);
GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MAX, advInt);
GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MIN, advInt);
GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MAX, advInt);
}
// Start the Device
VOID GAPRole_StartDevice(&simpleBLEBroadcaster_BroadcasterCBs);
//Display_print0(dispHandle, 0, 0, "BLE Broadcaster");
}
static void SimpleBLEBroadcaster_taskFxn(UArg a0, UArg a1)
{
ledPinHandle = PIN_open(&ledPinState, ledPinTable);
//blink an LED. just a visual that the program has started.
PIN_setOutputValue(ledPinHandle, OP, 1); millisecondDelay(2000); PIN_setOutputValue(ledPinHandle, OP, 0);
i2c_initialization();
i2c = I2C_open(Board_I2C, &i2cParams);
SimpleBLEBroadcaster_init();
millisecondDelay(5000); //5s delay
sensor_initialization(); //init the bme680
sensor_configuration(); //config the bme680
for (;;)
{
sensor_read_data(); //read environmental data from BME680 via i2c
sleep_bme680(); //set BME680 to sleep mode
load_adv_buf(); //load BME data into the advertising buffer
upload_adv_to_gap(); //use gaprole param setting to upload adv buffer
turn_on_adv(); //use gaprole param setting to enable advertising
millisecondDelay(10000); //10s delay
}
// Application main loop
for (;;)
{
// Waits for a signal to the semaphore associated with the calling thread.
// Note that the semaphore associated with a thread is signaled when a
// message is queued to the message receive queue of the thread or when
// ICall_signal() function is called onto the semaphore.
ICall_Errno errno = ICall_wait(ICALL_TIMEOUT_FOREVER);
if (errno == ICALL_ERRNO_SUCCESS)
{
ICall_EntityID dest;
ICall_ServiceEnum src;
ICall_HciExtEvt *pMsg = NULL;
if (ICall_fetchServiceMsg(&src, &dest,
(void **)&pMsg) == ICALL_ERRNO_SUCCESS)
{
if ((src == ICALL_SERVICE_CLASS_BLE) && (dest == selfEntity))
{
// Process inter-task message
SimpleBLEBroadcaster_processStackMsg((ICall_Hdr *)pMsg);
}
if (pMsg)
{
ICall_freeMsg(pMsg);
}
}
// If RTOS queue is not empty, process app message.
while (!Queue_empty(appMsgQueue))
{
sbbEvt_t *pMsg = (sbbEvt_t *)Util_dequeueMsg(appMsgQueue);
if (pMsg)
{
// Process message.
SimpleBLEBroadcaster_processAppMsg(pMsg);
// Free the space from the message.
ICall_free(pMsg);
}
}
}
}
}