This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Delay in connecting and disconnecting BLE

Hi,

For my application using softdevice I need ADC update every 400ms and Battery level update every 2sec and  string update for HT1632 led driver every 2sec.So I have created three timers with corresponding time interval.When I included ADC timer it worked well.But when I included battery level and ht1632 driver timer and tried connecting to device from nRF Connect for Mobile I found that connection to softdevice is delayed more than 5sec same thing observed on disconnect.

As a part of clearing this issue on browsing i read a post on devzone https://devzone.nordicsemi.com/f/nordic-q-a/4147/ble-connect-events-cause-delays-in-app_timer-and-ppi,here it is mentioned that scheduler could solve the issue.If it helps please let me know  how implementation can be done.And also I am unable to understand on including ADC timer it is working fine without improper delay,but why not on including other two timers?  

Thank you.

Parents Reply Children
  • /**
     * Copyright (c) 2014 - 2019, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    /** @file
     *
     * @defgroup ble_sdk_app_template_main main.c
     * @{
     * @ingroup ble_sdk_app_template
     * @brief Template project main file.
     *
     * This file contains a template for creating a new application. It has the code necessary to wakeup
     * from button, advertise, get a connection restart advertising on disconnect and if no new
     * connection created go back to system-off mode.
     * It can easily be used as a starting point for creating a new application, the comments identified
     * with 'YOUR_JOB' indicates where and how you can customize.
     */
    
    #include "HT1632_INIT.h"
    #include "app_error.h"
    #include "app_timer.h"
    #include "ble.h"
    #include "ble_advdata.h"
    #include "ble_advertising.h"
    #include "ble_bas.h"
    #include "ble_conn_params.h"
    #include "ble_conn_state.h"
    #include "ble_hci.h"
    #include "ble_srv_common.h"
    #include "bsp_btn_ble.h"
    #include "characterarray_5x21.h"
    #include "fds.h"
    #include "nordic_common.h"
    #include "nrf.h"
    #include "nrf_ble_gatt.h"
    #include "nrf_ble_qwr.h"
    #include "nrf_delay.h"
    #include "nrf_drv_rtc.h"                            //**RTC driver legacy layer**//
    #include "nrf_drv_saadc.h"
    #include "nrf_gpio.h"                               //** Hardware access layer for managing the GPIO peripheral.**//
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    #include "nrf_pwr_mgmt.h"
    #include "nrf_rtc.h"                                //**To access registers like INTENSET and EVTEN of RTC**//
    #include "nrf_saadc.h"
    #include "nrf_sdh.h"
    #include "nrf_sdh_ble.h"
    #include "nrf_sdh_soc.h"
    #include "peer_manager.h"
    #include "peer_manager_handler.h"
    #include "rtc_service.h"                            //**rtc service related header file**//
    #include "sensorsim.h"
    #include <math.h>
    #include <stdbool.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <string.h>
    
    #define SAMPLES_IN_BUFFER 5
    #define COMPARE_COUNTERTIME (3UL)                   //**< Get Compare event COMPARE_TIME seconds after the counter starts from 0. *//
    
    #define DEVICE_NAME "1Nordic_integration1"          /**< Name of device. Will be included in the advertising data. */
    #define MANUFACTURER_NAME "NordicSemiconductor"     /**< Manufacturer. Will be passed to Device Information Service. */
    #define APP_ADV_INTERVAL 300                        /**< The advertising interval (in units of 0.625 ms. This value corresponds to 187.5 ms). */
    
    #define APP_ADV_DURATION 18000                       /**< The advertising duration (180 seconds) in units of 10 milliseconds. */
    #define APP_BLE_OBSERVER_PRIO 3                      /**< Application's BLE observer priority. You shouldn't need to modify this value. */
    #define APP_BLE_CONN_CFG_TAG 1                      /**< A tag identifying the SoftDevice BLE configuration. */
    
    #define MIN_CONN_INTERVAL MSEC_TO_UNITS(100, UNIT_1_25_MS) /**< Minimum acceptable connection interval (0.1 seconds). */
    #define MAX_CONN_INTERVAL MSEC_TO_UNITS(200, UNIT_1_25_MS) /**< Maximum acceptable connection interval (0.2 second). */
    #define SLAVE_LATENCY 0                                    /**< Slave latency. */
    #define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS)   /**< Connection supervisory timeout (4 seconds). */
    
    #define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
    #define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
    #define MAX_CONN_PARAMS_UPDATE_COUNT 3                       /**< Number of attempts before giving up the connection parameter negotiation. */
    
    #define SEC_PARAM_BOND 1                               /**< Perform bonding. */
    #define SEC_PARAM_MITM 0                               /**< Man In The Middle protection not required. */
    #define SEC_PARAM_LESC 0                               /**< LE Secure Connections not enabled. */
    #define SEC_PARAM_KEYPRESS 0                           /**< Keypress notifications not enabled. */
    #define SEC_PARAM_IO_CAPABILITIES BLE_GAP_IO_CAPS_NONE /**< No I/O capabilities. */
    #define SEC_PARAM_OOB 0                                /**< Out Of Band data not available. */
    #define SEC_PARAM_MIN_KEY_SIZE 7                       /**< Minimum encryption key size. */
    #define SEC_PARAM_MAX_KEY_SIZE 16                      /**< Maximum encryption key size. */
    
    #define DEAD_BEEF 0xDEADBEEF      /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */
    #define BATT_MEAS_INTERVAL_MS 400 //**The interval between two measurements (to set up the application timer)**//
    #define mask 0XFFFFFF             //**Macro for wrapping value into 24bit**//
    //**Battery voltage measurement parameters and variables**//
    #define BATT_MAX_VOLTAGE_MV 1000                          //**The maximum battery voltage in mV (for percentage calculations)**//
    #define BATT_MIN_VOLTAGE_MV 432                           //**The minimum battery voltage in mV, used for % calculation and low battery action**//
    #define BATT_MEAS_AVG_FACTOR 3                            //**The inverse of the weight to use for the running average smoothing of the read value**//
    #define BATTERY_LEVEL_MEAS_INTERVAL APP_TIMER_TICKS(2000) //**< Battery level measurement interval (ticks). **//
    #define STRING_DISPLAY_INTERVAL APP_TIMER_TICKS(2000)     //**< string display interval (ticks). **//
    #define WRITE 25                                          //**Assigning GPIO Pin number to write pin of HT1632**//
    #define DATA 26                                           //*Assigning GPIO Pin number to Data pin of HT1632*//
    #define CS 27                                             //*Assigning GPIO Pin number to CS pin of HT1632*//
    #define chip_byte_address(x, y) ((x % 21) << 1);          //*Setting Address*//
    uint8_t cursorX = 0;                                      //*Cursor X position*//
    uint8_t cursorY = 0;                                      //*Cursor Y position*//
    char str[] = "ORDAN TECHNOLOGIES PVT LTD";                //*Welcome String*//
    char str1[] = "BATTERY LOW";                              //*String to be displayed on Battery Low Condition*//
    char str2[] = "BATTERY FULLY CHARGED";                    //*String to be displayed on Battery Critically Low Condition*//
    uint8_t deframe_arr[5];                                   //*Array to store string to serve scrolling functionality*//
    uint8_t i;                                                //**//
    bool HT1632_flag = false;
    uint32_t str_length, display_len = 4, loop, k, length; //**//
    uint32_t str_length = sizeof(str);                     //**//
    const nrf_drv_rtc_t rtc_instance = NRF_DRV_RTC_INSTANCE(2);
    float new_meas_value_in_mv = 0;
    uint16_t new_meas_value = 0;
    NRF_BLE_GATT_DEF(m_gatt);           /**< GATT module instance. */
    NRF_BLE_QWR_DEF(m_qwr);             /**< Context for the Queued Write module.*/
    BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */
    BLE_RTC_DEF(m_rtc);                 //**<RTC Module Instance**//
    BLE_BAS_DEF(m_bas);                 //**< Structure used to identify the battery service. **//
    APP_TIMER_DEF(m_battery_timer_id);  //**< Battery timer.**//
    APP_TIMER_DEF(m_adc_timer_id);      //**ADC Timer**//
    APP_TIMER_DEF(m_str_timer_id);
    static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */
    static uint32_t m_adc_evt_counter, battery_critical;     //**variable to count no. of events**//
    
    static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifiers. */
        {
            {BLE_UUID_DEVICE_INFORMATION_SERVICE, BLE_UUID_TYPE_BLE},
            {BLE_UUID_BATTERY_SERVICE, BLE_UUID_TYPE_BLE},
    };
    
    static nrf_saadc_value_t m_buffer_pool[2][SAMPLES_IN_BUFFER];
    
    uint32_t m_batt_current_voltage_mv = 0;       //The current, smoothed out, battery voltage
    uint8_t m_batt_percentage, conn_handle_value; //The current battery percentage calculated from voltage
    
    static void advertising_start(bool erase_bonds);
    
    /**@brief Callback function for asserts in the SoftDevice.
     *
     * @details This function will be called in case of an assert in the SoftDevice.
     *
     * @warning This handler is an example only and does not fit a final product. You need to analyze
     *          how your product is supposed to react in case of Assert.
     * @warning On assert from the SoftDevice, the system can only recover on reset.
     *
     * @param[in] line_num   Line number of the failing ASSERT call.
     * @param[in] file_name  File name of the failing ASSERT call.
     */
    void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name)
     {
      app_error_handler(DEAD_BEEF, line_num, p_file_name);
    }
    
    /**@brief Function for handling Peer Manager events.
     *
     * @param[in] p_evt  Peer Manager event.
     */
    static void pm_evt_handler(pm_evt_t const *p_evt) 
    {
      pm_handler_on_pm_evt(p_evt);
      pm_handler_flash_clean(p_evt);
    
      switch (p_evt->evt_id) {
      case PM_EVT_PEERS_DELETE_SUCCEEDED:
        advertising_start(false);
        break;
    
      default:
        break;
      }
    }
    
    //**Function for writing 8 bit data on to RAM**//
    void senddata_8bit(uint8_t address, uint8_t data) 
    {
      nrf_gpio_pin_clear(CS);
      ht1632_command(HT1632_ID_WR, 0x04); //1<<2);  // send ID: WRITE to RAM
      ht1632_command(address, 0x40);      //1<<6); // Send address
      writedatabits(data, 8);
      nrf_gpio_pin_set(CS);
    }
    
    /**function defining logic for sending command code**/
    void ht1632_command(uint8_t ID, uint8_t firstbit) 
    {
      while (firstbit) {
        nrf_gpio_pin_clear(WRITE);
        nrf_delay_us(1);
        if (ID & firstbit) {
          nrf_gpio_pin_set(DATA);
    
          nrf_delay_us(1);
    
        } else {
          nrf_gpio_pin_clear(DATA);
    
          nrf_delay_us(1);
        }
    
        nrf_gpio_pin_set(WRITE);
        nrf_delay_us(1);
        firstbit >>= 1;
      }
    }
    
    //**Writing one byte data on to LED Driver**//
    void writedatabits(uint8_t data, uint8_t count) 
    {
      while (count) {
        nrf_gpio_pin_clear(WRITE);
        nrf_delay_us(1);
        if (data & 1) {
          nrf_gpio_pin_set(DATA);
        } else {
          nrf_gpio_pin_clear(DATA);
        }
        nrf_gpio_pin_set(WRITE);
        nrf_delay_us(1);
        count--;
        data >>= 1;
      }
    }
    
    //**Function for clearing all leds on LED Driver**//
    void clearallbits(uint8_t data)
     {
      uint8_t i, address_var;
    
      for (i = 0; i <= 20; i++) {
        address_var = i * 2;
        senddata_8bit(address_var, data);
      }
    }
    
    //**Function for sending command**//
    void ht1632_sendcmd(uint8_t command) 
    {
      nrf_gpio_pin_clear(CS);
    
      nrf_delay_us(1);
      ht1632_command(HT1632_ID_CMD, 1 << 2); // send 3 bits of id: COMMMAND
      ht1632_command(command, 1 << 7);       // send the actual command
      ht1632_command(0, 1);
      nrf_gpio_pin_set(CS); /* one extra dont-care bit in commands. */
    
      nrf_delay_us(1);
    }
    //**All LEDS on and OFF Functionality using commands**//
    void blinker() 
    {
    
      ht1632_sendcmd(HT1632_CMD_BLON);
      nrf_delay_ms(250);
      ht1632_sendcmd(HT1632_CMD_BLOFF);
    }
    
    //** Gpio pins initializtion for ht1632 led driver**//
    void ht1632_gpio_init() 
    {
      nrf_gpio_cfg_output(CS);
      nrf_gpio_pin_set(CS);
      nrf_gpio_cfg_output(WRITE);
      nrf_gpio_pin_set(WRITE);
      nrf_gpio_cfg_output(DATA);
    }
    
    //**HT1632 LED Driver Initialization in master mode **//
    void ht1632_Init() 
    {
    
      ht1632_sendcmd(HT1632_CMD_SYSON); // Enable system
      ht1632_sendcmd(HT1632_CMD_LEDON); // LEDs on
      ht1632_sendcmd(HT1632_CMD_BLOFF);
      ht1632_sendcmd(HT1632_CMD_MSTMD);   // MASTER MODE
      ht1632_sendcmd(HT1632_CMD_RCCLK);   // master mode
      ht1632_sendcmd(HT1632_CMD_COMS00);  // com8, NMOS drivers
      ht1632_command(HT1632_CMD_PWM1, 8); // PWM duty cycle 1/16
    }
    //** Function for Sending single character**//
    int putChar(int x, int y, char c) 
    {
      uint8_t charIndex;
      uint8_t colData;
      uint8_t numCols;
      uint8_t addr;
      // uint8_t colsLeft = 0;
      uint8_t chipn0 = 1;
      if (c > 15) {
        // Regular characters
        // replace undisplayable characters with blank;
        if (c < 32 || c > 126) {
          charIndex = 0;
        } else {
          charIndex = c - 32;
        }
    
        numCols = Font5x21[charIndex][4];
        // get the number of columns this character uses
        for (uint8_t col = 0; col < 3; col++) {
          colData = Font5x21[charIndex][col];
          addr = chip_byte_address(x, y);
    
          senddata_8bit(addr, colData);
          x++;
        }
      }
    
      cursorX = x;
      cursorY = y;
      //return colsLeft;
    }
    
    //** Function for Sending string**//
    void putstring(uint8_t x, uint8_t y, char *str)
     {
    
      cursorX = x;
      cursorY = y;
      while (*str) {
        putChar(cursorX, y, *str++);
        cursorX += 1;
      }
    }
    
    //**Function for sending string of length 27 onto HT1632 LED Driver**//
    void send_message(char *message) 
    {
      if (HT1632_flag == false) {
        HT1632_flag = true;
    
        if (str_length > 5) {
          for (loop = 0; loop < str_length - 5; loop++) {
            for (k = 0; k <= display_len; k++) {
    
              deframe_arr[k] = message[k + loop];
            }
            k = 0;
            putstring(0, 0, deframe_arr);
            memset(deframe_arr, 0, 5);
            nrf_delay_ms(250);
          }
        }
      }
      nrf_delay_ms(1000);
      HT1632_flag = false;
    }
    
    //**Handler function for SAADC**//
    void saadc_callback(nrf_drv_saadc_evt_t const *p_event)
     {
      uint32_t value = 0, res;
      float config_param_ratio, vp, num;
    
      if (p_event->type == NRF_DRV_SAADC_EVT_DONE) {
        ret_code_t err_code;
    
        err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);
    
        int i;
        NRF_LOG_INFO("ADC event number: %d", (int)m_adc_evt_counter);
    
        for (i = 0; i < SAMPLES_IN_BUFFER; i++) {
          NRF_LOG_INFO("%d", p_event->data.done.p_buffer[i]);
          value = value + p_event->data.done.p_buffer[i];
          //The measurement has to be * (61/11) (voltage divider) and * 1200/1023 (ADC reference/resolution)
          new_meas_value = value / SAMPLES_IN_BUFFER;
        }
    
        NRF_LOG_INFO("ADC avg output: %d", new_meas_value);
    
        //** if The measurement has to be * (61/11) (voltage divider) and * 1200/1023 (ADC reference/resolution)**//
    
        //    m_batt_percentage = (( new_meas_value_in_mv-BATT_MIN_VOLTAGE_MV)*100) / (BATT_MAX_VOLTAGE_MV-BATT_MIN_VOLTAGE_MV);
    
        ++m_adc_evt_counter;
      }
    }
    
    /**@brief Function for performing battery measurement and updating the Battery Level characteristic
     *        in Battery Service.
     */
    static void battery_level_update(void) 
    {
      ret_code_t err_code;
    
      err_code = ble_bas_battery_level_update(&m_bas, m_batt_percentage, BLE_CONN_HANDLE_ALL);
      if ((err_code != NRF_SUCCESS) &&
          (err_code != NRF_ERROR_INVALID_STATE) &&
          (err_code != NRF_ERROR_RESOURCES) &&
          (err_code != NRF_ERROR_BUSY) &&
          (err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)) {
        APP_ERROR_HANDLER(err_code);
      }
    }
    
    /**@brief Function for handling the Battery measurement timer timeout.
     *
     * @details This function will be called each time the battery level measurement timer expires.
     *
     * @param[in] p_context  Pointer used for passing some arbitrary information (context) from the
     *                       app_start_timer() call to the timeout handler.
     */
    static void battery_level_meas_timeout_handler(void *p_context)
     {
      uint32_t err_code;
      UNUSED_PARAMETER(p_context);
      new_meas_value_in_mv = (new_meas_value * 3.6) / 1.024;
      m_batt_percentage = ((new_meas_value_in_mv - BATT_MIN_VOLTAGE_MV) * 100) / (BATT_MAX_VOLTAGE_MV - BATT_MIN_VOLTAGE_MV);
      if (m_batt_percentage <= 20) {
        send_message(str1);
      }
    
      //function display message "battery low n battery level" on ht1632//
      else {
        send_message(str2);
      }
    
      //function display message "battery fully charged n battery levl" on ht1632//
      battery_level_update();
    }
    
    /**@brief Function for triggering an ADC reading
     * The result will be processed in the ADC IRQ handler
     */
    static void adc_start(void *p_context) 
    {
      NRF_SAADC->TASKS_SAMPLE = 1;
    }
    
    void stringdisplay()
     {
      send_message(str);
    }
    
    /**@brief Function for the Timer initialization.
     *
     * @details Initializes the timer module. This creates and starts application timers.
     */
    static void timers_init(void) 
    {
      // Initialize timer module.
      ret_code_t err_code = app_timer_init();
      APP_ERROR_CHECK(err_code);
    
      // Create timers.
    
      err_code = app_timer_create(&m_str_timer_id,
    
          APP_TIMER_MODE_REPEATED,
          stringdisplay);
      APP_ERROR_CHECK(err_code);
    
      err_code = app_timer_create(&m_battery_timer_id,
          APP_TIMER_MODE_REPEATED,
          battery_level_meas_timeout_handler);
      APP_ERROR_CHECK(err_code);
    
      err_code = app_timer_create(&m_adc_timer_id,
          APP_TIMER_MODE_REPEATED,
          adc_start);
      APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for the GAP initialization.
     *
     * @details This function sets up all the necessary GAP (Generic Access Profile) parameters of the
     *          device including the device name, appearance, and the preferred connection parameters.
     */
    static void gap_params_init(void)
     {
      ret_code_t err_code;
      ble_gap_conn_params_t gap_conn_params;
      ble_gap_conn_sec_mode_t sec_mode;
    
      BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
    
      err_code = sd_ble_gap_device_name_set(&sec_mode,
          (const uint8_t *)DEVICE_NAME,
          strlen(DEVICE_NAME));
      APP_ERROR_CHECK(err_code);
    
      /* YOUR_JOB: Use an appearance value matching the application's use case.
           err_code = sd_ble_gap_appearance_set(BLE_APPEARANCE_);
           APP_ERROR_CHECK(err_code); */
    
      memset(&gap_conn_params, 0, sizeof(gap_conn_params));
    
      gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
      gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
      gap_conn_params.slave_latency = SLAVE_LATENCY;
      gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT;
    
      err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
      APP_ERROR_CHECK(err_code);
    }
    
    
    
    /**@brief Function for initializing the GATT module.
     */
    static void gatt_init(void) {
      ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, NULL);
      APP_ERROR_CHECK(err_code);
    }
    
    
    
    /**@brief Function for handling Queued Write Module errors.
     *
     * @details A pointer to this function will be passed to each service which may need to inform the
     *          application about an error.
     *
     * @param[in]   nrf_error   Error code containing information about what went wrong.
     */
    static void nrf_qwr_error_handler(uint32_t nrf_error)
     {
      APP_ERROR_HANDLER(nrf_error);
    }
    
    
    
    //**Function for raising notification**//
    uint32_t our_rtc_characteristic_update(ble_rtc_t *p_rtc_service, uint32_t evt_update)
     {
      uint32_t err_code;
      if (p_rtc_service->conn_handle != BLE_CONN_HANDLE_INVALID) {
    
        uint8_t temp;
        uint16_t len = 4;
        ble_gatts_hvx_params_t hvx_params;
        uint8_t buffer[sizeof(evt_update)];
        memcpy(buffer, &evt_update, len);
        memset(&hvx_params, 0, sizeof(hvx_params));
    
        hvx_params.handle = p_rtc_service->rtc_char_handles.value_handle;
        hvx_params.type = BLE_GATT_HVX_NOTIFICATION;
        hvx_params.offset = 0;
        hvx_params.p_len = &len;
        hvx_params.p_data = buffer;
    
        err_code = sd_ble_gatts_hvx(p_rtc_service->conn_handle, &hvx_params);
      } else {
        err_code = NRF_ERROR_INVALID_STATE;
      }
    
      return err_code;
    }
    
    
    //**Function for handling cc write event**//
    
    static void rtc_cc_write_handler(uint16_t conn_handle, ble_rtc_t *p_rtc_service, uint32_t value) 
    {
    
      printf("cc value\r\n");
      uint32_t cc_set, capturedval_rtc2;
      uint32_t err_code;
      if (value > 0)
    
      {
        value &= 0xffffffff;
        capturedval_rtc2 = NRF_RTC2->COUNTER;
        printf("counter value %d\n", capturedval_rtc2);
        cc_set = capturedval_rtc2 + value;
        printf("cc value  %d\n", cc_set);
    
        // Set compare channel to trigger interrupt after COMPARE_COUNTERTIME seconds
        err_code = nrf_drv_rtc_cc_set(&rtc_instance, 1, cc_set, true);
        APP_ERROR_CHECK(err_code);
    
        //**Notification test**//
        our_rtc_characteristic_update(&m_rtc, value);
        nrf_gpio_pin_toggle(LED_2);
    
        //Power on RTC instance
        nrf_drv_rtc_enable(&rtc_instance);
      }
    }
    
    /**@brief Function for initializing services that will be used by the application.
     */
    static void services_init(void)
     {
      ret_code_t err_code;
      nrf_ble_qwr_init_t qwr_init = {0};
      ble_rtc_init_t init_rtc = {0}; //Initializing rtc_write_handler with 0**//
      ble_bas_init_t bas_init;
      // Initialize Queued Write Module.
      qwr_init.error_handler = nrf_qwr_error_handler;
    
      err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
      APP_ERROR_CHECK(err_code);
    
      init_rtc.rtc_write_handler = rtc_cc_write_handler; //**assigning cc_write handler to the rtc_write_handler(member of ble_rtc_init_t)**//
      err_code = rtc_service_init(&m_rtc, &init_rtc);    //**RTC Service Initialization**//
      APP_ERROR_CHECK(err_code);
    
      // Initialize Battery Service.
      memset(&bas_init, 0, sizeof(bas_init));
    
      bas_init.evt_handler = NULL;
      bas_init.support_notification = true;
      bas_init.p_report_ref = NULL;
      bas_init.initial_batt_level = 100;
    
      // Here the sec level for the Battery Service can be changed/increased.
      bas_init.bl_rd_sec = SEC_OPEN;
      bas_init.bl_cccd_wr_sec = SEC_OPEN;
      bas_init.bl_report_rd_sec = SEC_OPEN;
    
      err_code = ble_bas_init(&m_bas, &bas_init);
      APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for handling the Connection Parameters Module.
     *
     * @details This function will be called for all events in the Connection Parameters Module which
     *          are passed to the application.
     *          @note All this function does is to disconnect. This could have been done by simply
     *                setting the disconnect_on_fail config parameter, but instead we use the event
     *                handler mechanism to demonstrate its use.
     *
     * @param[in] p_evt  Event received from the Connection Parameters Module.
     */
    static void on_conn_params_evt(ble_conn_params_evt_t *p_evt)
     {
      ret_code_t err_code;
    
      if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED) {
        err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
        APP_ERROR_CHECK(err_code);
      }
    }
    
    /**@brief Function for handling a Connection Parameters error.
     *
     * @param[in] nrf_error  Error code containing information about what went wrong.
     */
    static void conn_params_error_handler(uint32_t nrf_error) 
    {
      APP_ERROR_HANDLER(nrf_error);
    }
    
    /**@brief Function for initializing the Connection Parameters module.
     */
    static void conn_params_init(void) 
    {
      ret_code_t err_code;
      ble_conn_params_init_t cp_init;
    
      memset(&cp_init, 0, sizeof(cp_init));
    
      cp_init.p_conn_params = NULL;
      cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
      cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY;
      cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT;
      cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID;
      cp_init.disconnect_on_fail = false;
      cp_init.evt_handler = on_conn_params_evt;
      cp_init.error_handler = conn_params_error_handler;
    
      err_code = ble_conn_params_init(&cp_init);
      APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for starting timers.
     */
    static void application_timers_start(void)
     {
      ret_code_t err_code;
    
      // Start application timers.
    
      err_code = app_timer_start(m_str_timer_id, STRING_DISPLAY_INTERVAL, NULL);
      APP_ERROR_CHECK(err_code);
      err_code = app_timer_start(m_adc_timer_id, APP_TIMER_TICKS(BATT_MEAS_INTERVAL_MS), NULL);
      APP_ERROR_CHECK(err_code);
      err_code = app_timer_start(m_battery_timer_id, BATTERY_LEVEL_MEAS_INTERVAL, NULL);
      APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for putting the chip into sleep mode.
     *
     * @note This function will not return.
     */
    static void sleep_mode_enter(void) {
      ret_code_t err_code;
    
      err_code = bsp_indication_set(BSP_INDICATE_IDLE);
      APP_ERROR_CHECK(err_code);
    
     
    }
    
    /**@brief Function for handling advertising events.
     *
     * @details This function will be called for advertising events which are passed to the application.
     *
     * @param[in] ble_adv_evt  Advertising event.
     */
    static void on_adv_evt(ble_adv_evt_t ble_adv_evt) 
    {
      ret_code_t err_code;
    
      switch (ble_adv_evt) {
      case BLE_ADV_EVT_FAST:
        NRF_LOG_INFO("Fast advertising.");
        err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
        APP_ERROR_CHECK(err_code);
        break;
    
      case BLE_ADV_EVT_IDLE:
        sleep_mode_enter();
        break;
    
      default:
        break;
      }
    }
    
    /**@brief Function for handling BLE events.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     * @param[in]   p_context   Unused.
     */
    static void ble_evt_handler(ble_evt_t const *p_ble_evt, void *p_context) 
    {
      ret_code_t err_code = NRF_SUCCESS;
    
      switch (p_ble_evt->header.evt_id) {
      case BLE_GAP_EVT_DISCONNECTED:
        NRF_LOG_INFO("Disconnected.");
        // LED indication will be changed when advertising starts.
        break;
    
      case BLE_GAP_EVT_CONNECTED:
        NRF_LOG_INFO("Connected.");
        err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
        APP_ERROR_CHECK(err_code);
        m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
        err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
        APP_ERROR_CHECK(err_code);
        break;
    
      case BLE_GAP_EVT_PHY_UPDATE_REQUEST: {
        NRF_LOG_DEBUG("PHY update request.");
        ble_gap_phys_t const phys =
            {
                .rx_phys = BLE_GAP_PHY_AUTO,
                .tx_phys = BLE_GAP_PHY_AUTO,
            };
        err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
        APP_ERROR_CHECK(err_code);
      } break;
    
      case BLE_GATTC_EVT_TIMEOUT:
        // Disconnect on GATT Client timeout event.
        NRF_LOG_DEBUG("GATT Client Timeout.");
        err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
            BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
        APP_ERROR_CHECK(err_code);
        break;
    
      case BLE_GATTS_EVT_TIMEOUT:
        // Disconnect on GATT Server timeout event.
        NRF_LOG_DEBUG("GATT Server Timeout.");
        err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
            BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
        APP_ERROR_CHECK(err_code);
        break;
    
      default:
        // No implementation needed.
        break;
      }
    }
    
    /**@brief Function for initializing the BLE stack.
     *
     * @details Initializes the SoftDevice and the BLE event interrupt.
     */
    static void ble_stack_init(void) 
    {
      ret_code_t err_code;
    
      err_code = nrf_sdh_enable_request();
      APP_ERROR_CHECK(err_code);
    
      // Configure the BLE stack using the default settings.
      // Fetch the start address of the application RAM.
      uint32_t ram_start = 0;
      err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
      APP_ERROR_CHECK(err_code);
    
      // Enable BLE stack.
      err_code = nrf_sdh_ble_enable(&ram_start);
      APP_ERROR_CHECK(err_code);
    
      // Register a handler for BLE events.
      NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
    }
    
    /**@brief Function for the Peer Manager initialization.
     */
    static void peer_manager_init(void) 
    {
      ble_gap_sec_params_t sec_param;
      ret_code_t err_code;
    
      err_code = pm_init();
      APP_ERROR_CHECK(err_code);
    
      memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));
    
      // Security parameters to be used for all security procedures.
      sec_param.bond = SEC_PARAM_BOND;
      sec_param.mitm = SEC_PARAM_MITM;
      sec_param.lesc = SEC_PARAM_LESC;
      sec_param.keypress = SEC_PARAM_KEYPRESS;
      sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES;
      sec_param.oob = SEC_PARAM_OOB;
      sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE;
      sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE;
      sec_param.kdist_own.enc = 1;
      sec_param.kdist_own.id = 1;
      sec_param.kdist_peer.enc = 1;
      sec_param.kdist_peer.id = 1;
    
      err_code = pm_sec_params_set(&sec_param);
      APP_ERROR_CHECK(err_code);
    
      err_code = pm_register(pm_evt_handler);
      APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Clear bond information from persistent storage.
     */
    static void delete_bonds(void)
     {
      ret_code_t err_code;
    
      NRF_LOG_INFO("Erase bonds!");
    
      err_code = pm_peers_delete();
      APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for handling events from the BSP module.
     *
     * @param[in]   event   Event generated when button is pressed.
     */
    static void bsp_event_handler(bsp_event_t event) 
    {
      ret_code_t err_code;
    
      switch (event) {
      case BSP_EVENT_SLEEP:
        sleep_mode_enter();
        break; // BSP_EVENT_SLEEP
    
      case BSP_EVENT_DISCONNECT:
        err_code = sd_ble_gap_disconnect(m_conn_handle,
            BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
        if (err_code != NRF_ERROR_INVALID_STATE) {
          APP_ERROR_CHECK(err_code);
        }
        break; // BSP_EVENT_DISCONNECT
    
      case BSP_EVENT_WHITELIST_OFF:
        if (m_conn_handle == BLE_CONN_HANDLE_INVALID) {
          err_code = ble_advertising_restart_without_whitelist(&m_advertising);
          if (err_code != NRF_ERROR_INVALID_STATE) {
            APP_ERROR_CHECK(err_code);
          }
        }
        break; // BSP_EVENT_KEY_0
    
      default:
        break;
      }
    }
    
    /**@brief Function for initializing the Advertising functionality.
     */
    static void advertising_init(void)
     {
      ret_code_t err_code;
      ble_advertising_init_t init;
      ble_uuid_t adv_uuids[] = {{BLE_UUID_RTC_SERVICE, BLE_UUID_TYPE_VENDOR_BEGIN}}; //**creating a array variable and add service UUID and it's TYPE to it.**//
      memset(&init, 0, sizeof(init));
    
      init.advdata.name_type = BLE_ADVDATA_FULL_NAME;
      init.advdata.include_appearance = true;
      init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
      init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
      init.advdata.uuids_complete.p_uuids = m_adv_uuids;
      init.srdata.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]); //**Adding Service to the advertising packet**//
      init.srdata.uuids_complete.p_uuids = adv_uuids;
    
      init.config.ble_adv_fast_enabled = true;
      init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
      init.config.ble_adv_fast_timeout = APP_ADV_DURATION;
    
      init.evt_handler = on_adv_evt;
    
      err_code = ble_advertising_init(&m_advertising, &init);
      APP_ERROR_CHECK(err_code);
    
      ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
    }
    
    /**@brief Function for initializing buttons and leds.
     *
     * @param[out] p_erase_bonds  Will be true if the clear bonding button was pressed to wake the application up.
     */
    static void buttons_leds_init(bool *p_erase_bonds) 
    {
      ret_code_t err_code;
      bsp_event_t startup_event;
    
      err_code = bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS, bsp_event_handler);
      APP_ERROR_CHECK(err_code);
    
      err_code = bsp_btn_ble_init(NULL, &startup_event);
      APP_ERROR_CHECK(err_code);
    
      *p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA);
    }
    
    /**@brief Function for initializing the nrf log module.
     */
    static void log_init(void) 
    {
      ret_code_t err_code = NRF_LOG_INIT(NULL);
      APP_ERROR_CHECK(err_code);
    
      NRF_LOG_DEFAULT_BACKENDS_INIT();
    }
    
    /**@brief Function for initializing power management.
     */
    static void power_management_init(void)
     {
      ret_code_t err_code;
      err_code = nrf_pwr_mgmt_init();
      APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for handling the idle state (main loop).
     *
     * @details If there is no pending log operation, then sleep until next the next event occurs.
     */
    static void idle_state_handle(void)
     {
    
      if (NRF_LOG_PROCESS() == false) {
        nrf_pwr_mgmt_run();
      }
    }
    
    /**@brief Function for starting advertising.
     */
    static void advertising_start(bool erase_bonds) 
    {
      if (erase_bonds == true) {
        delete_bonds();
        // Advertising is started by PM_EVT_PEERS_DELETED_SUCEEDED event
      } else {
        ret_code_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
    
        APP_ERROR_CHECK(err_code);
      }
    }
    
    /** @brief: Function for handling the RTC0 interrupts.
     * Triggered on TICK and COMPARE0 match.
     */
    static void rtc_handler(nrf_drv_rtc_int_type_t int_type) 
    {
      if (int_type == NRF_DRV_RTC_INT_COMPARE1) {
        printf("compared\n");
        nrf_gpio_pin_toggle(20);
    
        printf("toggle occured\n");
      } else if (int_type == NRF_DRV_RTC_INT_TICK) {
        nrf_gpio_pin_toggle(17);
      }
    }
    
    //**RTC2 Initialization**//
    
    void rtc2_init() 
    {
      uint32_t err_code;
      nrf_drv_rtc_config_t config = NRF_DRV_RTC_DEFAULT_CONFIG;
      config.prescaler = 4095;
      err_code = nrf_drv_rtc_init(&rtc_instance, &config, rtc_handler);
      APP_ERROR_CHECK(err_code);
    }
    
    //**SAADC Initialization**//
    void saadc_init(void)
     {
      ret_code_t err_code;
      nrf_saadc_channel_config_t channel_config =
          NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
    
      err_code = nrf_drv_saadc_init(NULL, saadc_callback);
      APP_ERROR_CHECK(err_code);
    
      err_code = nrf_drv_saadc_channel_init(0, &channel_config);
      APP_ERROR_CHECK(err_code);
      err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER);
      APP_ERROR_CHECK(err_code);
    
      err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1], SAMPLES_IN_BUFFER);
      APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for application main entry.
     */
    int main(void)
    
    {
      uint32_t j;
      bool erase_bonds;
      // Initialize.
    
      log_init();
      ht1632_gpio_init();
      ht1632_Init();
      clearallbits(0x00);
      timers_init();
      buttons_leds_init(&erase_bonds);
      power_management_init();
      ble_stack_init();
      gap_params_init();
      gatt_init();
      rtc2_init();
      services_init();
      advertising_init();
      saadc_init();
      conn_params_init();
      peer_manager_init();
    
      // Start execution.
      NRF_LOG_INFO("Template example started.");
      application_timers_start();
      advertising_start(erase_bonds);
      clearallbits(0x00);
      // Enter main loop.
      for (;;)
      {
    
        idle_state_handle();
      }
    }
    
    /**
     * @}
     */

    Hi,

    Thank you for the response.And yes,From my description I tried to explain the issue concerned about connect and disconnect proccess.Above I have inserted source code of my application.I also gave a try using scheduler but if I just enable APP_TIMER_CONFIG_USE_SCHEDULER in sdk_config.h I coudn't find device advertising on nRFConnect for Mobile.

    NOTE: RTC2_Handler is also being used by the application.

    Thank you.

  • I'm not sure exactly how you measure that the connect/disconnect is delayed, but most likely the issues you are seeing is caused by your use of nrf_delay_ms() in function send_message(). From what I can see, the loop will loop over 20 times, blocking 250 ms for each loop, totalling over 5 seconds. At the end of the function, you also have another delay of 1 second. Since this function is called every time battery_level_meas_timeout_handler() is executed (every 2 seconds), you will get interrupt starvation in the application.

  • Hi,

    sorry for late reply.Thank you so much your answer was helpful to me.And exactly after commenting out delays it is working fine.But if i need to have some manditory delay.How can i deal with it?

    Thank you once again!

  • Normally if you want something to happen at a specific point of time in the future, you setup a timer. When the timer timeouts, a callback handler will be called where you can perform the desired task. Please have a look at the application timer tutorial.

Related