Question about Advertising and Disconnecting


#1

Hi all,

I’m new to the BLE ecosystem, and I’ve slightly edited the provided HRM demo in the Arduino IDE to send analog input values to the nRF toolbox app on my phone. Eventually, I want to make the device run on a battery instead of hooking it up to a power supply. The issue is that when I select disconnect on my phone, the Nano v2 stays in the periodicCallback() function, and doesn’t exit. How do I make it so that when I disconnect from the Nano v2, that it stops sending data, advertising and scanning? This is important because I’d like to only gather data from the device for a minute every hour, so it doesn’t need to be advertising and scanning for the entire time.

Thanks.


#2

Hi,

are you shure that is not the ticker?


#3

Hi,

thanks for the reply. I guess it could be, but do you mind explaining what the ticker does, and how I would change it to address the issue i’m having?


#4

Hi @Manny,

We can not address the issue unless you post your code here.


#5

Correct. Here is the code I’ve been using. It is just a modified version of the HRM demo. Instead of sending HRM data, it sends temperature recorded from an external source.

/*
 * Copyright (c) 2016 RedBear
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

/**
 * @note This demo is Nordic HRM example.
 *       You could use nRF toolbox tool to test it.
 */
#include <nRF5x_BLE_API.h>

#define DEVICE_NAME       "Temp Sensor v1"

#define res 10000
#define analogIn A3
#define stdTemp 25
#define nsamples 10
#define beta 3950
#define stdRes 10000
#define LED_BUILTIN D13

BLE                       ble;
Ticker                    ticker_task1;

static uint8_t Counter     = 100;
static uint8_t temp[2]         = {0x00, Counter};
static const uint8_t location = 0x03;

static const uint16_t uuid16_list[] = {GattService::UUID_HEART_RATE_SERVICE};

// Create characteristic and service
GattCharacteristic   tempRate(GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR, temp, sizeof(temp), sizeof(temp), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
GattCharacteristic   tempLocation(GattCharacteristic::UUID_BODY_SENSOR_LOCATION_CHAR,(uint8_t *)&location, sizeof(location), sizeof(location),GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
GattCharacteristic   *tempChars[] = {&tempRate, &tempLocation, };
GattService          tempService(GattService::UUID_HEART_RATE_SERVICE, tempChars, sizeof(tempChars) / sizeof(GattCharacteristic *));

void disconnectionCallBack(const Gap::DisconnectionCallbackParams_t *params)
{
  Serial.println("Disconnected!");
  Serial.println("Restarting the advertising process");
  ble.startAdvertising();
}

void periodicCallback() 
{
  if (ble.getGapState().connected)
  {
    // Update the temperature measurement
    // First byte = 8-bit values, no extra info, Second byte = uint8_t temp value
   
   uint16_t samples[nsamples];   
   float average;
   uint16_t i;
     for (i=0; i < nsamples; i++)
     {
       samples[i] = analogRead(analogIn);
       delay(100); 
     }
    average = 0;
    for(i=0; i<nsamples; i++)
    {
      average += samples[i];
    }
    average /= nsamples;
    average = 1023/average - 1;
    average = res/average;
    float steinhart;
    steinhart = average / stdRes;
    steinhart = log(steinhart);
    steinhart /= beta;
    steinhart += 1.0 / (stdTemp + 273.15);
    steinhart = 1.0 / steinhart;
    steinhart -= 273.15;
    temp[1] = steinhart; 
    ble.updateCharacteristicValue(tempRate.getValueAttribute().getHandle(), temp, sizeof(temp));
    digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level) to check if the function is still being called even after disconnection 
    //delay(1000);
  }
}

void setup()
{
  // put your setup code here, to run once
  Serial.begin(9600);
  Serial.println("Temp. Meas. ");
  // Init timer task
  ticker_task1.attach(periodicCallback, 1);
  // Init ble
  ble.init();
  ble.onDisconnection(disconnectionCallBack);

  // setup adv_data and srp_data
  ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
  ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t*)uuid16_list, sizeof(uuid16_list));
  ble.accumulateAdvertisingPayload(GapAdvertisingData::HEART_RATE_SENSOR_HEART_RATE_BELT);
  ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
  // set adv_type
  ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    // add service
  ble.addService(tempService);
  // set device name
  ble.setDeviceName((const uint8_t *)DEVICE_NAME);
  // set tx power,valid values are -40, -20, -16, -12, -8, -4, 0, 4
  ble.setTxPower(4);
  // set adv_interval, 100ms in multiples of 0.625ms.
  ble.setAdvertisingInterval(160);
  // set adv_timeout, in seconds
  ble.setAdvertisingTimeout(0);
  // start advertising
  ble.startAdvertising();
}

void loop() 
{
  // put your main code here, to run repeatedly:
  ble.waitForEvent();
}

#6

Your code looks like nothing special. If it stayed in the periodic callback function, I would suggest you to add some serial log to target where it stays.


#7

Do you mind explaining what a serial log is, and how I would use it to ensure that it exits the periodic callback function after disconnection?


#8

He’s talking about using the Arduino serial monitor to debug your program:

I think the way it would work now, when you disconnect on your phone, your program goes
to the disconnectionCallBack() function, where the ble.startAdvertising() function is then
called.

If you bring up the Ardunio serial monitor, you will probably see these messages printed by
the Serial.println() functions when you disconnect on the phone:

Disconnected!
Restarting the advertising process

At least, that’s the way my system setup works.

But before you start making modifications, what is your high level objective in changing the
advertising? Are you trying to save power by not advertising all the time, and if so, what
board function are you trying to save power against (BLE and/or ADC)?


#9

Correct. I’ve tried commenting out the ble.startAdvertising() function in the dissconnectionCallback(), but then the device doesn’t connect in the first place.

My high level objective is to save power by not advertising. Ideally, the device would run on sleep mode until it was pinged by another device (ie, raspberry pi), and then it would send data over ble for a set amount of a few minutes, then go back into sleep mode. Thanks


#10

Check these two threads for reducing power consumption. They are for the previous version of the Nano board, but perhaps they can be ported to the current NanoV2 board:



#11

Thanks for the links. I’ll take a look at them. Thanks for the advice